pvlib tutorial¶
Install with conda install -c pvlib pvlib
This page contains introductory examples of pvlib python usage. It is based on the Object Oriented code from https://pvlib-python.readthedocs.io/en/stable/introtutorial.html
The goal is to simulate a small PV system in different locations, and try to predict how much energy it could produce.
The code should be as concise as possible, while still delivering plausible results and taking weather into account.
Uploaded to https://gist.github.com/EricDuminil/f646d406967fe965190d2d3fa58df618 Pinged to https://stackoverflow.com/questions/57682450/importing-non-tmy3-format-weather-data-for-use-in-pvlib-simulation/57826625#57826625
Module import¶
In [1]:
Copied!
from pvlib.pvsystem import PVSystem, retrieve_sam
from pvlib.location import Location
from pvlib.modelchain import ModelChain
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
from pvlib.iotools import pvgis
from pvlib.pvsystem import PVSystem, retrieve_sam
from pvlib.location import Location
from pvlib.modelchain import ModelChain
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
from pvlib.iotools import pvgis
In [2]:
Copied!
# Not required, but recommended.
# It avoids downloading same data over and over again from PVGIS.
# https://pypi.org/project/requests-cache/
# pip install requests-cache
import requests_cache
requests_cache.install_cache('pvgis_requests_cache', backend='sqlite')
# Not required, but recommended.
# It avoids downloading same data over and over again from PVGIS.
# https://pypi.org/project/requests-cache/
# pip install requests-cache
import requests_cache
requests_cache.install_cache('pvgis_requests_cache', backend='sqlite')
Locations, Module & Inverter¶
In [3]:
Copied!
# latitude, longitude, name , altitude, timezone
coordinates = [( 32.2 , -111.0, 'Tucson, Arizona' , 700, 'Etc/GMT+7'),
( 35.1 , -106.6, 'Albuquerque, New Mexico' , 1500, 'Etc/GMT+7'),
( 37.8 , -122.4, 'San Francisco, California', 10, 'Etc/GMT+8'),
( 52.5 , 13.4, 'Berlin, Germany' , 34, 'Etc/GMT-1'),
(-20.9 , 55.5, 'St-Denis, La Réunion' , 100, 'Etc/GMT-4')]
# Get the module and inverter specifications from SAM (https://github.com/NREL/SAM)
module = retrieve_sam('SandiaMod')['Canadian_Solar_CS5P_220M___2009_']
inverter = retrieve_sam('cecinverter')['ABB__MICRO_0_25_I_OUTD_US_208__208V_']
temp_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
# latitude, longitude, name , altitude, timezone
coordinates = [( 32.2 , -111.0, 'Tucson, Arizona' , 700, 'Etc/GMT+7'),
( 35.1 , -106.6, 'Albuquerque, New Mexico' , 1500, 'Etc/GMT+7'),
( 37.8 , -122.4, 'San Francisco, California', 10, 'Etc/GMT+8'),
( 52.5 , 13.4, 'Berlin, Germany' , 34, 'Etc/GMT-1'),
(-20.9 , 55.5, 'St-Denis, La Réunion' , 100, 'Etc/GMT-4')]
# Get the module and inverter specifications from SAM (https://github.com/NREL/SAM)
module = retrieve_sam('SandiaMod')['Canadian_Solar_CS5P_220M___2009_']
inverter = retrieve_sam('cecinverter')['ABB__MICRO_0_25_I_OUTD_US_208__208V_']
temp_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
Simulation¶
In [4]:
Copied!
for latitude, longitude, name, altitude, timezone in coordinates:
location = Location(latitude, longitude, name=name,
altitude=altitude, tz=timezone)
# Download weather data from PVGIS server
weather, _, info, _ = pvgis.get_pvgis_tmy(location.latitude,
location.longitude)
# Rename columns from PVGIS TMY in order to define the required data.
weather = weather.rename(columns={'G(h)': 'ghi',
'Gb(n)': 'dni',
'Gd(h)': 'dhi',
'T2m': 'temp_air'
})
# Same logic as orientation_strategy='south_at_latitude_tilt', but might be
# a bit clearer for locations in southern hemishpere.
system = PVSystem(module_parameters=module,
inverter_parameters=inverter,
temperature_model_parameters=temp_parameters,
surface_tilt=abs(latitude),
surface_azimuth=180 if latitude > 0 else 0)
mc = ModelChain(system, location)
mc.run_model(weather)
mount = system.arrays[0].mount
# Reporting
nominal_power = module.Impo * module.Vmpo
annual_energy = mc.results.ac.sum()
specific_yield = annual_energy / nominal_power
global_poa = mc.results.total_irrad.poa_global.sum() / 1000
average_ambient_temperature = weather.temp_air.mean()
performance_ratio = specific_yield / global_poa
weather_source = '%s (%d - %d)' % (info['meteo_data']['radiation_db'],
info['meteo_data']['year_min'],
info['meteo_data']['year_max'])
latitude_NS = '%.1f°%s' % (abs(latitude), 'N' if latitude > 0 else 'S')
longitude_EW = '%.1f°%s' % (abs(longitude), 'E' if longitude > 0 else 'W')
print('## %s (%s %s, %s)' % (name, latitude_NS, longitude_EW, timezone))
print('Nominal power : %.2f kWp' % (nominal_power / 1000))
print('Surface azimuth : %.0f °' % mount.surface_azimuth)
print('Surface tilt : %.0f °' % mount.surface_tilt)
print('Weather data source : %s' % weather_source)
print('Global POA irradiance : %.0f kWh / (m² · y)' % global_poa)
print('Average temperature : %.1f °C' % average_ambient_temperature)
print('Total yield : %.0f kWh / y' % (annual_energy / 1000))
print('Specific yield : %.0f kWh / (kWp · y)' % specific_yield)
print('Performance ratio : %.1f %%' % (performance_ratio * 100))
print()
for latitude, longitude, name, altitude, timezone in coordinates:
location = Location(latitude, longitude, name=name,
altitude=altitude, tz=timezone)
# Download weather data from PVGIS server
weather, _, info, _ = pvgis.get_pvgis_tmy(location.latitude,
location.longitude)
# Rename columns from PVGIS TMY in order to define the required data.
weather = weather.rename(columns={'G(h)': 'ghi',
'Gb(n)': 'dni',
'Gd(h)': 'dhi',
'T2m': 'temp_air'
})
# Same logic as orientation_strategy='south_at_latitude_tilt', but might be
# a bit clearer for locations in southern hemishpere.
system = PVSystem(module_parameters=module,
inverter_parameters=inverter,
temperature_model_parameters=temp_parameters,
surface_tilt=abs(latitude),
surface_azimuth=180 if latitude > 0 else 0)
mc = ModelChain(system, location)
mc.run_model(weather)
mount = system.arrays[0].mount
# Reporting
nominal_power = module.Impo * module.Vmpo
annual_energy = mc.results.ac.sum()
specific_yield = annual_energy / nominal_power
global_poa = mc.results.total_irrad.poa_global.sum() / 1000
average_ambient_temperature = weather.temp_air.mean()
performance_ratio = specific_yield / global_poa
weather_source = '%s (%d - %d)' % (info['meteo_data']['radiation_db'],
info['meteo_data']['year_min'],
info['meteo_data']['year_max'])
latitude_NS = '%.1f°%s' % (abs(latitude), 'N' if latitude > 0 else 'S')
longitude_EW = '%.1f°%s' % (abs(longitude), 'E' if longitude > 0 else 'W')
print('## %s (%s %s, %s)' % (name, latitude_NS, longitude_EW, timezone))
print('Nominal power : %.2f kWp' % (nominal_power / 1000))
print('Surface azimuth : %.0f °' % mount.surface_azimuth)
print('Surface tilt : %.0f °' % mount.surface_tilt)
print('Weather data source : %s' % weather_source)
print('Global POA irradiance : %.0f kWh / (m² · y)' % global_poa)
print('Average temperature : %.1f °C' % average_ambient_temperature)
print('Total yield : %.0f kWh / y' % (annual_energy / 1000))
print('Specific yield : %.0f kWh / (kWp · y)' % specific_yield)
print('Performance ratio : %.1f %%' % (performance_ratio * 100))
print()
/home/ricou/anaconda3/lib/python3.9/site-packages/pvlib/iotools/pvgis.py:477: pvlibDeprecationWarning: PVGIS variable names will be renamed to pvlib conventions by default starting in pvlib 0.10.0. Specify map_variables=True to enable that behavior now, or specify map_variables=False to hide this warning. warnings.warn(
## Tucson, Arizona (32.2°N 111.0°W, Etc/GMT+7) Nominal power : 0.22 kWp Surface azimuth : 180 ° Surface tilt : 32 ° Weather data source : PVGIS-NSRDB (2005 - 2015) Global POA irradiance : 2405 kWh / (m² · y) Average temperature : 21.4 °C Total yield : 425 kWh / y Specific yield : 1936 kWh / (kWp · y) Performance ratio : 80.5 % ## Albuquerque, New Mexico (35.1°N 106.6°W, Etc/GMT+7) Nominal power : 0.22 kWp Surface azimuth : 180 ° Surface tilt : 35 ° Weather data source : PVGIS-NSRDB (2005 - 2015) Global POA irradiance : 2390 kWh / (m² · y) Average temperature : 14.5 °C Total yield : 439 kWh / y Specific yield : 2001 kWh / (kWp · y) Performance ratio : 83.7 % ## San Francisco, California (37.8°N 122.4°W, Etc/GMT+8) Nominal power : 0.22 kWp Surface azimuth : 180 ° Surface tilt : 38 ° Weather data source : PVGIS-NSRDB (2005 - 2015) Global POA irradiance : 2009 kWh / (m² · y) Average temperature : 12.8 °C Total yield : 383 kWh / y Specific yield : 1746 kWh / (kWp · y) Performance ratio : 86.9 % ## Berlin, Germany (52.5°N 13.4°E, Etc/GMT-1) Nominal power : 0.22 kWp Surface azimuth : 180 ° Surface tilt : 52 ° Weather data source : PVGIS-SARAH (2005 - 2016) Global POA irradiance : 1254 kWh / (m² · y) Average temperature : 10.4 °C Total yield : 239 kWh / y Specific yield : 1088 kWh / (kWp · y) Performance ratio : 86.7 % ## St-Denis, La Réunion (20.9°S 55.5°E, Etc/GMT-4) Nominal power : 0.22 kWp Surface azimuth : 0 ° Surface tilt : 21 ° Weather data source : PVGIS-SARAH (2005 - 2016) Global POA irradiance : 2141 kWh / (m² · y) Average temperature : 18.1 °C Total yield : 396 kWh / y Specific yield : 1802 kWh / (kWp · y) Performance ratio : 84.2 %