Esempio n. 1
0
def test_airmass(model, expected, zeniths):
    out = atmosphere.get_relative_airmass(zeniths, model)
    expected = np.array(expected)
    assert_allclose(out, expected, equal_nan=True, atol=0.001)
    # test series in/out. index does not matter
    # hits the isinstance() block in get_relative_airmass
    times = pd.date_range(start='20180101', periods=len(zeniths), freq='1s')
    zeniths = pd.Series(zeniths, index=times)
    expected = pd.Series(expected, index=times)
    out = atmosphere.get_relative_airmass(zeniths, model)
    assert_series_equal(out, expected, check_less_precise=True)
Esempio n. 2
0
def test_airmass(model, expected, zeniths):
    out = atmosphere.get_relative_airmass(zeniths, model)
    expected = np.array(expected)
    assert_allclose(out, expected, equal_nan=True, atol=0.001)
    # test series in/out. index does not matter
    # hits the isinstance() block in get_relative_airmass
    times = pd.date_range(start='20180101', periods=len(zeniths), freq='1s')
    zeniths = pd.Series(zeniths, index=times)
    expected = pd.Series(expected, index=times)
    out = atmosphere.get_relative_airmass(zeniths, model)
    assert_series_equal(out, expected, check_less_precise=True)
Esempio n. 3
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]
Esempio n. 4
0
def _air_mass(zenith, pressure):
    """
    Returns the absolute air mass.
    """

    # Methods from PvLib
    rel_am = get_relative_airmass(zenith=zenith)
    abs_am = get_absolute_airmass(rel_am, pressure=pressure)

    return abs_am
Esempio n. 5
0
 def test_airmass_default_post(self):
     am_data = {'zenith_data': AM_DATA['zenith_data']}
     r = self.client.post('/api/v1/pvlib/airmass/', am_data)
     self.assertEqual(r.status_code, 200)
     s = pd.Series(r.json())
     t = pd.DatetimeIndex(s.index)
     zdata = pd.read_json(ZDATA).T
     times = pd.DatetimeIndex(zdata.index)
     am = atmosphere.get_relative_airmass(zdata['apparent_zenith'])
     assert np.allclose(times.values.astype(int), t.values.astype(int))
     assert np.allclose(am, s)
Esempio n. 6
0
    def get_airmass(self,
                    times=None,
                    solar_position=None,
                    model='kastenyoung1989'):
        """
        Calculate the relative and absolute airmass.

        Automatically chooses zenith or apparant zenith
        depending on the selected model.

        Parameters
        ----------
        times : None or DatetimeIndex, default None
            Only used if solar_position is not provided.
        solar_position : None or DataFrame, default None
            DataFrame with with columns 'apparent_zenith', 'zenith'.
        model : str, default 'kastenyoung1989'
            Relative airmass model. See
            :py:func:`pvlib.atmosphere.get_relative_airmass`
            for a list of available models.

        Returns
        -------
        airmass : DataFrame
            Columns are 'airmass_relative', 'airmass_absolute'

        See also
        --------
        pvlib.atmosphere.get_relative_airmass
        """

        if solar_position is None:
            solar_position = self.get_solarposition(times)

        if model in atmosphere.APPARENT_ZENITH_MODELS:
            zenith = solar_position['apparent_zenith']
        elif model in atmosphere.TRUE_ZENITH_MODELS:
            zenith = solar_position['zenith']
        else:
            raise ValueError(f'{model} is not a valid airmass model')

        airmass_relative = atmosphere.get_relative_airmass(zenith, model)

        pressure = atmosphere.alt2pres(self.altitude)
        airmass_absolute = atmosphere.get_absolute_airmass(
            airmass_relative, pressure)

        airmass = pd.DataFrame(index=solar_position.index)
        airmass['airmass_relative'] = airmass_relative
        airmass['airmass_absolute'] = airmass_absolute

        return airmass
Esempio n. 7
0
def airmass_resource(request):
    if request.method == 'GET':
        params = AirmassForm(request.GET)
    else:
        params = AirmassForm(request.POST)
    if params.is_valid():
        zenith_data = params.cleaned_data['zenith_data']
        zenith_file = params.cleaned_data['zenith_file']
        filetype = params.cleaned_data['filetype']
        model = params.cleaned_data['model']
    else:
        return JsonResponse(params.errors, status=400)
    if filetype is None:
        filetype = 'json'
    if zenith_data is None and zenith_file is None:
        return JsonResponse(params.errors, status=400)
    if zenith_data:
        zenith_data = json.loads(zenith_data)
        if len(zenith_data) == 0:
            return JsonResponse(
                {"zenith_data": ["Invalid data in zenith data"]}, status=400)
        times = pd.DatetimeIndex(zenith_data.keys())  # keys not necessary
        columns = {}
        for row in zenith_data.values():
            if not columns:
                columns = {k: [float(v)] for k, v in row.items()}
            else:
                for k, v in row.items():
                    columns[k].append(float(v))
        zenith_data = pd.DataFrame(columns, index=times)
    if zenith_file and zenith_data is None:
        if filetype == 'json':
            zenith_data = pd.read_json(zenith_file)
        elif filetype == 'csv':
            zenith_data = pd.read_csv(zenith_file)
        elif filetype == 'xlsx':
            zenith_data = pd.read_excel(zenith_file)
        else:
            return JsonResponse(params.errors, status=400)
    if not model:
        model = 'kastenyoung1989'
    apparent_or_true = APPARENT_OR_TRUE.get(model)
    if not apparent_or_true:
        return JsonResponse(params.errors, status=400)
    am = atmosphere.get_relative_airmass(zenith_data[apparent_or_true], model)
    am.fillna(-9999.9, inplace=True)
    am.index = times.strftime('%Y-%m-%dT%H:%M:%S%z')
    data = am.to_dict()
    return JsonResponse(data)
