Пример #1
0
def test_get_extra_radiation_nrel_numba(times):
    with warnings.catch_warnings():
        # don't warn on method reload or num threads
        warnings.simplefilter("ignore")
        result = irradiance.get_extra_radiation(times,
                                                method='nrel',
                                                how='numba',
                                                numthreads=4)
        # and reset to no-numba state
        irradiance.get_extra_radiation(times, method='nrel')
    assert_allclose(result,
                    [1322.332316, 1322.296282, 1322.261205, 1322.227091])
Пример #2
0
    def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
        """
        Estimates irradiance from cloud cover in the following steps:

        1. Determine transmittance using a function of cloud cover e.g.
           :py:meth:`~ForecastModel.cloud_cover_to_transmittance_linear`
        2. Calculate GHI, DNI, DHI using the
           :py:func:`pvlib.irradiance.liujordan` model

        Parameters
        ----------
        cloud_cover : Series

        Returns
        -------
        irradiance : DataFrame
            Columns include ghi, dni, dhi
        """
        # in principle, get_solarposition could use the forecast
        # pressure, temp, etc., but the cloud cover forecast is not
        # accurate enough to justify using these minor corrections
        solar_position = self.location.get_solarposition(cloud_cover.index)
        dni_extra = get_extra_radiation(cloud_cover.index)
        airmass = self.location.get_airmass(cloud_cover.index)

        transmittance = self.cloud_cover_to_transmittance_linear(
            cloud_cover, **kwargs)

        irrads = liujordan(solar_position['apparent_zenith'],
                           transmittance,
                           airmass['airmass_absolute'],
                           dni_extra=dni_extra)
        irrads = irrads.fillna(0)

        return irrads
def test_get_extra_radiation_nrel_numba(times):
    result = irradiance.get_extra_radiation(times,
                                            method='nrel',
                                            how='numba',
                                            numthreads=8)
    assert_allclose(result,
                    [1322.332316, 1322.296282, 1322.261205, 1322.227091])
Пример #4
0
    def cloud_cover_to_irradiance_liujordan(self, cloud_cover, **kwargs):
        """
        Estimates irradiance from cloud cover in the following steps:

        1. Determine transmittance using a function of cloud cover e.g.
           :py:meth:`~ForecastModel.cloud_cover_to_transmittance_linear`
        2. Calculate GHI, DNI, DHI using the
           :py:func:`pvlib.irradiance.liujordan` model

        Parameters
        ----------
        cloud_cover : Series

        Returns
        -------
        irradiance : DataFrame
            Columns include ghi, dni, dhi
        """
        # in principle, get_solarposition could use the forecast
        # pressure, temp, etc., but the cloud cover forecast is not
        # accurate enough to justify using these minor corrections
        solar_position = self.location.get_solarposition(cloud_cover.index)
        dni_extra = get_extra_radiation(cloud_cover.index)
        airmass = self.location.get_airmass(cloud_cover.index)

        transmittance = self.cloud_cover_to_transmittance_linear(cloud_cover,
                                                                 **kwargs)

        irrads = liujordan(solar_position['apparent_zenith'],
                           transmittance, airmass['airmass_absolute'],
                           dni_extra=dni_extra)
        irrads = irrads.fillna(0)

        return irrads
Пример #5
0
def simulate_sun_positions_by_station(station_index, solar_position_method,
                                      days, lead_times, latitudes, longitudes):
    """
    This is the worker function of calculating sun positions at a specified station index. This function should
    be called from the parallel version of this function, `simulate_sun_positions`.

    Direct use of this function is discouraged. Please use the parallel version of this fucntion,
    `simulate_sun_positions`.

    :param station_index: A station index for simulation
    :param days: See `simulate_sun_positions`
    :param lead_times: See `simulate_sun_positions`
    :param latitudes: See `simulate_sun_positions`
    :param longitudes: See `simulate_sun_positions`
    :param solar_position_method: See `simulate_sun_positions`
    :return: A list with DNI, air mass, zenith, apparent zenith, and azimuth.
    """

    # Initialization
    num_lead_times, num_days = len(lead_times), len(days)

    dni_extra = np.zeros((num_lead_times, num_days))
    air_mass = np.zeros((num_lead_times, num_days))
    zenith = np.zeros((num_lead_times, num_days))
    apparent_zenith = np.zeros((num_lead_times, num_days))
    azimuth = np.zeros((num_lead_times, num_days))

    # Determine the current location
    current_location = location.Location(latitude=latitudes[station_index],
                                         longitude=longitudes[station_index])

    for day_index in range(num_days):
        for lead_time_index in range(num_lead_times):

            # Determine the current time
            current_posix = days[day_index] + lead_times[lead_time_index]
            current_time = pd.Timestamp(current_posix, tz="UTC", unit='s')

            # Calculate sun position
            solar_position = current_location.get_solarposition(
                current_time, method=solar_position_method, numthreads=1)

            # Calculate extraterrestrial DNI
            dni_extra[lead_time_index,
                      day_index] = irradiance.get_extra_radiation(current_time)

            # Calculate air mass
            air_mass[lead_time_index,
                     day_index] = atmosphere.get_relative_airmass(
                         solar_position["apparent_zenith"])

            # Store other keys
            zenith[lead_time_index, day_index] = solar_position["zenith"]
            apparent_zenith[lead_time_index,
                            day_index] = solar_position["apparent_zenith"]
            azimuth[lead_time_index, day_index] = solar_position["azimuth"]

    return [dni_extra, air_mass, zenith, apparent_zenith, azimuth]
