def _get_poa(data, solar_position): """ Return the radiation adjusted to Plane of Array (SkyDiffuse, GroundDiffuse, Total). """ extra_radiation = get_extra_radiation(data.data.index) # Best orientation for pv system surface_tilt = _surface_tilt(data.latitude) surface_azimuth = _surface_azimuth(data.latitude) # Sky Diffuse radiation (From PvLib) poa_diffuse = haydavies(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, dhi=data.data['Gd(h)'], dni=data.data['Gb(n)'], dni_extra=extra_radiation, solar_zenith=solar_position.apparent_zenith, solar_azimuth=solar_position.azimuth) # Ground Diffuse radiation (From PvLib) poa_ground = get_ground_diffuse(data.latitude, data.data['G(h)'], surface_type='urban') # Angle of incidence at best orientation _aoi = aoi(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, solar_zenith=solar_position.apparent_zenith, solar_azimuth=solar_position.apparent_zenith) # Total radiation at plane of the pv array. poa_total = poa_components(aoi=_aoi, dni=data.data['Gb(n)'], poa_sky_diffuse=poa_diffuse, poa_ground_diffuse=poa_ground) return poa_total, _aoi
def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): aoi = irradiance.aoi(40, 180, ephem_data['apparent_zenith'], ephem_data['azimuth']) gr_sand = irradiance.get_ground_diffuse(40, irrad_data['ghi'], surface_type='sand') diff_perez = irradiance.perez(40, 180, irrad_data['dhi'], irrad_data['dni'], dni_et, ephem_data['apparent_zenith'], ephem_data['azimuth'], relative_airmass) out = irradiance.poa_components(aoi, irrad_data['dni'], diff_perez, gr_sand) expected = pd.DataFrame(np.array( [[0., -0., 0., 0., 0.], [35.19456561, 0., 35.19456561, 31.4635077, 3.73105791], [956.18253696, 798.31939281, 157.86314414, 109.08433162, 48.77881252], [90.99624896, 33.50143401, 57.49481495, 45.45978964, 12.03502531]]), columns=[ 'poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse' ], index=irrad_data.index) assert_frame_equal(out, expected)
def test_poa_components(irrad_data, ephem_data, dni_et, relative_airmass): aoi = irradiance.aoi(40, 180, ephem_data['apparent_zenith'], ephem_data['azimuth']) gr_sand = irradiance.get_ground_diffuse(40, irrad_data['ghi'], surface_type='sand') diff_perez = irradiance.perez( 40, 180, irrad_data['dhi'], irrad_data['dni'], dni_et, ephem_data['apparent_zenith'], ephem_data['azimuth'], relative_airmass) out = irradiance.poa_components( aoi, irrad_data['dni'], diff_perez, gr_sand) expected = pd.DataFrame(np.array( [[ 0. , -0. , 0. , 0. , 0. ], [ 35.19456561, 0. , 35.19456561, 31.4635077 , 3.73105791], [956.18253696, 798.31939281, 157.86314414, 109.08433162, 48.77881252], [ 90.99624896, 33.50143401, 57.49481495, 45.45978964, 12.03502531]]), columns=['poa_global', 'poa_direct', 'poa_diffuse', 'poa_sky_diffuse', 'poa_ground_diffuse'], index=irrad_data.index) assert_frame_equal(out, expected)
def test_grounddiffuse_albedo_invalid_surface(irrad_data): with pytest.raises(KeyError): irradiance.get_ground_diffuse(40, irrad_data['ghi'], surface_type='invalid')
def test_grounddiffuse_albedo_0(irrad_data): ground_irrad = irradiance.get_ground_diffuse(40, irrad_data['ghi'], albedo=0) assert 0 == ground_irrad.all()
def test_grounddiffuse_simple_series(irrad_data): ground_irrad = irradiance.get_ground_diffuse(40, irrad_data['ghi']) assert ground_irrad.name == 'diffuse_ground'
def test_grounddiffuse_simple_float(): result = irradiance.get_ground_diffuse(40, 900) assert_allclose(result, 26.32000014911496)
def test_grounddiffuse_albedo_surface(irrad_data): result = irradiance.get_ground_diffuse(40, irrad_data['ghi'], surface_type='sand') assert_allclose(result, [0, 3.731058, 48.778813, 12.035025], atol=1e-4)
def get_poa_ground_diffuse(surface_tilt, forecast_data, albedo): # Calculate ground diffuse. We specified the albedo above. You could have also provided a string to the ``surface_type`` keyword argument. poa_ground_diffuse = irradiance.get_ground_diffuse(surface_tilt, forecast_data['ghi'], albedo=albedo) return poa_ground_diffuse
def simulate_power_by_station(station_index, surface_tilt, surface_azimuth, pv_module, tcell_model_parameters, ghi, tamb, wspd, albedo, days, lead_times, air_mass, dni_extra, zenith, apparent_zenith, azimuth): """ This is the worker function for simulating power at a specified location. This function should be used inside of `simulate_power` and direct usage is discouraged. :param station_index: A station index :param ghi: See `simulate_power` :param tamb: See `simulate_power` :param wspd: See `simulate_power` :param albedo: See `simulate_power` :param days: See `simulate_power` :param lead_times: See `simulate_power` :param air_mass: See `simulate_power` :param dni_extra: See `simulate_power` :param zenith: See `simulate_power` :param apparent_zenith: See `simulate_power` :param azimuth: See `simulate_power` :param surface_tilt: See `simulate_power` :param surface_azimuth: See `simulate_power` :param pv_module: A PV module name :param tcell_model_parameters: A cell module name :return: A list with power, cell temperature, and the effective irradiance """ # Sanity check assert 0 <= station_index < ghi.shape[3], 'Invalid station index' # Determine the dimensions num_analogs = ghi.shape[0] num_lead_times = ghi.shape[1] num_days = ghi.shape[2] # Initialization p_mp = np.zeros((num_analogs, num_lead_times, num_days)) tcell = np.zeros((num_analogs, num_lead_times, num_days)) effective_irradiance = np.zeros((num_analogs, num_lead_times, num_days)) pv_module = pvsystem.retrieve_sam("SandiaMod")[pv_module] tcell_model_parameters = temperature.TEMPERATURE_MODEL_PARAMETERS["sapm"][ tcell_model_parameters] 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') for analog_index in range(num_analogs): ghi_ = ghi[analog_index, lead_time_index, day_index, station_index] if ghi_ == 0: continue albedo_ = albedo[analog_index, lead_time_index, day_index, station_index] wspd_ = wspd[analog_index, lead_time_index, day_index, station_index] tamb_ = tamb[analog_index, lead_time_index, day_index, station_index] air_mass_ = air_mass[lead_time_index, day_index, station_index] dni_extra_ = dni_extra[lead_time_index, day_index, station_index] zenith_ = zenith[lead_time_index, day_index, station_index] apparent_zenith_ = apparent_zenith[lead_time_index, day_index, station_index] azimuth_ = azimuth[lead_time_index, day_index, station_index] ########################################################################################## # # # Core procedures of simulating power at one location # # # ########################################################################################## # Decompose DNI from GHI dni_dict = irradiance.disc(ghi_, zenith_, current_time) # Calculate POA sky diffuse poa_sky_diffuse = irradiance.haydavies( surface_tilt, surface_azimuth, ghi_, dni_dict["dni"], dni_extra_, apparent_zenith_, azimuth_) # Calculate POA ground diffuse poa_ground_diffuse = irradiance.get_ground_diffuse( surface_tilt, ghi_, albedo_) # Calculate angle of incidence aoi = irradiance.aoi(surface_tilt, surface_azimuth, apparent_zenith_, azimuth_) # Calculate POA total poa_irradiance = irradiance.poa_components( aoi, dni_dict["dni"], poa_sky_diffuse, poa_ground_diffuse) # Calculate cell temperature tcell[analog_index, lead_time_index, day_index] = pvsystem.temperature.sapm_cell( poa_irradiance['poa_global'], tamb_, wspd_, tcell_model_parameters['a'], tcell_model_parameters['b'], tcell_model_parameters["deltaT"]) # Calculate effective irradiance effective_irradiance[ analog_index, lead_time_index, day_index] = pvsystem.sapm_effective_irradiance( poa_irradiance['poa_direct'], poa_irradiance['poa_diffuse'], air_mass_, aoi, pv_module) # Calculate power sapm_out = pvsystem.sapm( effective_irradiance[analog_index, lead_time_index, day_index], tcell[analog_index, lead_time_index, day_index], pv_module) # Save output to numpy p_mp[analog_index, lead_time_index, day_index] = sapm_out["p_mp"] return [p_mp, tcell, effective_irradiance]
def time_get_ground_diffuse(self): irradiance.get_ground_diffuse(self.tilt, self.clearsky_irradiance.ghi)
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, poa_irrad.poa_diffuse, airmass, aoi, sandia_module) sapm_out = pvsystem.sapm(effective_irradiance, pvtemps['temp_cell'], sandia_module) # print(sapm_out.head()) print(sapm_out['p_mp']) plot = "pop"
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)