Esempio n. 8
0
    def __init__(self, lat, lon, elevation, date):
        # Must be longer than a day to make sure we see a continuous cycle
        index = pd.date_range(start=date, freq='1s', periods=24 * 60 * 60 * 2)

        # Generate solar position df
        self.solar_df = solarposition.get_solarposition(index, lat, lon)

        # generate sky df
        solpos = solarposition.get_solarposition(index, lat, lon)
        apparent_zenith = solpos['apparent_zenith']
        airmass = atmosphere.get_relative_airmass(apparent_zenith)
        pressure = pvlib.atmosphere.alt2pres(elevation)
        airmass = pvlib.atmosphere.get_absolute_airmass(airmass, pressure)
        linke_turbidity = pvlib.clearsky.lookup_linke_turbidity(
            index, lat, lon)
        dni_extra = pvlib.irradiance.get_extra_radiation(index)
        self.sky_df = clearsky.ineichen(apparent_zenith, airmass,
                                        linke_turbidity, elevation, dni_extra)
Esempio n. 9
0
    def get_airmass(self, times=None, solar_position=None,
                    model='kastenyoung1989'):
        """
        Calculate the relative and absolute airmass.

        Automatically chooses zenith or apparant zenith
        depending on the selected model.

        Parameters
        ----------
        times : None or DatetimeIndex, default None
            Only used if solar_position is not provided.
        solar_position : None or DataFrame, default None
            DataFrame with with columns 'apparent_zenith', 'zenith'.
        model : str, default 'kastenyoung1989'
            Relative airmass model

        Returns
        -------
        airmass : DataFrame
            Columns are 'airmass_relative', 'airmass_absolute'
        """

        if solar_position is None:
            solar_position = self.get_solarposition(times)

        if model in atmosphere.APPARENT_ZENITH_MODELS:
            zenith = solar_position['apparent_zenith']
        elif model in atmosphere.TRUE_ZENITH_MODELS:
            zenith = solar_position['zenith']
        else:
            raise ValueError('{} is not a valid airmass model'.format(model))

        airmass_relative = atmosphere.get_relative_airmass(zenith, model)

        pressure = atmosphere.alt2pres(self.altitude)
        airmass_absolute = atmosphere.get_absolute_airmass(airmass_relative,
                                                           pressure)

        airmass = pd.DataFrame(index=solar_position.index)
        airmass['airmass_relative'] = airmass_relative
        airmass['airmass_absolute'] = airmass_absolute

        return airmass
Esempio n. 10
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
Esempio n. 11
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)
Esempio n. 12
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)
Esempio n. 13
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))
Esempio n. 14
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')

    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
Esempio n. 15
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)
Esempio n. 16
0
def test_airmass(model):
    out = atmosphere.get_relative_airmass(ephem_data['zenith'], model)
    assert isinstance(out, pd.Series)
    out = atmosphere.get_relative_airmass(ephem_data['zenith'].values, model)
    assert isinstance(out, np.ndarray)
Esempio n. 17
0
ax = solar_df.loc[solar_df.index,
                  ['apparent_zenith', 'apparent_elevation', 'azimuth']].plot()
ax.legend(loc=1)
ax.axhline(0, color='darkgray')
# add 0 deg line for sunrise/sunset
ax.axhline(180, color='darkgray')
# add 180 deg line for azimuth at solar noon
ax.set_ylim(-60, 200)
# zoom in, but cuts off full azimuth range
ax.set_xlabel('Time (UTC)')
ax.set_ylabel('(degrees)')

solpos = solarposition.get_solarposition(index, lat, lon)
apparent_zenith = solpos['apparent_zenith']
airmass = atmosphere.get_relative_airmass(apparent_zenith)
pressure = pvlib.atmosphere.alt2pres(alt)
airmass = pvlib.atmosphere.get_absolute_airmass(airmass, pressure)
linke_turbidity = pvlib.clearsky.lookup_linke_turbidity(index, lat, lon)
dni_extra = pvlib.irradiance.get_extra_radiation(index)
sky_df = clearsky.ineichen(apparent_zenith, airmass, linke_turbidity, alt,
                           dni_extra)

