Skip to content

Commit 7ed18c4

Browse files
authored
Update intro tutorial (#1116) (#1144)
* Update intro tutorial (#1116) Make the procedural and OO results match exactly and highlight the use of `iotools` to download meteorological data. * fixup! Update intro tutorial (#1116)
1 parent 1385943 commit 7ed18c4

File tree

2 files changed

+100
-49
lines changed

2 files changed

+100
-49
lines changed

docs/sphinx/source/introtutorial.rst

Lines changed: 97 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,18 @@ configuration at a handful of sites listed below.
2727

2828
.. ipython:: python
2929
30+
import pvlib
3031
import pandas as pd
3132
import matplotlib.pyplot as plt
3233
33-
naive_times = pd.date_range(start='2015', end='2016', freq='1h')
34-
3534
# very approximate
3635
# latitude, longitude, name, altitude, timezone
37-
coordinates = [(30, -110, 'Tucson', 700, 'Etc/GMT+7'),
38-
(35, -105, 'Albuquerque', 1500, 'Etc/GMT+7'),
39-
(40, -120, 'San Francisco', 10, 'Etc/GMT+8'),
40-
(50, 10, 'Berlin', 34, 'Etc/GMT-1')]
41-
42-
import pvlib
36+
coordinates = [
37+
(30, -110, 'Tucson', 700, 'Etc/GMT+7'),
38+
(35, -105, 'Albuquerque', 1500, 'Etc/GMT+7'),
39+
(40, -120, 'San Francisco', 10, 'Etc/GMT+8'),
40+
(50, 10, 'Berlin', 34, 'Etc/GMT-1'),
41+
]
4342
4443
# get the module and inverter specifications from SAM
4544
sandia_modules = pvlib.pvsystem.retrieve_sam('SandiaMod')
@@ -48,9 +47,32 @@ configuration at a handful of sites listed below.
4847
inverter = sapm_inverters['ABB__MICRO_0_25_I_OUTD_US_208__208V_']
4948
temperature_model_parameters = pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
5049
51-
# specify constant ambient air temp and wind for simplicity
52-
temp_air = 20
53-
wind_speed = 0
50+
51+
In order to retrieve meteorological data for the simulation, we can make use of
52+
the :ref:`iotools` module. In this example we will be using PVGIS, one of the
53+
data sources available, to retrieve a Typical Meteorological Year (TMY) which
54+
includes irradiation, temperature and wind speed.
55+
56+
.. note:: PVGIS uses different naming conventions, so it is required to rename
57+
the weather data variables before using them. Data is already UTC-localized,
58+
so conversion to local timezone is optional.
59+
60+
.. ipython:: python
61+
62+
variables_translation = {
63+
"Gb(n)": "dni",
64+
"G(h)": "ghi",
65+
"Gd(h)": "dhi",
66+
"T2m": "temp_air",
67+
"WS10m": "wind_speed",
68+
}
69+
tmys = []
70+
for location in coordinates:
71+
latitude, longitude, name, altitude, timezone = location
72+
weather = pvlib.iotools.get_pvgis_tmy(latitude, longitude)[0]
73+
weather = weather.rename(columns=variables_translation)
74+
weather.index.name = "utc_time"
75+
tmys.append(weather)
5476
5577
5678
Procedural
@@ -69,41 +91,60 @@ to accomplish our system modeling goal:
6991
7092
energies = {}
7193
72-
for latitude, longitude, name, altitude, timezone in coordinates:
73-
times = naive_times.tz_localize(timezone)
94+
for location, weather in zip(coordinates, tmys):
95+
latitude, longitude, name, altitude, timezone = location
7496
system['surface_tilt'] = latitude
75-
solpos = pvlib.solarposition.get_solarposition(times, latitude, longitude)
76-
dni_extra = pvlib.irradiance.get_extra_radiation(times)
97+
solpos = pvlib.solarposition.get_solarposition(
98+
time=weather.index,
99+
latitude=latitude,
100+
longitude=longitude,
101+
altitude=altitude,
102+
temperature=weather["temp_air"],
103+
pressure=pvlib.atmosphere.alt2pres(altitude),
104+
)
105+
dni_extra = pvlib.irradiance.get_extra_radiation(weather.index)
77106
airmass = pvlib.atmosphere.get_relative_airmass(solpos['apparent_zenith'])
78107
pressure = pvlib.atmosphere.alt2pres(altitude)
79108
am_abs = pvlib.atmosphere.get_absolute_airmass(airmass, pressure)
80-
tl = pvlib.clearsky.lookup_linke_turbidity(times, latitude, longitude)
81-
cs = pvlib.clearsky.ineichen(solpos['apparent_zenith'], am_abs, tl,
82-
dni_extra=dni_extra, altitude=altitude)
83-
aoi = pvlib.irradiance.aoi(system['surface_tilt'], system['surface_azimuth'],
84-
solpos['apparent_zenith'], solpos['azimuth'])
85-
total_irrad = pvlib.irradiance.get_total_irradiance(system['surface_tilt'],
86-
system['surface_azimuth'],
87-
solpos['apparent_zenith'],
88-
solpos['azimuth'],
89-
cs['dni'], cs['ghi'], cs['dhi'],
90-
dni_extra=dni_extra,
91-
model='haydavies')
92-
tcell = pvlib.temperature.sapm_cell(total_irrad['poa_global'],
93-
temp_air, wind_speed,
94-
**temperature_model_parameters)
109+
aoi = pvlib.irradiance.aoi(
110+
system['surface_tilt'],
111+
system['surface_azimuth'],
112+
solpos["apparent_zenith"],
113+
solpos["azimuth"],
114+
)
115+
total_irradiance = pvlib.irradiance.get_total_irradiance(
116+
system['surface_tilt'],
117+
system['surface_azimuth'],
118+
solpos['apparent_zenith'],
119+
solpos['azimuth'],
120+
weather['dni'],
121+
weather['ghi'],
122+
weather['dhi'],
123+
dni_extra=dni_extra,
124+
model='haydavies',
125+
)
126+
cell_temperature = pvlib.temperature.sapm_cell(
127+
total_irradiance['poa_global'],
128+
weather["temp_air"],
129+
weather["wind_speed"],
130+
**temperature_model_parameters,
131+
)
95132
effective_irradiance = pvlib.pvsystem.sapm_effective_irradiance(
96-
total_irrad['poa_direct'], total_irrad['poa_diffuse'],
97-
am_abs, aoi, module)
98-
dc = pvlib.pvsystem.sapm(effective_irradiance, tcell, module)
133+
total_irradiance['poa_direct'],
134+
total_irradiance['poa_diffuse'],
135+
am_abs,
136+
aoi,
137+
module,
138+
)
139+
dc = pvlib.pvsystem.sapm(effective_irradiance, cell_temperature, module)
99140
ac = pvlib.inverter.sandia(dc['v_mp'], dc['p_mp'], inverter)
100141
annual_energy = ac.sum()
101142
energies[name] = annual_energy
102143
103144
energies = pd.Series(energies)
104145
105146
# based on the parameters specified above, these are in W*hrs
106-
print(energies.round(0))
147+
print(energies)
107148
108149
energies.plot(kind='bar', rot=0)
109150
@savefig proc-energies.png width=6in
@@ -150,28 +191,35 @@ by examining the parameters defined for the module.
150191
from pvlib.location import Location
151192
from pvlib.modelchain import ModelChain
152193
153-
system = PVSystem(module_parameters=module,
154-
inverter_parameters=inverter,
155-
temperature_model_parameters=temperature_model_parameters)
194+
system = PVSystem(
195+
module_parameters=module,
196+
inverter_parameters=inverter,
197+
temperature_model_parameters=temperature_model_parameters,
198+
)
156199
157200
energies = {}
158-
for latitude, longitude, name, altitude, timezone in coordinates:
159-
times = naive_times.tz_localize(timezone)
160-
location = Location(latitude, longitude, name=name, altitude=altitude,
161-
tz=timezone)
162-
weather = location.get_clearsky(times)
163-
mc = ModelChain(system, location,
164-
orientation_strategy='south_at_latitude_tilt')
165-
# model results (ac, dc) and intermediates (aoi, temps, etc.)
166-
# assigned as mc object attributes
167-
mc.run_model(weather)
168-
annual_energy = mc.results.ac.sum()
201+
for location, weather in zip(coordinates, tmys):
202+
latitude, longitude, name, altitude, timezone = location
203+
location = Location(
204+
latitude,
205+
longitude,
206+
name=name,
207+
altitude=altitude,
208+
tz=timezone,
209+
)
210+
mc = ModelChain(
211+
system,
212+
location,
213+
orientation_strategy='south_at_latitude_tilt',
214+
)
215+
results = mc.run_model(weather)
216+
annual_energy = results.ac.sum()
169217
energies[name] = annual_energy
170218
171219
energies = pd.Series(energies)
172220
173221
# based on the parameters specified above, these are in W*hrs
174-
print(energies.round(0))
222+
print(energies)
175223
176224
energies.plot(kind='bar', rot=0)
177225
@savefig modelchain-energies.png width=6in

docs/sphinx/source/whatsnew/v0.9.0.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ Testing
100100
Documentation
101101
~~~~~~~~~~~~~
102102

103+
* Update intro tutorial to highlight the use of historical meteorological data
104+
and to make the procedural and OO results match exactly.
105+
103106
Requirements
104107
~~~~~~~~~~~~
105108
* ``dataclasses`` is required for python 3.6

0 commit comments

Comments
 (0)