def test_sapm_celltemp_dict_like(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_almost_equals(43.509, default.ix[0, 'temp_cell'], 3) assert_almost_equals(40.809, default.ix[0, 'temp_module'], 3) model = {'a':-3.47, 'b':-.0594, 'deltaT':3} assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, model)) model = pd.Series(model) assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, model))
def test_sapm_celltemp_dict_like(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_allclose(default['temp_cell'], 43.509, 3) assert_allclose(default['temp_module'], 40.809, 3) model = {'a': -3.47, 'b': -.0594, 'deltaT': 3} assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, model)) model = pd.Series(model) assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, model))
def test_sapm_celltemp_with_index(): times = pd.DatetimeIndex(start="2015-01-01", end="2015-01-02", freq="12H") temps = pd.Series([0, 10, 5], index=times) irrads = pd.Series([0, 500, 0], index=times) winds = pd.Series([10, 5, 0], index=times) pvtemps = pvsystem.sapm_celltemp(irrads, winds, temps) expected = pd.DataFrame({"temp_cell": [0.0, 23.06066166, 5.0], "temp_module": [0.0, 21.56066166, 5.0]}, index=times) assert_frame_equal(expected, pvtemps)
def _add_cell_module_temp(sys_df, mod): if 'wind_speed' not in sys_df.keys(): sys_df['wind_speed'] = 0 vals = pvsystem.sapm_celltemp(sys_df['g_poa'], sys_df['wind_speed'], sys_df['temp_air'], mod) for key in vals.keys(): sys_df[key] = vals[key] return sys_df
def test_sapm_celltemp_with_index(): times = pd.DatetimeIndex(start='2015-01-01', end='2015-01-02', freq='12H') temps = pd.Series([0, 10, 5], index=times) irrads = pd.Series([0, 500, 0], index=times) winds = pd.Series([10, 5, 0], index=times) pvtemps = pvsystem.sapm_celltemp(irrads, winds, temps) expected = pd.DataFrame({'temp_cell':[0., 23.06066166, 5.], 'temp_module':[0., 21.56066166, 5.]}, index=times) assert_frame_equal(expected, pvtemps)
def get_perfect_voltage_for_a_day(start, freq): """This method is used to build a pandas serie with voltage values. This serie has DateTime index and contains a value for every "freq" seconds during 24 hours starting from "start" date. There are several assumptions: 1. Location is Munich 2. A battery is pointing to the south, amount of blocks is 20 3. Sandia Module database is used 4. pvlib library is heavily used :param start: datetime. First timestamp in result series :param freq: str. How often voltage should be sampled :return: voltage : Series """ surface_tilt = _munich_location.latitude surface_azimuth = 180 # pointing south date_range = pd.date_range(start=start, end=start + dt.timedelta( hours=23, minutes=59, seconds=59), freq=freq, tz=_munich_location.tz) clearsky_estimations = _munich_location.get_clearsky(date_range) dni_extra = irradiance.extraradiation(date_range) solar_position = solarposition.get_solarposition( date_range, _munich_location.latitude, _munich_location.longitude) airmass = atmosphere.relativeairmass(solar_position['apparent_zenith']) pressure = atmosphere.alt2pres(_munich_location.altitude) am_abs = atmosphere.absoluteairmass(airmass, pressure) total_irrad = irradiance.total_irrad(surface_tilt, surface_azimuth, solar_position['apparent_zenith'], solar_position['azimuth'], clearsky_estimations['dni'], clearsky_estimations['ghi'], clearsky_estimations['dhi'], dni_extra=dni_extra, model='haydavies') temps = pvsystem.sapm_celltemp(total_irrad['poa_global'], 0, 15) aoi = irradiance.aoi(surface_tilt, surface_azimuth, solar_position['apparent_zenith'], solar_position['azimuth']) # add 0.0001 to avoid np.log(0) and warnings about that effective_irradiance = pvsystem.sapm_effective_irradiance( total_irrad['poa_direct'], total_irrad['poa_diffuse'], am_abs, aoi, _sandia_module) + 0.0001 sapm = pvsystem.sapm(effective_irradiance, temps['temp_cell'], _sandia_module) return sapm['p_mp'] * _module_count
def calc_t_cell(L: np.ndarray, T_am: float, W_10: float, model: str = 'roof_mount_cell_glassback'): """Wrapper function for cell temperature calculation Args: L (np.ndarray): Irradiance in kw. T_am (float): Ambient temperature. W_10 (float): Windspeed @10 meter. model (str): Defaults to 'roof_mount_cell_glassback'. Returns: float: Cell temperature in Kelvin. """ return pvsystem.sapm_celltemp( np.sum(np.hstack(L)) / np.size(np.hstack(L)) * 1e3, W_10, T_am, )['temp_cell'][0]
def test_sapm_celltemp(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_allclose(default['temp_cell'], 43.509, 3) assert_allclose(default['temp_module'], 40.809, 3) assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, [-3.47, -.0594, 3]))
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)
def test_sapm_celltemp(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_almost_equals(43.509, default.ix[0, 'temp_cell'], 3) assert_almost_equals(40.809, default.ix[0, 'temp_module'], 3) assert_frame_equal(default, pvsystem.sapm_celltemp(900, 5, 20, [-3.47, -.0594, 3]))
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
def temp(poa_irrad, forecast_data): pvtemps = pvsystem.sapm_celltemp(poa_irrad['poa_global'], forecast_data['wind_speed'], forecast_data['temp_air']) return (pvtemps)
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" # sapm_out[['p_mp']].plot() # plt.ylabel('DC Power (W)') # plot = plt.savefig('tmp.png') # sapm_inverters = pvsystem.retrieve_sam('sandiainverter') # sapm_inverter = sapm_inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'] # p_ac = pvsystem.snlinverter(sapm_out.v_mp, sapm_out.p_mp, sapm_inverter) #
solpos['apparent_zenith'], solpos['azimuth'], cs['dni'], cs['ghi'], cs['dhi'], dni_extra=dni_extra, model='haydavies') # dictionary of a bunch of existing solar panels and their specifications sandia_modules = pvsystem.retrieve_sam(name='SandiaMod') # get specific panle info sandia_module = sandia_modules.Canadian_Solar_CS5P_220M___2009_ module = sandia_module # a sunny, calm, and hot day in the desert temps = pvsystem.sapm_celltemp(total_irrad['poa_global'], 0, 30) effective_irradiance = pvlib.pvsystem.sapm_effective_irradiance( total_irrad['poa_direct'], total_irrad['poa_diffuse'], am_abs, aoi, module) effective_irradiance.plot() plt.show() ''' GRAPH KEY: i_sc : Short-circuit current (A) i_mp : Current at the maximum-power point (A) v_oc : Open-circuit voltage (V) v_mp : Voltage at maximum-power point (V) p_mp : Power at maximum-power point (W) i_x : Current at module V = 0.5Voc, defines 4th point on I-V curve for modeling curve shape i_xx : Current at module V = 0.5(Voc+Vmp), defines 5th point on I-V curve for modeling curve shape '''
def test_sapm_celltemp(): default = pvsystem.sapm_celltemp(900, 5, 20) assert_almost_equals(43.509, default['tcell'], 3) assert_almost_equals(40.809, default['tmodule'], 3) assert_equals(default, pvsystem.sapm_celltemp(900, 5, 20, [-3.47, -.0594, 3]))
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``. 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: irradiance = clearsky.ineichen( solar_position.index, latitude, longitude, zenith_data=solar_position['apparent_zenith'], airmass_data=airmass, altitude=altitude) 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']) dc = pvsystem.sapm(module_parameters, total_irrad['poa_direct'], total_irrad['poa_diffuse'], temps['temp_cell'], airmass, aoi) ac = pvsystem.snlinverter(inverter_parameters, dc['v_mp'], dc['p_mp']) return dc, ac