Пример #6
0
def _solpos_dni_extra(observation, values):
    solar_position = pvmodel.calculate_solar_position(
        observation.site.latitude, observation.site.longitude,
        observation.site.elevation, values.index)
    dni_extra = get_extra_radiation(values.index)
    timestamp_flag = _validate_timestamp(observation, values)
    night_flag = validator.check_irradiance_day_night(solar_position['zenith'],
                                                      _return_mask=True)
    return solar_position, dni_extra, timestamp_flag, night_flag
Пример #7
0
def _get_extra_radiation_shim(datetime_or_doy, solar_constant=1366.1,
    method='spencer', epoch_year=2014, **kwargs):
    if method == 'spencer':
        if not isinstance(datetime_or_doy, (float, int)):
            dayofyear = datetime_or_doy.timetuple().tm_yday
        else:
            dayofyear = datetime_or_doy
        B = (2.*pi/365.)*(dayofyear - 1)
        RoverR0sqrd = (1.00011 + 0.034221*cos(B) + 0.00128*sin(B) +
        0.000719*cos(2.0*B) + 7.7e-05*sin(2.0*B))

        Ea = solar_constant * RoverR0sqrd
        return Ea
    from pvlib.irradiance import get_extra_radiation
    return get_extra_radiation(datetime_or_doy=datetime_or_doy,
                              solar_constant=solar_constant,
                              method=method,
                              epoch_year=epoch_year,
                              **kwargs)
Пример #8
0
def _get_poa(data, solar_position):
    """
    Return the radiation adjusted to 
    Plane of Array (SkyDiffuse, GroundDiffuse, Total).
    """

    extra_radiation = get_extra_radiation(data.data.index)

    # Best orientation for pv system
    surface_tilt = _surface_tilt(data.latitude)
    surface_azimuth = _surface_azimuth(data.latitude)

    # Sky Diffuse radiation (From PvLib)
    poa_diffuse = haydavies(surface_tilt=surface_tilt,
                            surface_azimuth=surface_azimuth,
                            dhi=data.data['Gd(h)'],
                            dni=data.data['Gb(n)'],
                            dni_extra=extra_radiation,
                            solar_zenith=solar_position.apparent_zenith,
                            solar_azimuth=solar_position.azimuth)

    # Ground Diffuse radiation (From PvLib)
    poa_ground = get_ground_diffuse(data.latitude,
                                    data.data['G(h)'],
                                    surface_type='urban')

    # Angle of incidence at best orientation
    _aoi = aoi(surface_tilt=surface_tilt,
               surface_azimuth=surface_azimuth,
               solar_zenith=solar_position.apparent_zenith,
               solar_azimuth=solar_position.apparent_zenith)

    # Total radiation at plane of the pv array.
    poa_total = poa_components(aoi=_aoi,
                               dni=data.data['Gb(n)'],
                               poa_sky_diffuse=poa_diffuse,
                               poa_ground_diffuse=poa_ground)

    return poa_total, _aoi
Пример #9
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
Пример #10
0
def sun_extraradiation(dates=None, daydate=_day, solar_constant=1366.1,
                       method='spencer', timezone=_timezone):
    """ Extraterrestrial radiation (W.m2) at the top of the earth atmosphere

        Args:
            dates: a pandas.DatetimeIndex specifying the dates at which output
            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).
            solar_constant: (float)
            method: one method provided by pvlib
            timezone: a string identifying the timezone to be associated to dates if
             dates is not already localised.
    """
    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

    return get_extra_radiation(times, solar_constant=solar_constant, method=method)
Пример #11
0
    def get_clearsky(self,
                     times,
                     model='ineichen',
                     solar_position=None,
                     dni_extra=None,
                     **kwargs):
        """
        Calculate the clear sky estimates of GHI, DNI, and/or DHI
        at this location.

        Parameters
        ----------
        times: DatetimeIndex
        model: str, default 'ineichen'
            The clear sky model to use. Must be one of
            'ineichen', 'haurwitz', 'simplified_solis'.
        solar_position : None or DataFrame, default None
            DataFrame with columns 'apparent_zenith', 'zenith',
            'apparent_elevation'.
        dni_extra: None or numeric, default None
            If None, will be calculated from times.

        kwargs
            Extra parameters passed to the relevant functions. Climatological
            values are assumed in many cases. See source code for details!

        Returns
        -------
        clearsky : DataFrame
            Column names are: ``ghi, dni, dhi``.
        """
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(times)

        try:
            pressure = kwargs.pop('pressure')
        except KeyError:
            pressure = atmosphere.alt2pres(self.altitude)

        if solar_position is None:
            solar_position = self.get_solarposition(times,
                                                    pressure=pressure,
                                                    **kwargs)

        apparent_zenith = solar_position['apparent_zenith']
        apparent_elevation = solar_position['apparent_elevation']

        if model == 'ineichen':
            try:
                linke_turbidity = kwargs.pop('linke_turbidity')
            except KeyError:
                interp_turbidity = kwargs.pop('interp_turbidity', True)
                linke_turbidity = clearsky.lookup_linke_turbidity(
                    times,
                    self.latitude,
                    self.longitude,
                    interp_turbidity=interp_turbidity)

            try:
                airmass_absolute = kwargs.pop('airmass_absolute')
            except KeyError:
                airmass_absolute = self.get_airmass(
                    times, solar_position=solar_position)['airmass_absolute']

            cs = clearsky.ineichen(apparent_zenith,
                                   airmass_absolute,
                                   linke_turbidity,
                                   altitude=self.altitude,
                                   dni_extra=dni_extra,
                                   **kwargs)
        elif model == 'haurwitz':
            cs = clearsky.haurwitz(apparent_zenith)
        elif model == 'simplified_solis':
            cs = clearsky.simplified_solis(apparent_elevation,
                                           pressure=pressure,
                                           dni_extra=dni_extra,
                                           **kwargs)
        else:
            raise ValueError(
                '{} is not a valid clear sky model. Must be '
                'one of ineichen, simplified_solis, haurwitz'.format(model))

        return cs
