Is there a way to take into account the horizon in PVLib ?
I have PV systems in the mountains, so with high neigbouring montains affecting the horizon. I have simulated the clearsky irradiance with PVLib, PVGis with and without horizon (see next figure). We see that the difference is significant.
Location
when calling the Location.get_clearsky()
function ?PS: This is my code to get the clearsky irradiance and the PV system AC Power:
# Location
locationValley = Location(latitude=46.179, longitude=7.602, altitude=1431, tz='Europe/Zurich', name='Valley')
# Weather
datetime = pd.date_range(start='2022-01-01', end='2022-01-02', freq='5min', tz=locationValley.tz, inclusive='left')
csPowerValley = locationValley.get_clearsky(datetime) # ineichen with climatology table by default
# ModelChain
array1 = Array(
mount=FixedMount(surface_tilt=30, surface_azimuth=241, racking_model = 'open_rack'),
module_parameters={'pdc0': 55, 'gamma_pdc' : -0.004},
module_type = 'glass_polymer',
modules_per_string = 445, # 445 modules for 1 string or 89 modules for 5 strings is the same
strings = 1,
temperature_model_parameters=pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer'],
)
system = PVSystem(arrays=[array1], inverter_parameters={'pdc0': 24475, 'eta_inv_nom': 0.96})
modelChain = ModelChain(system, locationValley, clearsky_model = 'ineichen', aoi_model='no_loss', spectral_model="no_loss")
modelChain.run_model(csPowerValley)
To account for the horizon when calculating clear sky irradiance using PVLib, you can follow the approach demonstrated in the PVLib documentation example. This method involves using horizon profile data to adjust the Direct Normal Irradiance (DNI) and Plane of Array (POA) global irradiance based on the horizon elevation angles.
Here's a concise implementation:
import numpy as np
import pandas as pd
import pvlib
# Define location (Golden, CO) and time range
latitude, longitude = 39.76, -105.22
tz = 'MST'
times = pd.date_range('2020-12-20 6:30', '2020-12-20 9:00', freq='1T', tz=tz)
location = pvlib.location.Location(latitude, longitude, tz)
# Get solar position and clearsky data
solar_position = location.get_solarposition(times)
clearsky = location.get_clearsky(times)
# Example horizon profile (azimuth: 0° to 360° in 7.5° increments)
horizon_profile = pd.Series([
10.7, 11.8, 11.5, 10.3, 8.0, 6.5, 3.8, 2.3, 2.3, 2.3, 4.6, 8.0, 10.3, 11.1,
10.7, 10.3, 9.2, 6.1, 5.3, 2.3, 3.1, 1.9, 1.9, 2.7, 3.8, 5.3, 6.5, 8.4,
8.8, 8.4, 8.4, 8.4, 6.5, 6.1, 6.5, 6.1, 7.3, 9.2, 8.4, 8.0, 5.7, 5.3, 5.3,
4.2, 4.2, 4.2, 7.3, 9.5
], index=np.arange(0, 360, 7.5))
# Interpolate horizon elevation data to the solar azimuth
horizon_elevation_data = np.interp(
solar_position.azimuth, horizon_profile.index, horizon_profile
)
# Adjust DNI based on horizon data
dni_adjusted = np.where(solar_position.apparent_elevation > horizon_elevation_data, clearsky.dni, 0)
ghi_adjusted = np.where(dni_adjusted == 0, clearsky.dhi, clearsky.ghi)
# Calculate irradiance before and after adjustment
surface_tilt, surface_azimuth = 30, 180
irrad_pre_adj = pvlib.irradiance.get_total_irradiance(
surface_tilt, surface_azimuth, solar_position.apparent_zenith, solar_position.azimuth,
clearsky.dni, clearsky.ghi, clearsky.dhi
)
irrad_post_adj = pvlib.irradiance.get_total_irradiance(
surface_tilt, surface_azimuth, solar_position.apparent_zenith, solar_position.azimuth,
dni_adjusted, ghi_adjusted, clearsky.dhi
)
By following this approach, you can adjust the clear sky irradiance values to account for the horizon profile, providing more accurate irradiance data for locations with significant surrounding terrain.