#trim sky df
sky_df = sky_df.drop(sky_df[sky_df.index < left].index)
sky_df = sky_df.drop(sky_df[sky_df.index > right].index)
print(sky_df)

plt.figure()

ax = sky_df.plot()
Esempio n. 18
0
def test_airmass_scalar():
    assert not np.isnan(atmosphere.get_relative_airmass(10))
Esempio n. 19
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)

effective_irradiance = pvsystem.sapm_effective_irradiance(poa_irrad.poa_direct,
Esempio n. 20
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)
Esempio n. 21
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)
Esempio n. 22
0
def test_airmass_invalid():
    with pytest.raises(ValueError):
        atmosphere.get_relative_airmass(ephem_data['zenith'], 'invalid')
Esempio n. 23
0
def test_get_absolute_airmass():
    relative_am = atmosphere.get_relative_airmass(ephem_data['zenith'],
                                                  'simple')
    atmosphere.get_absolute_airmass(relative_am)
    atmosphere.get_absolute_airmass(relative_am, pressure=100000)
tilt = 37
azimuth = 180
pressure = 101300  # sea level, roughly
water_vapor_content = 0.5  # cm
tau500 = 0.1
ozone = 0.31  # atm-cm
albedo = 0.2

times = pd.date_range('1984-03-20 06:17', freq='h', periods=6, tz='Etc/GMT+7')
solpos = solarposition.get_solarposition(times, lat, lon)
aoi = irradiance.aoi(tilt, azimuth, solpos.apparent_zenith, solpos.azimuth)

# The technical report uses the 'kasten1966' airmass model, but later
# versions of SPECTRL2 use 'kastenyoung1989'.  Here we use 'kasten1966'
# for consistency with the technical report.
relative_airmass = atmosphere.get_relative_airmass(solpos.apparent_zenith,
                                                   model='kasten1966')

# %%
# With all the necessary inputs in hand we can model spectral irradiance using
# :py:func:`pvlib.spectrum.spectrl2`.  Note that because we are calculating
# the spectra for more than one set of conditions, we will get back 2-D
# arrays (one dimension for wavelength, one for time).

spectra = spectrum.spectrl2(
    apparent_zenith=solpos.apparent_zenith,
    aoi=aoi,
    surface_tilt=tilt,
    ground_albedo=albedo,
    surface_pressure=pressure,
    relative_airmass=relative_airmass,
    precipitable_water=water_vapor_content,
Esempio n. 25
0
def test_airmass_invalid():
    with pytest.raises(ValueError):
        atmosphere.get_relative_airmass(0, 'invalid')
Esempio n. 26
0
def get_airmass(solpos):
    # Calculate airmass. Lots of model options here, see the ``atmosphere`` module tutorial for more details.
    airmass = atmosphere.get_relative_airmass(solpos['apparent_zenith'])
    return airmass
Esempio n. 27
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
Esempio n. 28
0
def test_airmass_scalar():
    assert not np.isnan(atmosphere.get_relative_airmass(10))
Esempio n. 29
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)
Esempio n. 30
0
def test_airmass_invalid():
    with pytest.raises(ValueError):
        atmosphere.get_relative_airmass(0, 'invalid')
def calculate_overcast_spectrl2():
    """
    This example will loop over a range of cloud covers and latitudes
    (at longitude=0) for a specific date and calculate the spectral
    irradiance with and without accounting for clouds. Clouds are accounted for
    by applying the cloud opacity factor defined in [1]. Several steps
    are required:
    1. Calculate the atmospheric and solar conditions for the
    location and time
    2. Calculate the spectral irradiance using `pvlib.spectrum.spectrl2`
    for clear sky conditions
    3. Calculate the dni, dhi, and ghi for cloudy conditions using
    `pvlib.irradiance.campbell_norman`
    4. Determine total in-plane irradiance and its beam,
    sky diffuse and ground
    reflected components for cloudy conditions -
    `pvlib.irradiance.get_total_irradiance`
    5. Calculate the dni, dhi, and ghi for clear sky conditions
    using `pvlib.irradiance.campbell_norman`
    6. Determine total in-plane irradiance and its beam,
    sky diffuse and ground
    reflected components for clear sky conditions -
    `pvlib.irradiance.get_total_irradiance`
    7. Calculate the cloud opacity factor [1] and scale the
    spectral results from step 4 - func cloud_opacity_factor
    8. Plot the results  - func plot_spectral_irradiance
    """
    month = 2
    hour_of_day = 12
    altitude = 0.0
    longitude = 0.0
    latitudes = [10, 40]

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

    ctime, pv_system = setup_pv_system(month, hour_of_day)

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

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

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

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

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

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

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

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

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

            plot_spectral_irr(spectra,
                              f_dir,
                              f_diff,
                              lat=latitude,
                              doy=day_of_year,
                              year=ctime.year[0],
                              clouds=cloud_cover)
Esempio n. 32
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