Skip to content

Instantly share code, notes, and snippets.

@EricDuminil
Created October 9, 2020 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EricDuminil/f646d406967fe965190d2d3fa58df618 to your computer and use it in GitHub Desktop.
Save EricDuminil/f646d406967fe965190d2d3fa58df618 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# pvlib tutorial\n",
"\n",
"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 \n",
"\n",
"The goal is to simulate a small PV system in different locations, and try to predict how much energy it could produce.\n",
"\n",
"The code should be as concise as possible, while still delivering plausible results and taking weather into account."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Module import"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from pvlib.pvsystem import PVSystem, retrieve_sam\n",
"from pvlib.location import Location\n",
"from pvlib.modelchain import ModelChain\n",
"from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS\n",
"from pvlib.iotools import pvgis"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Not required, but recommended.\n",
"# It avoids downloading same data over and over again from PVGIS.\n",
"# https://pypi.org/project/requests-cache/\n",
"# pip install requests-cache\n",
"import requests_cache\n",
"requests_cache.install_cache('pvgis_requests_cache', backend='sqlite')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Locations, Module & Inverter"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# latitude, longitude, name , altitude, timezone\n",
"coordinates = [( 32.2 , -111.0, 'Tucson, Arizona' , 700, 'Etc/GMT+7'),\n",
" ( 35.1 , -106.6, 'Albuquerque, New Mexico' , 1500, 'Etc/GMT+7'),\n",
" ( 37.8 , -122.4, 'San Francisco, California', 10, 'Etc/GMT+8'),\n",
" ( 52.5 , 13.4, 'Berlin, Germany' , 34, 'Etc/GMT-1'),\n",
" (-20.9 , 55.5, 'St-Denis, La Réunion' , 100, 'Etc/GMT-4')]\n",
"\n",
"# Get the module and inverter specifications from SAM (https://github.com/NREL/SAM)\n",
"module = retrieve_sam('SandiaMod')['Canadian_Solar_CS5P_220M___2009_']\n",
"inverter = retrieve_sam('cecinverter')['ABB__MICRO_0_25_I_OUTD_US_208__208V_']\n",
"\n",
"temp_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simulation"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"## Tucson, Arizona (32.2°N 111.0°W, Etc/GMT+7)\n",
"Nominal power : 0.22 kWp\n",
"Surface azimuth : 180 °\n",
"Surface tilt : 32 °\n",
"Weather data source : PVGIS-NSRDB (2005 - 2015)\n",
"Global POA irradiance : 2405 kWh / (m² · y)\n",
"Average temperature : 21.4 °C\n",
"Total yield : 425 kWh / y\n",
"Specific yield : 1936 kWh / (kWp · y)\n",
"Performance ratio : 80.5 %\n",
"\n",
"## Albuquerque, New Mexico (35.1°N 106.6°W, Etc/GMT+7)\n",
"Nominal power : 0.22 kWp\n",
"Surface azimuth : 180 °\n",
"Surface tilt : 35 °\n",
"Weather data source : PVGIS-NSRDB (2005 - 2015)\n",
"Global POA irradiance : 2390 kWh / (m² · y)\n",
"Average temperature : 14.5 °C\n",
"Total yield : 439 kWh / y\n",
"Specific yield : 2001 kWh / (kWp · y)\n",
"Performance ratio : 83.7 %\n",
"\n",
"## San Francisco, California (37.8°N 122.4°W, Etc/GMT+8)\n",
"Nominal power : 0.22 kWp\n",
"Surface azimuth : 180 °\n",
"Surface tilt : 38 °\n",
"Weather data source : PVGIS-NSRDB (2005 - 2015)\n",
"Global POA irradiance : 2009 kWh / (m² · y)\n",
"Average temperature : 12.8 °C\n",
"Total yield : 383 kWh / y\n",
"Specific yield : 1746 kWh / (kWp · y)\n",
"Performance ratio : 86.9 %\n",
"\n",
"## Berlin, Germany (52.5°N 13.4°E, Etc/GMT-1)\n",
"Nominal power : 0.22 kWp\n",
"Surface azimuth : 180 °\n",
"Surface tilt : 52 °\n",
"Weather data source : PVGIS-SARAH (2005 - 2016)\n",
"Global POA irradiance : 1254 kWh / (m² · y)\n",
"Average temperature : 10.4 °C\n",
"Total yield : 239 kWh / y\n",
"Specific yield : 1088 kWh / (kWp · y)\n",
"Performance ratio : 86.7 %\n",
"\n",
"## St-Denis, La Réunion (20.9°S 55.5°E, Etc/GMT-4)\n",
"Nominal power : 0.22 kWp\n",
"Surface azimuth : 0 °\n",
"Surface tilt : 21 °\n",
"Weather data source : PVGIS-SARAH (2005 - 2016)\n",
"Global POA irradiance : 2141 kWh / (m² · y)\n",
"Average temperature : 18.1 °C\n",
"Total yield : 396 kWh / y\n",
"Specific yield : 1802 kWh / (kWp · y)\n",
"Performance ratio : 84.2 %\n",
"\n"
]
}
],
"source": [
"for latitude, longitude, name, altitude, timezone in coordinates:\n",
" location = Location(latitude, longitude, name=name,\n",
" altitude=altitude, tz=timezone)\n",
"\n",
" # Download weather data from PVGIS server\n",
" weather, _, info, _ = pvgis.get_pvgis_tmy(location.latitude,\n",
" location.longitude)\n",
"\n",
" # Rename columns from PVGIS TMY in order to define the required data.\n",
" weather = weather.rename(columns={'G(h)': 'ghi',\n",
" 'Gb(n)': 'dni',\n",
" 'Gd(h)': 'dhi',\n",
" 'T2m': 'temp_air'\n",
" })\n",
" \n",
" # Same logic as orientation_strategy='south_at_latitude_tilt', but might be\n",
" # a bit clearer for locations in southern hemishpere.\n",
" system = PVSystem(module_parameters=module,\n",
" inverter_parameters=inverter,\n",
" temperature_model_parameters=temp_parameters,\n",
" surface_tilt=abs(latitude),\n",
" surface_azimuth=180 if latitude > 0 else 0)\n",
" mc = ModelChain(system, location)\n",
" mc.run_model(weather)\n",
"\n",
" # Reporting\n",
" nominal_power = module.Impo * module.Vmpo\n",
" annual_energy = mc.ac.sum()\n",
" specific_yield = annual_energy / nominal_power\n",
" global_poa = mc.total_irrad.poa_global.sum() / 1000\n",
" average_ambient_temperature = weather.temp_air.mean()\n",
" performance_ratio = specific_yield / global_poa\n",
" weather_source = '%s (%d - %d)' % (info['meteo_data']['radiation_db'],\n",
" info['meteo_data']['year_min'],\n",
" info['meteo_data']['year_max'])\n",
" latitude_NS = '%.1f°%s' % (abs(latitude), 'N' if latitude > 0 else 'S')\n",
" longitude_EW = '%.1f°%s' % (abs(longitude), 'E' if longitude > 0 else 'W')\n",
"\n",
" print('## %s (%s %s, %s)' % (name, latitude_NS, longitude_EW, timezone))\n",
" print('Nominal power : %.2f kWp' % (nominal_power / 1000))\n",
" print('Surface azimuth : %.0f °' % system.surface_azimuth)\n",
" print('Surface tilt : %.0f °' % system.surface_tilt)\n",
" print('Weather data source : %s' % weather_source)\n",
" print('Global POA irradiance : %.0f kWh / (m² · y)' % global_poa)\n",
" print('Average temperature : %.1f °C' % average_ambient_temperature)\n",
" print('Total yield : %.0f kWh / y' % (annual_energy / 1000))\n",
" print('Specific yield : %.0f kWh / (kWp · y)' % specific_yield)\n",
" print('Performance ratio : %.1f %%' % (performance_ratio * 100))\n",
" print()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment