Exemple #1
0
def _solpos_night(observation, values):
    solar_position = pvmodel.calculate_solar_position(
        observation.site.latitude, observation.site.longitude,
        observation.site.elevation, values.index)
    night_flag = validator.check_irradiance_day_night(solar_position['zenith'],
                                                      _return_mask=True)
    return solar_position, night_flag
Exemple #2
0
def _solpos_dni_extra(observation, values):
    solar_position = pvmodel.calculate_solar_position(
        observation.site.latitude, observation.site.longitude,
        observation.site.elevation, values.index)
    dni_extra = get_extra_radiation(values.index)
    timestamp_flag = _validate_timestamp(observation, values)
    night_flag = validator.check_irradiance_day_night(solar_position['zenith'],
                                                      _return_mask=True)
    return solar_position, dni_extra, timestamp_flag, night_flag
Exemple #3
0
def _ghi_to_dni_dhi(latitude, longitude, elevation, ghi):
    """
    Calculate DNI, DHI from GHI and calculated solar position.
    """
    solar_position = pvmodel.calculate_solar_position(
        latitude, longitude, elevation, ghi.index)
    dni, dhi = pvmodel.complete_irradiance_components(
        ghi, solar_position['zenith'])

    def solar_pos_calculator(): return solar_position
    return dni, dhi, solar_pos_calculator
def test_calculate_solar_position(expected_solpos, golden_mst):
    times = pd.date_range(datetime.datetime(2003, 10, 17, 12, 30, 30),
                          periods=1,
                          freq='D',
                          tz=golden_mst.tz)
    solar_position = pvmodel.calculate_solar_position(golden_mst.latitude,
                                                      golden_mst.longitude,
                                                      golden_mst.altitude,
                                                      times)
    expected_solpos.index = times
    assert_frame_equal(expected_solpos,
                       solar_position[expected_solpos.columns],
                       check_less_precise=3)
def _solpos_night_resample(observation, values):
    # similar approach as in persistence_scalar_index.
    # Calculate solar position and clearsky at 1 minute resolution to
    # reduce errors from changing solar position during interval.
    # Later, nighttime bools will be resampled over the interval
    closed = datamodel.CLOSED_MAPPING[observation.interval_label]
    freq = pd.Timedelta('1min')
    interval_length = observation.interval_length
    # need to calculate solar position for instants before or after the
    # first/last labels depending on the interval label convention.
    obs_range = _resample_date_range(interval_length, closed, freq, values)
    # could add logic to remove points from obs_range where there are
    # gaps in values. that would reduce computation time in some situations
    solar_position = pvmodel.calculate_solar_position(
        observation.site.latitude, observation.site.longitude,
        observation.site.elevation, obs_range)
    # get the night flag as bitmask
    night_flag = validator.check_day_night_interval(
        solar_position['zenith'],
        closed,
        interval_length,
        solar_zenith_interval_length=freq,
        _return_mask=True)
    # Better to use average solar position in downstream functions
    # Best to return high res solar position and adapt downstream functions
    # but that is left for future work
    solar_position = solar_position.resample(interval_length,
                                             closed=closed,
                                             label=closed).mean()
    # return series with same index as input values
    # i.e. put any gaps back in the data
    try:
        night_flag = night_flag.loc[values.index]
        solar_position = solar_position.loc[values.index]
    except KeyError:
        raise KeyError(
            'Missing times when reindexing averaged flag or solar position to '
            'original data. Check that observation.interval_length is '
            'consistent with observation_values.index.')
    return solar_position, night_flag