Пример #12
0
    def get_irradiance(self, surface_tilt, surface_azimuth,
                       solar_zenith, solar_azimuth, dni, ghi, dhi,
                       dni_extra=None, airmass=None, model='haydavies',
                       **kwargs):
        """
        Uses the :func:`irradiance.get_total_irradiance` function to
        calculate the plane of array irradiance components on a tilted
        surface defined by the input data and ``self.albedo``.

        For a given set of solar zenith and azimuth angles, the
        surface tilt and azimuth parameters are typically determined
        by :py:meth:`~SingleAxisTracker.singleaxis`.

        Parameters
        ----------
        surface_tilt : numeric
            Panel tilt from horizontal.
        surface_azimuth : numeric
            Panel azimuth from north
        solar_zenith : numeric
            Solar zenith angle.
        solar_azimuth : numeric
            Solar azimuth angle.
        dni : float or Series
            Direct Normal Irradiance
        ghi : float or Series
            Global horizontal irradiance
        dhi : float or Series
            Diffuse horizontal irradiance
        dni_extra : float or Series, default None
            Extraterrestrial direct normal irradiance
        airmass : float or Series, default None
            Airmass
        model : String, default 'haydavies'
            Irradiance model.

        **kwargs
            Passed to :func:`irradiance.total_irrad`.

        Returns
        -------
        poa_irradiance : DataFrame
            Column names are: ``total, beam, sky, ground``.
        """

        # not needed for all models, but this is easier
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(solar_zenith.index)

        if airmass is None:
            airmass = atmosphere.get_relative_airmass(solar_zenith)

        return irradiance.get_total_irradiance(surface_tilt,
                                               surface_azimuth,
                                               solar_zenith,
                                               solar_azimuth,
                                               dni, ghi, dhi,
                                               dni_extra=dni_extra,
                                               airmass=airmass,
                                               model=model,
                                               albedo=self.albedo,
                                               **kwargs)
