@@ -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