Skip to content

Commit 0699bea

Browse files
committed
Update intro tutorial (#1116)
Make the procedural and OO results match exactly and highlight the use of `iotools` to download meteorological data.
1 parent 1385943 commit 0699bea

1 file changed

Lines changed: 94 additions & 49 deletions

File tree

docs/sphinx/source/introtutorial.rst

Lines changed: 94 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,29 @@ 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+
Let's download the typical meteorological year weather data from PVGIS, which
52+
includes irradiation, temperature and wind speed. Note that PVGIS uses
53+
different naming conventions, so it is required to rename the weather data
54+
variables before using them. PVGIS weather data is already UTC-localized, so
55+
conversion to local timezone is optional.
56+
57+
.. ipython:: python
58+
59+
variables_translation = {
60+
"Gb(n)": "dni",
61+
"G(h)": "ghi",
62+
"Gd(h)": "dhi",
63+
"T2m": "temp_air",
64+
"WS10m": "wind_speed",
65+
}
66+
tmys = []
67+
for location in coordinates:
68+
latitude, longitude, name, altitude, timezone = location
69+
weather = pvlib.iotools.get_pvgis_tmy(latitude, longitude)[0]
70+
weather = weather.rename(columns=variables_translation)
71+
weather.index.name = "utc_time"
72+
tmys.append(weather)
5473
5574
5675
Procedural
@@ -69,41 +88,60 @@ to accomplish our system modeling goal:
6988
7089
energies = {}
7190
72-
for latitude, longitude, name, altitude, timezone in coordinates:
73-
times = naive_times.tz_localize(timezone)
91+
for location, weather in zip(coordinates, tmys):
92+
latitude, longitude, name, altitude, timezone = location
7493
system['surface_tilt'] = latitude
75-
solpos = pvlib.solarposition.get_solarposition(times, latitude, longitude)
76-
dni_extra = pvlib.irradiance.get_extra_radiation(times)
94+
solpos = pvlib.solarposition.get_solarposition(
95+
time=weather.index,
96+
latitude=latitude,
97+
longitude=longitude,
98+
altitude=altitude,
99+
temperature=weather["temp_air"],
100+
pressure=pvlib.atmosphere.alt2pres(altitude),
101+
)
102+
dni_extra = pvlib.irradiance.get_extra_radiation(weather.index)
77103
airmass = pvlib.atmosphere.get_relative_airmass(solpos['apparent_zenith'])
78104
pressure = pvlib.atmosphere.alt2pres(altitude)
79105
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)
106+
aoi = pvlib.irradiance.aoi(
107+
system['surface_tilt'],
108+
system['surface_azimuth'],
109+
solpos["apparent_zenith"],
110+
solpos["azimuth"],
111+
)
112+
total_irradiance = pvlib.irradiance.get_total_irradiance(
113+
system['surface_tilt'],
114+
system['surface_azimuth'],
115+
solpos['apparent_zenith'],
116+
solpos['azimuth'],
117+
weather['dni'],
118+
weather['ghi'],
119+
weather['dhi'],
120+
dni_extra=dni_extra,
121+
model='haydavies',
122+
)
123+
cell_temperature = pvlib.temperature.sapm_cell(
124+
total_irradiance['poa_global'],
125+
weather["temp_air"],
126+
weather["wind_speed"],
127+
**temperature_model_parameters,
128+
)
95129
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)
130+
total_irradiance['poa_direct'],
131+
total_irradiance['poa_diffuse'],
132+
am_abs,
133+
aoi,
134+
module,
135+
)
136+
dc = pvlib.pvsystem.sapm(effective_irradiance, cell_temperature, module)
99137
ac = pvlib.inverter.sandia(dc['v_mp'], dc['p_mp'], inverter)
100138
annual_energy = ac.sum()
101139
energies[name] = annual_energy
102140
103141
energies = pd.Series(energies)
104142
105143
# based on the parameters specified above, these are in W*hrs
106-
print(energies.round(0))
144+
print(energies)
107145
108146
energies.plot(kind='bar', rot=0)
109147
@savefig proc-energies.png width=6in
@@ -150,28 +188,35 @@ by examining the parameters defined for the module.
150188
from pvlib.location import Location
151189
from pvlib.modelchain import ModelChain
152190
153-
system = PVSystem(module_parameters=module,
154-
inverter_parameters=inverter,
155-
temperature_model_parameters=temperature_model_parameters)
191+
system = PVSystem(
192+
module_parameters=module,
193+
inverter_parameters=inverter,
194+
temperature_model_parameters=temperature_model_parameters,
195+
)
156196
157197
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()
198+
for location, weather in zip(coordinates, tmys):
199+
latitude, longitude, name, altitude, timezone = location
200+
location = Location(
201+
latitude,
202+
longitude,
203+
name=name,
204+
altitude=altitude,
205+
tz=timezone,
206+
)
207+
mc = ModelChain(
208+
system,
209+
location,
210+
orientation_strategy='south_at_latitude_tilt',
211+
)
212+
results = mc.run_model(weather)
213+
annual_energy = results.ac.sum()
169214
energies[name] = annual_energy
170215
171216
energies = pd.Series(energies)
172217
173218
# based on the parameters specified above, these are in W*hrs
174-
print(energies.round(0))
219+
print(energies)
175220
176221
energies.plot(kind='bar', rot=0)
177222
@savefig modelchain-energies.png width=6in

0 commit comments

Comments
 (0)