Пример #13
0
def test_bird():
    """Test Bird/Hulstrom Clearsky Model"""
    times = pd.date_range(start='1/1/2015 0:00', end='12/31/2015 23:00',
                          freq='H')
    tz = -7  # test timezone
    gmt_tz = pytz.timezone('Etc/GMT%+d' % -(tz))
    times = times.tz_localize(gmt_tz)  # set timezone
    # match test data from BIRD_08_16_2012.xls
    latitude = 40.
    longitude = -105.
    press_mB = 840.
    o3_cm = 0.3
    h2o_cm = 1.5
    aod_500nm = 0.1
    aod_380nm = 0.15
    b_a = 0.85
    alb = 0.2
    eot = solarposition.equation_of_time_spencer71(times.dayofyear)
    hour_angle = solarposition.hour_angle(times, longitude, eot) - 0.5 * 15.
    declination = solarposition.declination_spencer71(times.dayofyear)
    zenith = solarposition.solar_zenith_analytical(
        np.deg2rad(latitude), np.deg2rad(hour_angle), declination
    )
    zenith = np.rad2deg(zenith)
    airmass = atmosphere.get_relative_airmass(zenith, model='kasten1966')
    etr = irradiance.get_extra_radiation(times)
    # test Bird with time series data
    field_names = ('dni', 'direct_horizontal', 'ghi', 'dhi')
    irrads = clearsky.bird(
        zenith, airmass, aod_380nm, aod_500nm, h2o_cm, o3_cm, press_mB * 100.,
        etr, b_a, alb
    )
    Eb, Ebh, Gh, Dh = (irrads[_] for _ in field_names)
    clearsky_path = os.path.dirname(os.path.abspath(__file__))
    pvlib_path = os.path.dirname(clearsky_path)
    data_path = os.path.join(pvlib_path, 'data', 'BIRD_08_16_2012.csv')
    testdata = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna()
    testdata.index = times[1:48]
    assert np.allclose(testdata['DEC'], np.rad2deg(declination[1:48]))
    assert np.allclose(testdata['EQT'], eot[1:48], rtol=1e-4)
    assert np.allclose(testdata['Hour Angle'], hour_angle[1:48])
    assert np.allclose(testdata['Zenith Ang'], zenith[1:48])
    dawn = zenith < 88.
    dusk = testdata['Zenith Ang'] < 88.
    am = pd.Series(np.where(dawn, airmass, 0.), index=times).fillna(0.0)
    assert np.allclose(
        testdata['Air Mass'].where(dusk, 0.), am[1:48], rtol=1e-3
    )
    direct_beam = pd.Series(np.where(dawn, Eb, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Direct Beam'].where(dusk, 0.), direct_beam[1:48], rtol=1e-3
    )
    direct_horz = pd.Series(np.where(dawn, Ebh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Direct Hz'].where(dusk, 0.), direct_horz[1:48], rtol=1e-3
    )
    global_horz = pd.Series(np.where(dawn, Gh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Global Hz'].where(dusk, 0.), global_horz[1:48], rtol=1e-3
    )
    diffuse_horz = pd.Series(np.where(dawn, Dh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3
    )
    # test keyword parameters
    irrads2 = clearsky.bird(
        zenith, airmass, aod_380nm, aod_500nm, h2o_cm, dni_extra=etr
    )
    Eb2, Ebh2, Gh2, Dh2 = (irrads2[_] for _ in field_names)
    clearsky_path = os.path.dirname(os.path.abspath(__file__))
    pvlib_path = os.path.dirname(clearsky_path)
    data_path = os.path.join(pvlib_path, 'data', 'BIRD_08_16_2012_patm.csv')
    testdata2 = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna()
    testdata2.index = times[1:48]
    direct_beam2 = pd.Series(np.where(dawn, Eb2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Direct Beam'].where(dusk, 0.), direct_beam2[1:48], rtol=1e-3
    )
    direct_horz2 = pd.Series(np.where(dawn, Ebh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Direct Hz'].where(dusk, 0.), direct_horz2[1:48], rtol=1e-3
    )
    global_horz2 = pd.Series(np.where(dawn, Gh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Global Hz'].where(dusk, 0.), global_horz2[1:48], rtol=1e-3
    )
    diffuse_horz2 = pd.Series(np.where(dawn, Dh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Dif Hz'].where(dusk, 0.), diffuse_horz2[1:48], rtol=1e-3
    )
    # test scalars just at noon
    # XXX: calculations start at 12am so noon is at index = 12
    irrads3 = clearsky.bird(
        zenith[12], airmass[12], aod_380nm, aod_500nm, h2o_cm, dni_extra=etr[12]
    )
    Eb3, Ebh3, Gh3, Dh3 = (irrads3[_] for _ in field_names)
    # XXX: testdata starts at 1am so noon is at index = 11
    np.allclose(
        [Eb3, Ebh3, Gh3, Dh3],
        testdata2[['Direct Beam', 'Direct Hz', 'Global Hz', 'Dif Hz']].iloc[11],
        rtol=1e-3)
    return pd.DataFrame({'Eb': Eb, 'Ebh': Ebh, 'Gh': Gh, 'Dh': Dh}, index=times)
Пример #14
0
 def _toa_radiation():
     toa = get_extra_radiation(elevation.index, SOLAR_CONSTANT) * np.sin(
         elevation.values * np.pi / 180)
     toa[toa < 0] = 0
     return toa
Пример #15
0
def test_get_extra_radiation(input, expected, method):
    out = irradiance.get_extra_radiation(input)
    assert_allclose(out, expected, atol=1)
Пример #16
0
def test_get_extra_radiation_epoch_year():
    out = irradiance.get_extra_radiation(doy, method='nrel', epoch_year=2012)
    assert_allclose(out, 1382.4926804890767, atol=0.1)
Пример #17
0
def test_get_extra_radiation(input, expected, method):
    out = irradiance.get_extra_radiation(input)
    assert_allclose(out, expected, atol=1)
Пример #18
0
def test_get_extra_radiation(testval, expected, method):
    out = irradiance.get_extra_radiation(testval, method=method)
    assert_allclose(out, expected, atol=10)
Пример #19
0
    def __init__(self, panel=None, forecast_length=7, forecast_model=None):
        self.forecast_length = forecast_length
        if panel == None:
            self.panel = Panel()
        else:
            self.panel = panel

        if forecast_model == None:
            self.fm = GFS()
        else:
            self.fm = forecast_model

        self.start = pd.Timestamp(datetime.date.today(),
                                  tz=self.panel.tz)  # today's date
        self.end = self.start + pd.Timedelta(
            days=forecast_length)  # days from today

        print(
            "getting processed data with lat: %s, lng: %s, start:%s, end:%s" %
            (self.panel.latitude, self.panel.longitude, self.start, self.end))
        # get forecast data
        forecast_data = self.fm.get_processed_data(self.panel.latitude,
                                                   self.panel.longitude,
                                                   self.start, self.end)
        ghi = forecast_data['ghi']

        # get solar position
        time = forecast_data.index
        a_point = self.fm.location
        solpos = a_point.get_solarposition(time)

        # get PV(photovoltaic device) modules
        sandia_modules = pvsystem.retrieve_sam('SandiaMod')
        sandia_module = sandia_modules.Canadian_Solar_CS5P_220M___2009_

        dni_extra = irradiance.get_extra_radiation(
            self.fm.time)  # extra terrestrial radiation
        airmass = atmosphere.get_relative_airmass(solpos['apparent_zenith'])
        # POA: Plane Of Array: an image sensing device consisting of an array
        # (typically rectangular) of light-sensing pixels at the focal plane of a lens.
        # https://en.wikipedia.org/wiki/Staring_array

        # Diffuse sky radiation is solar radiation reaching the Earth's surface after
        # having been scattered from the direct solar beam by molecules or particulates
        # in the atmosphere.
        # https://en.wikipedia.org/wiki/Diffuse_sky_radiation
        poa_sky_diffuse = irradiance.haydavies(self.panel.surface_tilt,
                                               self.panel.surface_azimuth,
                                               forecast_data['dhi'],
                                               forecast_data['dni'], dni_extra,
                                               solpos['apparent_zenith'],
                                               solpos['azimuth'])

        # Diffuse reflection is the reflection of light or other waves or particles
        # from a surface such that a ray incident on the surface is scattered at many
        # angles rather than at just one angle as in the case of specular reflection.
        poa_ground_diffuse = irradiance.get_ground_diffuse(
            self.panel.surface_tilt, ghi, albedo=self.panel.albedo)

        # AOI: Angle Of Incidence
        aoi = irradiance.aoi(self.panel.surface_tilt,
                             self.panel.surface_azimuth,
                             solpos['apparent_zenith'], solpos['azimuth'])

        #  irradiance is the radiant flux (power) received by a surface per unit area
        # https://en.wikipedia.org/wiki/Irradiance
        poa_irrad = irradiance.poa_components(aoi, forecast_data['dni'],
                                              poa_sky_diffuse,
                                              poa_ground_diffuse)

        temperature = forecast_data['temp_air']
        wnd_spd = forecast_data['wind_speed']

        # pvtemps: pv temperature
        pvtemps = pvsystem.sapm_celltemp(poa_irrad['poa_global'], wnd_spd,
                                         temperature)

        # irradiance actually used by PV
        effective_irradiance = pvsystem.sapm_effective_irradiance(
            poa_irrad.poa_direct, poa_irrad.poa_diffuse, airmass, aoi,
            sandia_module)

        # SAPM: Sandia PV Array Performance Model
        # https://pvpmc.sandia.gov/modeling-steps/2-dc-module-iv/point-value-models/sandia-pv-array-performance-model/

        self.sapm_out = pvsystem.sapm(effective_irradiance,
                                      pvtemps['temp_cell'], sandia_module)

        sapm_inverters = pvsystem.retrieve_sam('sandiainverter')
        sapm_inverter = sapm_inverters[
            'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_']
        self.ac_power = pvsystem.snlinverter(self.sapm_out.v_mp,
                                             self.sapm_out.p_mp, sapm_inverter)
Пример #20
0
def perez_diffuse_luminance(timestamps, surface_tilt, surface_azimuth,
                            solar_zenith, solar_azimuth, dni, dhi):
    """Function used to calculate the luminance and the view factor terms from the
    Perez diffuse light transposition model, as implemented in the
    ``pvlib-python`` library.
    This function was custom made to allow the calculation of the circumsolar
    component on the back surface as well. Otherwise, the ``pvlib``
    implementation would ignore it.

    Parameters
    ----------
    timestamps : array-like
        simulation timestamps
    surface_tilt : array-like
        Surface tilt angles in decimal degrees.
        surface_tilt must be >=0 and <=180.
        The tilt angle is defined as degrees from horizontal
        (e.g. surface facing up = 0, surface facing horizon = 90)
    surface_azimuth : array-like
        The azimuth of the rotated panel,
        determined by projecting the vector normal to the panel's surface to
        the earth's surface [degrees].
    solar_zenith : array-like
        solar zenith angles
    solar_azimuth : array-like
        solar azimuth angles
    dni : array-like
        values for direct normal irradiance
    dhi : array-like
        values for diffuse horizontal irradiance

    Returns
    -------
    df_inputs : `pandas.DataFrame`
        Dataframe with the following columns:
        ['solar_zenith', 'solar_azimuth', 'surface_tilt', 'surface_azimuth',
        'dhi', 'dni', 'vf_horizon', 'vf_circumsolar', 'vf_isotropic',
        'luminance_horizon', 'luminance_circuqmsolar', 'luminance_isotropic',
        'poa_isotropic', 'poa_circumsolar', 'poa_horizon', 'poa_total_diffuse']

    """
    # Create a dataframe to help filtering on all arrays
    df_inputs = pd.DataFrame(
        {
            'surface_tilt': surface_tilt,
            'surface_azimuth': surface_azimuth,
            'solar_zenith': solar_zenith,
            'solar_azimuth': solar_azimuth,
            'dni': dni,
            'dhi': dhi
        },
        index=pd.DatetimeIndex(timestamps))

    dni_et = irradiance.get_extra_radiation(df_inputs.index.dayofyear)
    am = atmosphere.get_relative_airmass(df_inputs.solar_zenith)

    # Need to treat the case when the sun is hitting the back surface of pvrow
    aoi_proj = irradiance.aoi_projection(df_inputs.surface_tilt,
                                         df_inputs.surface_azimuth,
                                         df_inputs.solar_zenith,
                                         df_inputs.solar_azimuth)
    sun_hitting_back_surface = ((aoi_proj < 0) &
                                (df_inputs.solar_zenith <= 90))
    df_inputs_back_surface = df_inputs.loc[sun_hitting_back_surface].copy()
    # Reverse the surface normal to switch to back-surface circumsolar calc
    df_inputs_back_surface.loc[:, 'surface_azimuth'] = (
        df_inputs_back_surface.loc[:, 'surface_azimuth'] - 180.)
    df_inputs_back_surface.loc[:, 'surface_azimuth'] = np.mod(
        df_inputs_back_surface.loc[:, 'surface_azimuth'], 360.)
    df_inputs_back_surface.loc[:, 'surface_tilt'] = (
        180. - df_inputs_back_surface.surface_tilt)

    if df_inputs_back_surface.shape[0] > 0:
        # Use recursion to calculate circumsolar luminance for back surface
        df_inputs_back_surface = perez_diffuse_luminance(
            *breakup_df_inputs(df_inputs_back_surface))

    # Calculate Perez diffuse components
    components = irradiance.perez(df_inputs.surface_tilt,
                                  df_inputs.surface_azimuth,
                                  df_inputs.dhi,
                                  df_inputs.dni,
                                  dni_et,
                                  df_inputs.solar_zenith,
                                  df_inputs.solar_azimuth,
                                  am,
                                  return_components=True)

    # Calculate Perez view factors:
    a = irradiance.aoi_projection(df_inputs.surface_tilt,
                                  df_inputs.surface_azimuth,
                                  df_inputs.solar_zenith,
                                  df_inputs.solar_azimuth)
    a = np.maximum(a, 0)
    b = cosd(df_inputs.solar_zenith)
    b = np.maximum(b, cosd(85))

    vf_perez = pd.DataFrame(
        {
            'vf_horizon': sind(df_inputs.surface_tilt),
            'vf_circumsolar': a / b,
            'vf_isotropic': (1. + cosd(df_inputs.surface_tilt)) / 2.
        },
        index=df_inputs.index)

    # Calculate diffuse luminance
    luminance = pd.DataFrame(np.array([
        components['horizon'] / vf_perez['vf_horizon'],
        components['circumsolar'] / vf_perez['vf_circumsolar'],
        components['isotropic'] / vf_perez['vf_isotropic']
    ]).T,
                             index=df_inputs.index,
                             columns=[
                                 'luminance_horizon', 'luminance_circumsolar',
                                 'luminance_isotropic'
                             ])
    luminance.loc[components['sky_diffuse'] == 0, :] = 0.

    # Format components column names
    components = components.rename(
        columns={
            'isotropic': 'poa_isotropic',
            'circumsolar': 'poa_circumsolar',
            'horizon': 'poa_horizon'
        })

    df_inputs = pd.concat([df_inputs, components, vf_perez, luminance],
                          axis=1,
                          join='outer')
    df_inputs = df_inputs.rename(columns={'sky_diffuse': 'poa_total_diffuse'})

    # Adjust the circumsolar luminance when it hits the back surface
    if df_inputs_back_surface.shape[0] > 0:
        df_inputs.loc[sun_hitting_back_surface, 'luminance_circumsolar'] = (
            df_inputs_back_surface.loc[:, 'luminance_circumsolar'])

    return df_inputs
Пример #21
0
def get_dni_extra(fm):
    # Calculate extra terrestrial radiation. This is needed for many plane of array diffuse irradiance models.
    dni_extra = irradiance.get_extra_radiation(fm.time)
    return dni_extra
Пример #22
0
 def time_get_extra_radiation(self):
     irradiance.get_extra_radiation(self.days)
Пример #23
0
# Retrieve data
forecast_data = fm.get_processed_data(latitude, longitude, start, end)
ghi = forecast_data['ghi']

sandia_modules = pvsystem.retrieve_sam('SandiaMod')
sandia_module = sandia_modules.Canadian_Solar_CS5P_220M___2009_



# retrieve time and location parameters
time = forecast_data.index
a_point = fm.location

solpos = a_point.get_solarposition(time)
dni_extra = irradiance.get_extra_radiation(fm.time)
airmass = atmosphere.get_relative_airmass(solpos['apparent_zenith'])
poa_sky_diffuse = irradiance.haydavies(surface_tilt, surface_azimuth,
                           forecast_data['dhi'], forecast_data['dni'], dni_extra,
                           solpos['apparent_zenith'], solpos['azimuth'])

poa_ground_diffuse = irradiance.get_ground_diffuse(surface_tilt, ghi, albedo=albedo)
aoi = irradiance.aoi(surface_tilt, surface_azimuth, solpos['apparent_zenith'], solpos['azimuth'])

poa_irrad = irradiance.poa_components(aoi, forecast_data['dni'], poa_sky_diffuse,
                                        poa_ground_diffuse)

temperature = forecast_data['temp_air']
wnd_spd = forecast_data['wind_speed']
pvtemps = pvsystem.sapm_celltemp(poa_irrad['poa_global'], wnd_spd, temperature)
Пример #24
0
    def get_irradiance(self,
                       surface_tilt,
                       surface_azimuth,
                       solar_zenith,
                       solar_azimuth,
                       dni,
                       ghi,
                       dhi,
                       dni_extra=None,
                       airmass=None,
                       model='haydavies',
                       **kwargs):
        """
        Uses the :func:`irradiance.get_total_irradiance` function to
        calculate the plane of array irradiance components on a tilted
        surface defined by the input data and ``self.albedo``.

        For a given set of solar zenith and azimuth angles, the
        surface tilt and azimuth parameters are typically determined
        by :py:meth:`~SingleAxisTracker.singleaxis`.

        Parameters
        ----------
        surface_tilt : numeric
            Panel tilt from horizontal.
        surface_azimuth : numeric
            Panel azimuth from north
        solar_zenith : numeric
            Solar zenith angle.
        solar_azimuth : numeric
            Solar azimuth angle.
        dni : float or Series
            Direct Normal Irradiance
        ghi : float or Series
            Global horizontal irradiance
        dhi : float or Series
            Diffuse horizontal irradiance
        dni_extra : float or Series, default None
            Extraterrestrial direct normal irradiance
        airmass : float or Series, default None
            Airmass
        model : String, default 'haydavies'
            Irradiance model.

        **kwargs
            Passed to :func:`irradiance.total_irrad`.

        Returns
        -------
        poa_irradiance : DataFrame
            Column names are: ``total, beam, sky, ground``.
        """

        # not needed for all models, but this is easier
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(solar_zenith.index)

        if airmass is None:
            airmass = atmosphere.get_relative_airmass(solar_zenith)

        return irradiance.get_total_irradiance(surface_tilt,
                                               surface_azimuth,
                                               solar_zenith,
                                               solar_azimuth,
                                               dni,
                                               ghi,
                                               dhi,
                                               dni_extra=dni_extra,
                                               airmass=airmass,
                                               model=model,
                                               albedo=self.albedo,
                                               **kwargs)
Пример #25
0
    def get_clearsky(self, times, model='ineichen', solar_position=None,
                     dni_extra=None, **kwargs):
        """
        Calculate the clear sky estimates of GHI, DNI, and/or DHI
        at this location.

        Parameters
        ----------
        times: DatetimeIndex
        model: str, default 'ineichen'
            The clear sky model to use. Must be one of
            'ineichen', 'haurwitz', 'simplified_solis'.
        solar_position : None or DataFrame, default None
            DataFrame with columns 'apparent_zenith', 'zenith',
            'apparent_elevation'.
        dni_extra: None or numeric, default None
            If None, will be calculated from times.

        kwargs passed to the relevant functions. Climatological values
        are assumed in many cases. See source code for details!

        Returns
        -------
        clearsky : DataFrame
            Column names are: ``ghi, dni, dhi``.
        """
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(times)

        try:
            pressure = kwargs.pop('pressure')
        except KeyError:
            pressure = atmosphere.alt2pres(self.altitude)

        if solar_position is None:
            solar_position = self.get_solarposition(times, pressure=pressure,
                                                    **kwargs)

        apparent_zenith = solar_position['apparent_zenith']
        apparent_elevation = solar_position['apparent_elevation']

        if model == 'ineichen':
            try:
                linke_turbidity = kwargs.pop('linke_turbidity')
            except KeyError:
                interp_turbidity = kwargs.pop('interp_turbidity', True)
                linke_turbidity = clearsky.lookup_linke_turbidity(
                    times, self.latitude, self.longitude,
                    interp_turbidity=interp_turbidity)

            try:
                airmass_absolute = kwargs.pop('airmass_absolute')
            except KeyError:
                airmass_absolute = self.get_airmass(
                    times, solar_position=solar_position)['airmass_absolute']

            cs = clearsky.ineichen(apparent_zenith, airmass_absolute,
                                   linke_turbidity, altitude=self.altitude,
                                   dni_extra=dni_extra, **kwargs)
        elif model == 'haurwitz':
            cs = clearsky.haurwitz(apparent_zenith)
        elif model == 'simplified_solis':
            cs = clearsky.simplified_solis(
                apparent_elevation, pressure=pressure, dni_extra=dni_extra,
                **kwargs)
        else:
            raise ValueError('{} is not a valid clear sky model. Must be '
                             'one of ineichen, simplified_solis, haurwitz'
                             .format(model))

        return cs
Пример #26
0
def test_get_extra_radiation_epoch_year():
    out = irradiance.get_extra_radiation(doy, method='nrel', epoch_year=2012)
    assert_allclose(out, 1382.4926804890767, atol=0.1)
Пример #27
0
    def get_irradiance(self,
                       solar_zenith,
                       solar_azimuth,
                       dni,
                       ghi,
                       dhi,
                       dni_extra=None,
                       airmass=None,
                       model='haydavies',
                       **kwargs):
        """
        Uses the :py:func:`irradiance.get_total_irradiance` function to
        calculate the plane of array irradiance components on a Fixed panel.

        Parameters
        ----------
        solar_zenith : float or Series.
            Solar zenith angle.
        solar_azimuth : float or Series.
            Solar azimuth angle.
        dni : float or Series
            Direct Normal Irradiance
        ghi : float or Series
            Global horizontal irradiance
        dhi : float or Series
            Diffuse horizontal irradiance
        dni_extra : None, float or Series, default None
            Extraterrestrial direct normal irradiance
        airmass : None, float or Series, default None
            Airmass
        model : String, default 'haydavies'
            Irradiance model.

        **kwargs
            Passed to :func:`irradiance.total_irrad`.

        Returns
        -------
        poa_irradiance : DataFrame
            Column names are: ``total, beam, sky, ground``.
        """

        # not needed for all models, but this is easier
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(solar_zenith.index)

        if airmass is None:
            airmass = atmosphere.get_relative_airmass(solar_zenith)

        return irradiance.get_total_irradiance(self.surface_tilt,
                                               self.surface_azimuth,
                                               solar_zenith,
                                               solar_azimuth,
                                               dni,
                                               ghi,
                                               dhi,
                                               dni_extra=dni_extra,
                                               airmass=airmass,
                                               model=model,
                                               albedo=self.albedo,
                                               **kwargs)
Пример #28
0
def test_get_extra_radiation_invalid():
    with pytest.raises(ValueError):
        irradiance.get_extra_radiation(300, method='invalid')
Пример #29
0
def _solpos_dni_extra(observation, values):
    solar_position, night_flag = _solpos_night(observation, values)
    dni_extra = get_extra_radiation(values.index)
    timestamp_flag = _validate_timestamp(observation, values)
    return solar_position, dni_extra, timestamp_flag, night_flag
Пример #30
0
def test_get_extra_radiation_nrel_numba(times):
    result = irradiance.get_extra_radiation(times, method='nrel', how='numba',
                                            numthreads=8)
    assert_allclose(result, [1322.332316, 1322.296282, 1322.261205, 1322.227091])
Пример #31
0
    def get_irradiance(self,
                       surface_tilt,
                       surface_azimuth,
                       solar_zenith,
                       solar_azimuth,
                       dni,
                       ghi,
                       dhi,
                       dni_extra=None,
                       airmass=None,
                       model='haydavies',
                       **kwargs):
        """
        Uses the :func:`irradiance.get_total_irradiance` function to
        calculate the plane of array irradiance components on a tilted
        surface defined by the input data and ``self.albedo``.

        For a given set of solar zenith and azimuth angles, the
        surface tilt and azimuth parameters are typically determined
        by :py:meth:`~SingleAxisTracker.singleaxis`.

        Parameters
        ----------
        surface_tilt : numeric
            Panel tilt from horizontal.
        surface_azimuth : numeric
            Panel azimuth from north
        solar_zenith : numeric
            Solar zenith angle.
        solar_azimuth : numeric
            Solar azimuth angle.
        dni : float or Series
            Direct Normal Irradiance
        ghi : float or Series
            Global horizontal irradiance
        dhi : float or Series
            Diffuse horizontal irradiance
        dni_extra : float or Series, default None
            Extraterrestrial direct normal irradiance
        airmass : float or Series, default None
            Airmass
        model : String, default 'haydavies'
            Irradiance model.

        **kwargs
            Passed to :func:`irradiance.get_total_irradiance`.

        Returns
        -------
        poa_irradiance : DataFrame
            Column names are: ``total, beam, sky, ground``.
        """

        # not needed for all models, but this is easier
        if dni_extra is None:
            dni_extra = irradiance.get_extra_radiation(solar_zenith.index)

        if airmass is None:
            airmass = atmosphere.get_relative_airmass(solar_zenith)

        # SingleAxisTracker only supports a single Array, but we need the
        # validate/iterate machinery so that single length tuple input/output
        # is handled the same as PVSystem.get_irradiance. GH 1159
        dni = self._validate_per_array(dni, system_wide=True)
        ghi = self._validate_per_array(ghi, system_wide=True)
        dhi = self._validate_per_array(dhi, system_wide=True)

        return tuple(
            irradiance.get_total_irradiance(surface_tilt,
                                            surface_azimuth,
                                            solar_zenith,
                                            solar_azimuth,
                                            dni,
                                            ghi,
                                            dhi,
                                            dni_extra=dni_extra,
                                            airmass=airmass,
                                            model=model,
                                            albedo=self.arrays[0].albedo,
                                            **kwargs)
            for array, dni, ghi, dhi in zip(self.arrays, dni, ghi, dhi))
Пример #32
0
def test_get_extra_radiation_invalid():
    with pytest.raises(ValueError):
        irradiance.get_extra_radiation(300, method='invalid')
Пример #33
0
def test_bird():
    """Test Bird/Hulstrom Clearsky Model"""
    times = pd.date_range(start='1/1/2015 0:00', end='12/31/2015 23:00',
                          freq='H')
    tz = -7  # test timezone
    gmt_tz = pytz.timezone('Etc/GMT%+d' % -(tz))
    times = times.tz_localize(gmt_tz)  # set timezone
    # match test data from BIRD_08_16_2012.xls
    latitude = 40.
    longitude = -105.
    press_mB = 840.
    o3_cm = 0.3
    h2o_cm = 1.5
    aod_500nm = 0.1
    aod_380nm = 0.15
    b_a = 0.85
    alb = 0.2
    eot = solarposition.equation_of_time_spencer71(times.dayofyear)
    hour_angle = solarposition.hour_angle(times, longitude, eot) - 0.5 * 15.
    declination = solarposition.declination_spencer71(times.dayofyear)
    zenith = solarposition.solar_zenith_analytical(
        np.deg2rad(latitude), np.deg2rad(hour_angle), declination
    )
    zenith = np.rad2deg(zenith)
    airmass = atmosphere.get_relative_airmass(zenith, model='kasten1966')
    etr = irradiance.get_extra_radiation(times)
    # test Bird with time series data
    field_names = ('dni', 'direct_horizontal', 'ghi', 'dhi')
    irrads = clearsky.bird(
        zenith, airmass, aod_380nm, aod_500nm, h2o_cm, o3_cm, press_mB * 100.,
        etr, b_a, alb
    )
    Eb, Ebh, Gh, Dh = (irrads[_] for _ in field_names)
    data_path = DATA_DIR / 'BIRD_08_16_2012.csv'
    testdata = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna()
    testdata.index = times[1:48]
    assert np.allclose(testdata['DEC'], np.rad2deg(declination[1:48]))
    assert np.allclose(testdata['EQT'], eot[1:48], rtol=1e-4)
    assert np.allclose(testdata['Hour Angle'], hour_angle[1:48])
    assert np.allclose(testdata['Zenith Ang'], zenith[1:48])
    dawn = zenith < 88.
    dusk = testdata['Zenith Ang'] < 88.
    am = pd.Series(np.where(dawn, airmass, 0.), index=times).fillna(0.0)
    assert np.allclose(
        testdata['Air Mass'].where(dusk, 0.), am[1:48], rtol=1e-3
    )
    direct_beam = pd.Series(np.where(dawn, Eb, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Direct Beam'].where(dusk, 0.), direct_beam[1:48], rtol=1e-3
    )
    direct_horz = pd.Series(np.where(dawn, Ebh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Direct Hz'].where(dusk, 0.), direct_horz[1:48], rtol=1e-3
    )
    global_horz = pd.Series(np.where(dawn, Gh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Global Hz'].where(dusk, 0.), global_horz[1:48], rtol=1e-3
    )
    diffuse_horz = pd.Series(np.where(dawn, Dh, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata['Dif Hz'].where(dusk, 0.), diffuse_horz[1:48], rtol=1e-3
    )
    # test keyword parameters
    irrads2 = clearsky.bird(
        zenith, airmass, aod_380nm, aod_500nm, h2o_cm, dni_extra=etr
    )
    Eb2, Ebh2, Gh2, Dh2 = (irrads2[_] for _ in field_names)
    data_path = DATA_DIR / 'BIRD_08_16_2012_patm.csv'
    testdata2 = pd.read_csv(data_path, usecols=range(1, 26), header=1).dropna()
    testdata2.index = times[1:48]
    direct_beam2 = pd.Series(np.where(dawn, Eb2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Direct Beam'].where(dusk, 0.), direct_beam2[1:48], rtol=1e-3
    )
    direct_horz2 = pd.Series(np.where(dawn, Ebh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Direct Hz'].where(dusk, 0.), direct_horz2[1:48], rtol=1e-3
    )
    global_horz2 = pd.Series(np.where(dawn, Gh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Global Hz'].where(dusk, 0.), global_horz2[1:48], rtol=1e-3
    )
    diffuse_horz2 = pd.Series(np.where(dawn, Dh2, 0.), index=times).fillna(0.)
    assert np.allclose(
        testdata2['Dif Hz'].where(dusk, 0.), diffuse_horz2[1:48], rtol=1e-3
    )
    # test scalars just at noon
    # XXX: calculations start at 12am so noon is at index = 12
    irrads3 = clearsky.bird(
        zenith[12], airmass[12], aod_380nm, aod_500nm, h2o_cm, dni_extra=etr[12]
    )
    Eb3, Ebh3, Gh3, Dh3 = (irrads3[_] for _ in field_names)
    # XXX: testdata starts at 1am so noon is at index = 11
    np.allclose(
        [Eb3, Ebh3, Gh3, Dh3],
        testdata2[['Direct Beam', 'Direct Hz', 'Global Hz', 'Dif Hz']].iloc[11],
        rtol=1e-3)
    return pd.DataFrame({'Eb': Eb, 'Ebh': Ebh, 'Gh': Gh, 'Dh': Dh}, index=times)