Exemple #6
0
def _resample_using_cloud_cover(latitude, longitude, elevation,
                                cloud_cover, air_temperature, wind_speed,
                                start, end, interval_label,
                                fill_method, solar_position=None):
    """
    Calculate all irradiance components from cloud cover.

    Cloud cover from GFS is an interval average with ending label.
    Air temperature and wind speed are instantaneous values.
    Intervals are 1, 3, or 6 hours in length.

    Cloud cover, air temperature, and wind speed from RAP and NAM are
    instantaneous.

    To accurately convert from cloud cover to irradiance, we need to
    interpolate this data to subhourly resolution because solar position
    and PV power calculations assume instantaneous inputs at each time.

    Parameters
    ----------
    latitude : float
    longitude : float
    elevation : float
    cloud_cover : pd.Series
    air_temperature : pd.Series
    wind_speed : pd.Series
    start : pd.Timestamp
    end : pd.Timestamp
    interval_label : str
        beginning, ending, or instant
    fill_method : str
        'bfill' (recommended for GFS), 'interpolate' (recommended for
        NAM/RAP), or any other method of pd.Series.
    solar_position : pd.DataFrame or None
        Provide a DataFrame to avoid unnecessary recomputation for e.g.
        GEFS members. If None, solar position is computed.

    Returns
    -------
    ghi : pd.Series
    dni : pd.Series
    dhi : pd.Series
    air_temperature : pd.Series
    wind_speed : pd.Series
    resampler : function
    sol_pos_calculator : function
        When called, immediatedly returns pre-computed solar position.
    """
    # Resample cloud cover, temp, and wind to higher temporal resolution
    # because solar position and PV power calculations assume instantaneous
    # inputs. Why 5 minutes? It's a round number that produces order 10 data
    # points per hour, so it's reasonable for hour average calculations.
    # Cloud cover should be filled backwards for GFS because model output
    # represents average over the previous hour and interpolated for RAP and
    # NAM because model outputs represent instantaneous values. Air temperature
    # and wind are interpolated because model output represents
    # instantaneous values.
    freq = '5min'
    start_adj, end_adj = adjust_start_end_for_interval_label(interval_label,
                                                             start, end)
    cloud_cover = forecast.reindex_fill_slice(
        cloud_cover, freq=freq, start=start, end=end,
        start_slice=start_adj, end_slice=end_adj,
        fill_method=fill_method)
    resample_fill_slicer = partial(
        forecast.reindex_fill_slice, freq=freq, start=start, end=end,
        start_slice=start_adj, end_slice=end_adj, fill_method='interpolate')
    air_temperature, wind_speed = [
        resample_fill_slicer(v) for v in (air_temperature, wind_speed)
    ]
    if solar_position is None:
        solar_position = pvmodel.calculate_solar_position(
            latitude, longitude, elevation, cloud_cover.index)
    ghi, dni, dhi = forecast.cloud_cover_to_irradiance(
        latitude, longitude, elevation, cloud_cover,
        solar_position['apparent_zenith'], solar_position['zenith'])

    label = datamodel.CLOSED_MAPPING[interval_label]
    resampler = partial(forecast.resample, freq='1h', label=label)

    def solar_pos_calculator(): return solar_position

    return (ghi, dni, dhi, air_temperature, wind_speed,
            resampler, solar_pos_calculator)
metadata = datamodel.SolarPowerPlant(name='Boulder Power Plant',
                                     latitude=40.,
                                     longitude=-105.,
                                     elevation=1650.,
                                     timezone='America/Denver',
                                     provider='Sandia',
                                     modeling_parameters=modeling_params)

times = pd.date_range(start='20190801',
                      end='20191001',
                      freq='5min',
                      closed='left')

solpos = pvmodel.calculate_solar_position(metadata.latitude,
                                          metadata.longitude,
                                          metadata.elevation, times)
cs = pvmodel.calculate_clearsky(metadata.latitude, metadata.longitude,
                                metadata.elevation, solpos['apparent_zenith'])
ac_clear = pvmodel.irradiance_to_power(modeling_params,
                                       solpos['apparent_zenith'],
                                       solpos['azimuth'], cs['ghi'], cs['dni'],
                                       cs['dhi'])

ac_clear_1h = ac_clear.resample('1h').mean()
ac_clear_1h = pd.DataFrame({'value': ac_clear_1h, 'quality_flag': 0})
ac_clear_1h.to_csv('boulder_clear_aug_sept.csv', index_label='timestamp')

# make it cloudy, but apply clipping
random = np.random.random(size=len(times)) + 0.5
random = random.clip(max=1)