Example #1
0
def test_lookup_linke_turbidity_nointerp_months():
    times = pd.date_range(start='2014-04-10', end='2014-07-10',
                          freq='1M', tz='America/Phoenix')
    expected = pd.Series(np.array([2.85, 2.95, 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
    # changing the dates shouldn't matter if interp=False
    times = pd.date_range(start='2014-04-05', end='2014-07-05',
                          freq='1M', tz='America/Phoenix')
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
Example #2
0
def test_lookup_linke_turbidity_nointerp_months():
    times = pd.date_range(start='2014-04-10', end='2014-07-10',
                          freq='1M', tz='America/Phoenix')
    expected = pd.Series(np.array([2.85, 2.95, 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
    # changing the dates shouldn't matter if interp=False
    times = pd.date_range(start='2014-04-05', end='2014-07-05',
                          freq='1M', tz='America/Phoenix')
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
def test_lookup_linke_turbidity_months():
    times = pd.date_range(start='2014-04-01', end='2014-07-01',
                          freq='1M', tz='America/Phoenix')
    expected = pd.Series(np.array([2.8943038, 2.97316456, 3.18025316]),
                         index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.2, -111)
    assert_series_equal(expected, out)
Example #4
0
def linke_turbidity_resource(request):
    if request.method == 'GET':
        params = LinkeTurbidityForm(request.GET)
    else:
        params = LinkeTurbidityForm(request.POST)
    if params.is_valid():
        lat = params.cleaned_data['tl_lat']
        lon = params.cleaned_data['tl_lon']
        start = params.cleaned_data['tl_start']
        end = params.cleaned_data['tl_end']
        tz = params.cleaned_data['tl_tz']
        freq = params.cleaned_data['tl_freq']
    else:
        return JsonResponse(params.errors, status=400)
    tz = tz or 0  # if tz is None then use zero
    freq = freq or 'H'  # if freq if '' then use 'H'
    if start > end:
        return JsonResponse({'start': ['End time must be after start.']},
                            status=400)
    # drop the timezone
    start = start.replace(tzinfo=None)
    end = end.replace(tzinfo=None)
    tz = 'Etc/GMT{:+d}'.format(-tz)
    try:
        times = pd.DatetimeIndex(start=start, end=end, freq=freq, tz=tz)
    except ValueError as exc:
        return JsonResponse({'freq': [str(exc)]}, status=400)
    tl = clearsky.lookup_linke_turbidity(times, lat, lon)
    tl.index = times.strftime('%Y-%m-%dT%H:%M:%S%z')
    # [t.isoformat() for t in times.to_pydatetime()]
    data = tl.to_dict()
    return JsonResponse(data)
Example #5
0
def test_lookup_linke_turbidity_months_leapyear():
    times = pd.date_range(start='2016-04-01', end='2016-07-01',
                          freq='1M', tz='America/Phoenix')
    expected = pd.Series(
        np.array([2.89918032787, 2.97540983607, 3.19672131148]), index=times
    )
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875)
    assert_series_equal(expected, out)
Example #6
0
def test_lookup_linke_turbidity_months():
    times = pd.date_range(start='2014-04-01', end='2014-07-01',
                          freq='1M', tz=tus.tz)
    expected = pd.Series(np.array([2.8943038, 2.97316456, 3.18025316]),
                         index=times)
    out = clearsky.lookup_linke_turbidity(times, tus.latitude,
                                          tus.longitude)
    assert_series_equal(expected, out)
Example #7
0
def test_lookup_linke_turbidity_nointerp():
    times = pd.date_range(start='2014-06-24', end='2014-06-25',
                          freq='12h', tz=tus.tz)
    # expect same value for all days
    expected = pd.Series(np.array([3., 3., 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times, tus.latitude, tus.longitude,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
Example #8
0
def test_lookup_linke_turbidity_nointerp():
    times = pd.date_range(start='2014-06-24', end='2014-06-25',
                          freq='12h', tz='America/Phoenix')
    # expect same value for all days
    expected = pd.Series(np.array([3., 3., 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
Example #9
0
def test_lookup_linke_turbidity_months_leapyear():
    times = pd.date_range(start='2016-04-01', end='2016-07-01',
                          freq='1M', tz='America/Phoenix')
    expected = pd.Series(
        np.array([2.89918032787, 2.97540983607, 3.19672131148]), index=times
    )
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875)
    assert_series_equal(expected, out)
Example #10
0
def test_lookup_linke_turbidity_nointerp():
    times = pd.date_range(start='2014-06-24', end='2014-06-25',
                          freq='12h', tz='America/Phoenix')
    # expect same value for all days
    expected = pd.Series(np.array([3., 3., 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
Example #11
0
def test_lookup_linke_turbidity_months():
    times = pd.date_range(start='2014-04-01',
                          end='2014-07-01',
                          freq='1M',
                          tz=tus.tz)
    expected = pd.Series(np.array([2.8943038, 2.97316456, 3.18025316]),
                         index=times)
    out = clearsky.lookup_linke_turbidity(times, tus.latitude, tus.longitude)
    assert_series_equal(expected, out)
Example #12
0
def test_lookup_linke_turbidity():
    times = pd.date_range(start='2014-06-24', end='2014-06-25',
                          freq='12h', tz=tus.tz)
    # expect same value on 2014-06-24 0000 and 1200, and
    # diff value on 2014-06-25
    expected = pd.Series(np.array([3.10126582, 3.10126582, 3.11443038]),
                         index=times)
    out = clearsky.lookup_linke_turbidity(times, tus.latitude, tus.longitude)
    assert_series_equal(expected, out)
Example #13
0
def test_lookup_linke_turbidity():
    times = pd.date_range(start='2014-06-24', end='2014-06-25',
                          freq='12h', tz='America/Phoenix')
    # expect same value on 2014-06-24 0000 and 1200, and
    # diff value on 2014-06-25
    expected = pd.Series(np.array([3.10126582, 3.10126582, 3.11443038]),
                         index=times)
    out = clearsky.lookup_linke_turbidity(times, 32.2, -111)
    assert_series_equal(expected, out)
Example #14
0
def test_lookup_linke_turbidity_leapyear():
    times = pd.date_range(start='2016-06-24', end='2016-06-25',
                          freq='12h', tz='America/Phoenix')
    # expect same value on 2016-06-24 0000 and 1200, and
    # diff value on 2016-06-25
    expected = pd.Series(
        np.array([3.11803278689, 3.11803278689, 3.13114754098]), index=times
    )
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875)
    assert_series_equal(expected, out)
Example #15
0
def test_lookup_linke_turbidity_leapyear():
    times = pd.date_range(start='2016-06-24', end='2016-06-25',
                          freq='12h', tz='America/Phoenix')
    # expect same value on 2016-06-24 0000 and 1200, and
    # diff value on 2016-06-25
    expected = pd.Series(
        np.array([3.11803278689, 3.11803278689, 3.13114754098]), index=times
    )
    out = clearsky.lookup_linke_turbidity(times, 32.125, -110.875)
    assert_series_equal(expected, out)
Example #16
0
def test_lookup_linke_turbidity_nointerp():
    times = pd.date_range(start='2014-06-24',
                          end='2014-06-25',
                          freq='12h',
                          tz=tus.tz)
    # expect same value for all days
    expected = pd.Series(np.array([3., 3., 3.]), index=times)
    out = clearsky.lookup_linke_turbidity(times,
                                          tus.latitude,
                                          tus.longitude,
                                          interp_turbidity=False)
    assert_series_equal(expected, out)
Example #17
0
 def test_tl_lookup(self):
     data = {
         'tl_lat': 38.2,
         'tl_lon': -122.1,
         'tl_freq': 'T',
         'tl_tz': -8,
         'tl_start': '2018-01-01 07:00',
         'tl_end': '2018-01-01 08:00'
     }
     r = self.client.get('/api/v1/pvlib/linke-turbidity/', data)
     self.assertEqual(r.status_code, 200)
     s = pd.Series(r.json())
     t = pd.DatetimeIndex(s.index)
     times = pd.DatetimeIndex(start=data['tl_start'],
                              end=data['tl_end'],
                              freq=data['tl_freq'],
                              tz='Etc/GMT{:+d}'.format(-data['tl_tz']))
     tl = clearsky.lookup_linke_turbidity(times, data['tl_lat'],
                                          data['tl_lon'])
     assert np.allclose(times.values.astype(int), t.values.astype(int))
     assert np.allclose(tl, s)
Example #18
0
def generate_clearsky_sequence(time,
                               location,
                               sun_position=None,
                               p_0=101325.0,
                               model="ineichen"):
    """ Generate clear-sky irradiance sequence

    :param time:
    :param location: pvlib.location.Location object
    :param sun_position:
    :param p_0: sea level pressure
    :param model: {'ineichen', 'solis'} #TODO: implement solis clearsky model
    :return:
    """
    if sun_position is None:
        sun_position = get_solar_position(time, location.latitude,
                                          location.longitude,
                                          location.altitude)

    # Altitude corrected (King et al. 1997; Rigollier et al. 2000)
    pressure = p_0 * np.exp(-0.0001184 * location.altitude)

    # Relative airmass
    am = get_relative_airmass(sun_position["zenith"])

    # Absolute airmass
    am_a = get_absolute_airmass(am, pressure)

    # Linke turbidity
    linke_turbidity = lookup_linke_turbidity(time, location.latitude,
                                             location.longitude)

    if model == "ineichen":
        return ineichen(sun_position["apparent_zenith"], am_a,
                        linke_turbidity)["ghi"]
    elif model == "solis":
        pass
Example #19
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
            The clear sky model to use. Must be one of
            'ineichen', 'haurwitz', 'simplified_solis'.
        solar_position : None or DataFrame
            DataFrame with with columns 'apparent_zenith', 'zenith',
            'apparent_elevation'.
        dni_extra: None or numeric
            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.extraradiation(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)
        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
Example #20
0
def solar_irradiation(latitude, longitude, Z, moment, surface_tilt,
                      surface_azimuth, T=None, P=None, solar_constant=1366.1,
                      atmos_refract=0.5667, albedo=0.25, linke_turbidity=None,
                      extraradiation_method='spencer',
                      airmass_model='kastenyoung1989',
                      cache=None):
    r'''Calculates the amount of solar radiation and radiation reflected back
    the atmosphere which hits a surface at a specified tilt, and facing a
    specified azimuth.

    This functions is a wrapper for the incredibly
    comprehensive `pvlib library <https://github.com/pvlib/pvlib-python>`_,
    and requires it to be installed.

    Parameters
    ----------
    latitude : float
        Latitude, between -90 and 90 [degrees]
    longitude : float
        Longitude, between -180 and 180, [degrees]
    Z : float, optional
        Elevation above sea level for the position, [m]
    moment : datetime, optionally with pytz info
        Time and date for the calculation, in UTC time OR in the time zone
        of the latitude/longitude specified BUT WITH A TZINFO ATTATCHED!
        Please be careful with this argument, time zones are confusing. [-]
    surface_tilt : float
        The angle above the horizontal of the object being hit by radiation,
        [degrees]
    surface_azimuth : float
        The angle the object is facing (positive, North eastwards 0° to 360°),
        [degrees]
    T : float, optional
        Temperature of atmosphere at ground level, [K]
    P : float, optional
        Pressure of atmosphere at ground level, [Pa]
    solar_constant : float, optional
        The amount of solar radiation which reaches earth's disk (at a
        standardized distance of 1 AU); this constant is independent of
        activity or conditions on earth, but will vary throughout the sun's
        lifetime and may increase or decrease slightly due to solar activity,
        [W/m^2]
    atmos_refract : float, optional
        Atmospheric refractivity at sunrise/sunset (0.5667 deg is an often used
        value; this varies substantially and has an impact of a few minutes on
        when sunrise and sunset is), [degrees]
    albedo : float, optional
        The average amount of reflection of the terrain surrounding the object
        at quite a distance; this impacts how much sunlight reflected off the
        ground, gets reflected back off clouds, [-]
    linke_turbidity : float, optional
        The amount of pollution/water in the sky versus a perfect clear sky;
        If not specified, this will be retrieved from a historical grid;
        typical values are 3 for cloudy, and 7 for severe pollution around a
        city, [-]
    extraradiation_method : str, optional
        The specified method to calculate the effect of earth's position on the
        amount of radiation which reaches earth according to the methods
        available in the `pvlib` library, [-]
    airmass_model : str, optional
        The specified method to calculate the amount of air the sunlight
        needs to travel through to reach the earth according to the methods
        available in the `pvlib` library, [-]
    cache : dict, optional
        Dictionary to to check for values to use to skip some calculations;
        `apparent_zenith`, `zenith`, `azimuth` supported, [-]

    Returns
    -------
    poa_global : float
        The total irradiance in the plane of the surface, [W/m^2]
    poa_direct : float
        The total beam irradiance in the plane of the surface, [W/m^2]
    poa_diffuse : float
        The total diffuse irradiance in the plane of the surface, [W/m^2]
    poa_sky_diffuse : float
        The sky component of the diffuse irradiance, excluding the impact
        from the ground, [W/m^2]
    poa_ground_diffuse : float
        The ground-sky diffuse irradiance component, [W/m^2]

    Examples
    --------
    >>> import pytz
    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07, linke_turbidity=3,
    ... moment=pytz.timezone('America/Edmonton').localize(datetime(2018, 4, 15, 13, 43, 5)), surface_tilt=41.0,
    ... surface_azimuth=180.0)
    (1065.7621896280, 945.2656564506, 120.49653317744, 95.31535344213, 25.181179735317)

    >>> cache = {'apparent_zenith': 41.099082295767545, 'zenith': 41.11285376417578, 'azimuth': 182.5631874250523}
    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07,
    ... moment=pytz.timezone('America/Edmonton').localize(datetime(2018, 4, 15, 13, 43, 5)), surface_tilt=41.0,
    ... linke_turbidity=3, T=300, P=1E5,
    ... surface_azimuth=180.0, cache=cache)
    (1042.567770367, 918.237754854, 124.3300155131, 99.622865737, 24.7071497753)

    At night, there is no solar radiation and this function returns zeros:

    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07, linke_turbidity=3,
    ... moment=pytz.timezone('America/Edmonton').localize(datetime(2018, 4, 15, 2, 43, 5)), surface_tilt=41.0,
    ... surface_azimuth=180.0)
    (0.0, -0.0, 0.0, 0.0, 0.0)


    Notes
    -----
    The retrieval of `linke_turbidity` requires the pytables library (and
    Pandas); if it is not installed, specify a value of `linke_turbidity` to
    avoid the dependency.

    There is some redundancy of the calculated results, according to the
    following relations. The total irradiance is normally that desired for
    engineering calculations.

    poa_diffuse = poa_ground_diffuse + poa_sky_diffuse

    poa_global = poa_direct + poa_diffuse

    For a surface such as a pipe or vessel, an approach would be to split it
    into a number of rectangles and sum up the radiation absorbed by each.

    This calculation is fairly slow.

    References
    ----------
    .. [1] Will Holmgren, Calama-Consulting, Tony Lorenzo, Uwe Krien, bmu,
       DaCoEx, mayudong, et al. Pvlib/Pvlib-Python: 0.5.1. Zenodo, 2017.
       https://doi.org/10.5281/zenodo.1016425.
    '''
    # Atmospheric refraction at sunrise/sunset (0.5667 deg is an often used value)
    import calendar
    from fluids.optional import spa
    from fluids.optional.irradiance import (get_relative_airmass, get_absolute_airmass,
                                            ineichen, get_relative_airmass,
                                            get_absolute_airmass, get_total_irradiance)

    moment_timetuple = moment.timetuple()
    moment_arg_dni = (moment_timetuple.tm_yday if
                      extraradiation_method == 'spencer' else moment)

    dni_extra = _get_extra_radiation_shim(moment_arg_dni, solar_constant=solar_constant,
                               method=extraradiation_method,
                               epoch_year=moment.year)

    if T is None or P is None:
        atmosphere = ATMOSPHERE_NRLMSISE00(Z=Z, latitude=latitude,
                                           longitude=longitude,
                                           day=moment_timetuple.tm_yday)
        if T is None:
            T = atmosphere.T
        if P is None:
            P = atmosphere.P

    if cache is not None and 'zenith' in cache:
        zenith = cache['zenith']
        apparent_zenith = cache['apparent_zenith']
        azimuth = cache['azimuth']
    else:
        apparent_zenith, zenith, _, _, azimuth, _ = solar_position(moment=moment,
                                                                   latitude=latitude,
                                                                   longitude=longitude,
                                                                   Z=Z, T=T, P=P,
                                                                   atmos_refract=atmos_refract)

    if linke_turbidity is None:
        try:
            import pvlib
        except:
            raise ImportError(PVLIB_MISSING_MSG)
        from pvlib.clearsky import lookup_linke_turbidity
        import pandas as pd
        linke_turbidity = float(lookup_linke_turbidity(
            pd.DatetimeIndex([moment]), latitude, longitude).values)


    if airmass_model in apparent_zenith_airmass_models:
        used_zenith = apparent_zenith
    elif airmass_model in true_zenith_airmass_models:
        used_zenith = zenith
    else:
        raise ValueError('Unrecognized airmass model')

    relative_airmass = get_relative_airmass(used_zenith, model=airmass_model)
    airmass_absolute = get_absolute_airmass(relative_airmass, pressure=P)


    ans = ineichen(apparent_zenith=apparent_zenith,
                   airmass_absolute=airmass_absolute,
                   linke_turbidity=linke_turbidity,
                   altitude=Z, dni_extra=solar_constant, perez_enhancement=True)
    ghi = ans['ghi']
    dni = ans['dni']
    dhi = ans['dhi']


#    from pvlib.irradiance import get_total_irradiance
    ans = get_total_irradiance(surface_tilt=surface_tilt,
                      surface_azimuth=surface_azimuth,
                      solar_zenith=apparent_zenith, solar_azimuth=azimuth,
                      dni=dni, ghi=ghi, dhi=dhi, dni_extra=dni_extra,
                      airmass=airmass_absolute, albedo=albedo)
    poa_global = float(ans['poa_global'])
    poa_direct = float(ans['poa_direct'])
    poa_diffuse = float(ans['poa_diffuse'])
    poa_sky_diffuse = float(ans['poa_sky_diffuse'])
    poa_ground_diffuse = float(ans['poa_ground_diffuse'])
    return (poa_global, poa_direct, poa_diffuse, poa_sky_diffuse,
            poa_ground_diffuse)
Example #21
0
 def monthly_lt_nointerp(lat, lon, time=months):
     """monthly Linke turbidity factor without time interpolation"""
     return clearsky.lookup_linke_turbidity(
         time, lat, lon, interp_turbidity=False
     )
Example #22
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``. Allowed strategies include 'flat',
        'south_at_latitude_tilt'. Ignored for SingleAxisTracker systems.

    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:
        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.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'])

    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
Example #23
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
Example #24
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
Example #25
0
 def monthly_lt_nointerp(lat, lon, time=months):
     """monthly Linke turbidity factor without time interpolation"""
     return clearsky.lookup_linke_turbidity(
         time, lat, lon, interp_turbidity=False
     )
Example #26
0
def solar_irradiation(latitude, longitude, Z, moment, surface_tilt, 
                      surface_azimuth, T=None, P=None, solar_constant=1366.1,
                      atmos_refract=0.5667, albedo=0.25, linke_turbidity=None, 
                      extraradiation_method='spencer',
                      airmass_model='kastenyoung1989',
                      cache=None):
    r'''Calculates the amount of solar radiation and radiation reflected back
    the atmosphere which hits a surface at a specified tilt, and facing a
    specified azimuth. 
    
    This functions is a wrapper for the incredibly 
    comprehensive `pvlib library <https://github.com/pvlib/pvlib-python>`_, 
    and requires it to be installed.
    
    Parameters
    ----------
    latitude : float
        Latitude, between -90 and 90 [degrees]
    longitude : float
        Longitude, between -180 and 180, [degrees]
    Z : float, optional
        Elevation above sea level for the position, [m]
    moment : datetime
        Time and date for the calculation, in local UTC time (not daylight 
        savings time), [-]
    surface_tilt : float
        The angle above the horizontal of the object being hit by radiation,
        [degrees]
    surface_azimuth : float
        The angle the object is facing (positive North eastwards 0° to 360°),
        [degrees]
    T : float, optional
        Temperature of atmosphere at ground level, [K]
    P : float, optional
        Pressure of atmosphere at ground level, [Pa]
    solar_constant : float, optional
        The amount of solar radiation which reaches earth's disk (at a 
        standardized distance of 1 AU); this constant is independent of 
        activity or conditions on earth, but will vary throughout the sun's
        lifetime and may increase or decrease slightly due to solar activity,
        [W/m^2]
    atmos_refract : float, optional
        Atmospheric refractivity at sunrise/sunset (0.5667 deg is an often used
        value; this varies substantially and has an impact of a few minutes on 
        when sunrise and sunset is), [degrees]
    albedo : float, optional
        The average amount of reflection of the terrain surrounding the object
        at quite a distance; this impacts how much sunlight reflected off the
        ground, gest reflected back off clouds, [-]
    linke_turbidity : float, optional
        The amount of pollution/water in the sky versus a perfect clear sky;
        If not specified, this will be retrieved from a historical grid;
        typical values are 3 for cloudy, and 7 for severe pollution around a
        city, [-]
    extraradiation_method : str, optional
        The specified method to calculate the effect of earth's position on the
        amount of radiation which reaches earth according to the methods 
        available in the `pvlib` library, [-]
    airmass_model : str, optional
        The specified method to calculate the amount of air the sunlight
        needs to travel through to reach the earth according to the methods 
        available in the `pvlib` library, [-]
    cache : dict, optional
        Dictionary to to check for values to use to skip some calculations;
        `apparent_zenith`, `zenith`, `azimuth` supported, [-]

    Returns
    -------
    poa_global : float
        The total irradiance in the plane of the surface, [W/m^2]
    poa_direct : float
        The total beam irradiance in the plane of the surface, [W/m^2]
    poa_diffuse : float
        The total diffuse irradiance in the plane of the surface, [W/m^2]
    poa_sky_diffuse : float
        The sky component of the diffuse irradiance, excluding the impact 
        from the ground, [W/m^2]
    poa_ground_diffuse : float
        The ground-sky diffuse irradiance component, [W/m^2]

    Examples
    --------
    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07, 
    ... moment=datetime(2018, 4, 15, 13, 43, 5), surface_tilt=41.0, 
    ... surface_azimuth=180.0)
    (1065.7621896280812, 945.2656564506323, 120.49653317744884, 95.31535344213178, 25.181179735317063)
    
    >>> cache = {'apparent_zenith': 41.099082295767545, 'zenith': 41.11285376417578, 'azimuth': 182.5631874250523}
    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07, 
    ... moment=datetime(2018, 4, 15, 13, 43, 5), surface_tilt=41.0, 
    ... linke_turbidity=3, T=300, P=1E5,
    ... surface_azimuth=180.0, cache=cache)
    (1042.5677703677097, 918.2377548545295, 124.33001551318027, 99.6228657378363, 24.70714977534396)

    At night, there is no solar radiation and this function returns zeros:
        
    >>> solar_irradiation(Z=1100.0, latitude=51.0486, longitude=-114.07, 
    ... moment=datetime(2018, 4, 15, 2, 43, 5), surface_tilt=41.0, 
    ... surface_azimuth=180.0)
    (0.0, -0.0, 0.0, 0.0, 0.0)
    

    Notes
    -----    
    The retrieval of `linke_turbidity` requires the pytables library (and 
    Pandas); if it is not installed, specify a value of `linke_turbidity` to 
    avoid the dependency.
    
    There is some redundancy of the calculated results, according to the 
    following relations. The total irradiance is normally that desired for 
    engineering calculations.
    
    poa_diffuse = poa_ground_diffuse + poa_sky_diffuse
    
    poa_global = poa_direct + poa_diffuse
    
    FOr a surface such as a pipe or vessel, an approach would be to split it
    into a number of rectangles and sum up the radiation absorbed by each.
    
    This calculation is fairly slow. 

    References
    ----------
    .. [1] Will Holmgren, Calama-Consulting, Tony Lorenzo, Uwe Krien, bmu, 
       DaCoEx, mayudong, et al. Pvlib/Pvlib-Python: 0.5.1. Zenodo, 2017. 
       https://doi.org/10.5281/zenodo.1016425.
    '''
    # Atmospheric refraction at sunrise/sunset (0.5667 deg is an often used value)
    from fluids.optional import spa
    from fluids.optional.irradiance import (get_relative_airmass, get_absolute_airmass,
                                            ineichen, get_relative_airmass, 
                                            get_absolute_airmass, get_total_irradiance)
#    try:
#        import pvlib
#    except:
#        raise ImportError(PVLIB_MISSING_MSG)

    moment_timetuple = moment.timetuple()
    moment_arg_dni = (moment_timetuple.tm_yday if 
                      extraradiation_method == 'spencer' else moment)

    dni_extra = _get_extra_radiation_shim(moment_arg_dni, solar_constant=solar_constant, 
                               method=extraradiation_method, 
                               epoch_year=moment.year)
    
    if T is None or P is None:
        atmosphere = ATMOSPHERE_NRLMSISE00(Z=Z, latitude=latitude, 
                                           longitude=longitude, 
                                           day=moment_timetuple.tm_yday)
        if T is None:
            T = atmosphere.T
        if P is None:
            P = atmosphere.P
    
    if cache is not None and 'zenith' in cache:
        zenith = cache['zenith']
        apparent_zenith = cache['apparent_zenith']
        azimuth = cache['azimuth']
    else:
        apparent_zenith, zenith, _, _, azimuth, _ = solar_position(moment=moment,
                                                                   latitude=latitude, 
                                                                   longitude=longitude,
                                                                   Z=Z, T=T, P=P, 
                                                                   atmos_refract=atmos_refract)
    
    if linke_turbidity is None:
        from pvlib.clearsky import lookup_linke_turbidity
        import pandas as pd
        linke_turbidity = float(lookup_linke_turbidity(
            pd.DatetimeIndex([moment]), latitude, longitude).values)

        
    if airmass_model in apparent_zenith_airmass_models:
        used_zenith = apparent_zenith
    elif airmass_model in true_zenith_airmass_models:
        used_zenith = zenith
    else:
        raise Exception('Unrecognized airmass model')
    
    relative_airmass = get_relative_airmass(used_zenith, model=airmass_model)
    airmass_absolute = get_absolute_airmass(relative_airmass, pressure=P)


    ans = ineichen(apparent_zenith=apparent_zenith,
                   airmass_absolute=airmass_absolute, 
                   linke_turbidity=linke_turbidity,
                   altitude=Z, dni_extra=solar_constant, perez_enhancement=True)
    ghi = ans['ghi']
    dni = ans['dni']
    dhi = ans['dhi']
    
    
#    from pvlib.irradiance import get_total_irradiance
    ans = get_total_irradiance(surface_tilt=surface_tilt, 
                      surface_azimuth=surface_azimuth,
                      solar_zenith=apparent_zenith, solar_azimuth=azimuth,
                      dni=dni, ghi=ghi, dhi=dhi, dni_extra=dni_extra, 
                      airmass=airmass_absolute, albedo=albedo)
    poa_global = float(ans['poa_global'])
    poa_direct = float(ans['poa_direct'])
    poa_diffuse = float(ans['poa_diffuse'])
    poa_sky_diffuse = float(ans['poa_sky_diffuse'])
    poa_ground_diffuse = float(ans['poa_ground_diffuse'])
    return (poa_global, poa_direct, poa_diffuse, poa_sky_diffuse, 
            poa_ground_diffuse)