def apply_decomposition_model(weather_df, model, location): """ Uses the specified decomposition model to calculate DNI and DHI. Parameters ---------- weather_df : :pandas:`DataFrame` Weather DataFrame containing all variables needed to apply the decomposition model. See model functions for more information. model : :obj:`str` Decomposition model to use. Choose from 'reindl', 'erbs' or 'disc'. location : :pvlib:`Location` Returns ------- :pandas:`DataFrame` DataFrame with DNI and DHI. """ solar_position = location.get_solarposition( weather_df.index, pressure=weather_df['pressure'].mean(), temperature=weather_df['temp_air'].mean()) if model == 'reindl': solar_position = location.get_solarposition( weather_df.index, pressure=weather_df['pressure'].mean(), temperature=weather_df['temp_air'].mean()) df = reindl(weather_df.ghi, weather_df.i0_h, solar_position.elevation) df['dni_corrected'] = irradiance.dni( weather_df['ghi'], df['dhi'], solar_position.zenith, clearsky_dni=location.get_clearsky( weather_df.index, solar_position=solar_position).dni, clearsky_tolerance=1.1, zenith_threshold_for_zero_dni=88.0, zenith_threshold_for_clearsky_limit=80.0) elif model == 'erbs': df = irradiance.erbs(weather_df.ghi, solar_position.zenith, weather_df.index) df['dni_corrected'] = irradiance.dni( weather_df['ghi'], df['dhi'], solar_position.zenith, clearsky_dni=location.get_clearsky( weather_df.index, solar_position=solar_position).dni, clearsky_tolerance=1.1, zenith_threshold_for_zero_dni=88.0, zenith_threshold_for_clearsky_limit=80.0) elif model == 'disc': df = irradiance.disc(weather_df.ghi, solar_position.zenith, weather_df.index, weather_df.pressure.mean()) df['dhi'] = weather_df.ghi - df.dni * pvlib.tools.cosd( solar_position.zenith) df['gni'] = df.dni + df.dhi return df
def test_dni(): ghi = pd.Series([90, 100, 100, 100, 100]) dhi = pd.Series([100, 90, 50, 50, 50]) zenith = pd.Series([80, 100, 85, 70, 85]) clearsky_dni = pd.Series([50, 50, 200, 50, 300]) dni = irradiance.dni(ghi, dhi, zenith, clearsky_dni=clearsky_dni, clearsky_tolerance=2) assert_series_equal(dni, pd.Series([float('nan'), float('nan'), 400, 146.190220008, 573.685662283])) dni = irradiance.dni(ghi, dhi, zenith) assert_series_equal(dni, pd.Series([float('nan'), float('nan'), 573.685662283, 146.190220008, 573.685662283]))
def test_dni(): ghi = pd.Series([90, 100, 100, 100, 100]) dhi = pd.Series([100, 90, 50, 50, 50]) zenith = pd.Series([80, 100, 85, 70, 85]) clearsky_dni = pd.Series([50, 50, 200, 50, 300]) dni = irradiance.dni(ghi, dhi, zenith, clearsky_dni=clearsky_dni, clearsky_tolerance=2) assert_series_equal(dni, pd.Series([float('nan'), float('nan'), 400, 146.190220008, 573.685662283])) dni = irradiance.dni(ghi, dhi, zenith) assert_series_equal(dni, pd.Series([float('nan'), float('nan'), 573.685662283, 146.190220008, 573.685662283]))
def calculate_dni_pvlib(weather_df, corrected=True): """ Calculates DNI from open_FRED GHI and DHI using the pvlib. :param weather_df: :param corrected: :return: """ # calculate DNI times = weather_df.index location = read_htw_data.setup_pvlib_location_object() solarposition = location.get_solarposition( times, pressure=None, temperature=weather_df['temp_air']) if corrected: # calculate corrected DNI clearsky = location.get_clearsky(times, solar_position=solarposition) dni = irradiance.dni(weather_df['ghi'], weather_df['dhi'], zenith=solarposition['zenith'], clearsky_dni=clearsky['dni'], clearsky_tolerance=1.1, zenith_threshold_for_zero_dni=88.0, zenith_threshold_for_clearsky_limit=80.0) else: dni = (weather_df['ghi'] - weather_df['dhi']) / np.cos( np.radians(solarposition['zenith'])) # setup df with calculated and Fred DNI dni.name = 'dni' df = weather_df['dni'].to_frame().join( dni.to_frame(), lsuffix='_fred', rsuffix='_pvlib') dni.set_index('time', inplace=True) return df
def reindl (lat,lon, times, ghi, extra_i, zenith): """ this function calculates dhi, dni and the clearness index kt from ghi, extraterrestial_irradiance and the solar zenith propsed by Merra2 [1] Parameters ----------- ghi: numeric pd.Series or sequence global horizontal irradiance [W/m^2] zenith: numeric pd.Series or sequence real solar zenith angle (not apparent) in [°] extra_i: numeric pd.Series or sequence extraterrestial irradiance [W/m^2] == top-of-the-atmosphere irradiance (TOA) == SWTDN (Merra-2) Returns ------- data : OrderedDict or DataFrame Contains the following keys/columns: * ``dni``: the modeled direct normal irradiance in W/m^2. * ``dhi``: the modeled diffuse horizontal irradiance in W/m^2. * ``kt``: Ratio of global to extraterrestrial irradiance on a horizontal plane. References ----------- [1] Reindl et al. (1990): Diffuse fraction correlations """ i0_h = extra_i * tools.cosd(zenith) kt = ghi / i0_h kt = np.maximum(kt, 0) kt.fillna(0, inplace=True) # for kt outside the boundaries, set diffuse fraction to zero df = 0.0 # for 0<kt<=0.3 set diffuse fraction df = np.where((kt > 0) & (kt <= 0.3), 1.02 - 0.254 * kt + 0.0123 * tools.cosd(zenith), df) # for 0.3<kt<0.78 and df>=0.1, set diffuse fraction df = np.where((kt > 0.3) & (kt <= 0.78) & (1.4 - 1.794 * kt + 0.177 * tools.cosd(zenith) >= 0.1), 1.4 - 1.794 * kt + 0.177 * tools.cosd(zenith), df) # for kt > 0.78 and df>=0.1 df = np.where((kt > 0.78) & (0.486 * kt + 0.182 * tools.cosd(zenith) >= 0.1), 0.486 * kt + 0.182 * tools.cosd(zenith), df) # remove extreme values df = np.where((df < 0.9) & (kt < 0.2), 0, df) df = np.where((df > 0.8) & (kt > 0.6), 0, df) df = np.where((df > 1), 0, df) df = np.where(((ghi - extra_i) >= 0), 0, df) dhi = df * ghi dni = irradiance.dni(ghi, dhi, zenith, clearsky_dni=Location(lat, lon).get_clearsky(times).dni, zenith_threshold_for_zero_dni=88.0, clearsky_tolerance=1.1, zenith_threshold_for_clearsky_limit=64) data = OrderedDict() data['dni'] = dni data['dhi'] = dhi data['kt'] = kt if isinstance(dni, pd.Series): data = pd.DataFrame(data) return data