Skip to content

Commit 5b4ba72

Browse files
authored
move celltemp functions to celltemp.py, expose celltemp.pvsyst in ModelChain (#682)
* move celltemp functions to celltemp.py, fix docstring for pvsystem.PVSystem.sapm * formatting * formatting * initial commit fit_cec_using_sam * outline ivcurves * use nrel-pysam * remove sam_dir * add Sandia single curve fit * complete function * add test, move code to ivtools.py * remove single files * fix mock * add celltemp.pvsyst as a ModelChain option, change order of arguments in celltemp.samp * lint * argument order fixes * another argument order fix * another argument order fix, change model_params to model in celltemp.pvsyst * more model_params to model cleanup * pare back modelchain test * put test back in to hit ModelChain.pvsyst_temp * output dataframe from celltemp.pvsyst * cleanup tests with pvsyst output as dataframe * fix dataframe creation in celltemp.pvsyst * fix type checking * fix test condition * update api, whatsnew * comment responses * change arguments for celltemp.sapm * fix conflict * fix kwarg error * update whatsnew * test fixes, table formatting * docstring fixes * edits to celltemp.pvsyst * add PVsystem properties, move PVsystem tests back to test_pvsystem.py * start working on ModelChain * fix ModelChain tests * modelchain fixes * modelchain test fixes * modelchain test fixes * more modelchain test fixes * add infer_temp_model * lint, test fixes * yet more modelchain test fixes * update whatsnew, improve coverage * fix deprecated test * fix import * one more MC test fix * rename functions, change output type * change argument names, add parameter_set lookup * fix function names * fix function names more * update modelchain and tests * more test fixes * test fixes * lint * lint, merge master * lint, remove pvwatts_dc_pvwatts_ac_system fixture from test_modelchain.py * rename from celltemp to temperature * lint, rename test_celltemp.py * cleanup docstrings * add invalid test for infer_temp_model * review comments * remove unrelated code * handle deprecated attributes and functions * test fixes * fix documentation * fix infer_temp_model naming, whatsnew * test fixes and docstring edits * handle ModelChain deprecated behavior, test type input of _translate functions * test fixes * fix tests * another test fix * pop unused kwarg * improve test coverage * test fixes * add UserWarning * improve warnings * use property setter * test fixes * yet another code fix trying to distinguish kwargs from attribute of same name * still struggling with tests * reset system between ModelChain init * infer parameters from racking, module_type * add the missing colon * delete vestigial lines * test fixes * fix tests, reformat whatsnew section * test fix * better handling of deprecated behavior, add consistency check temperature_model vs. temperature_model_parameters * fix method check * missing . * update tests * remove duplicate test value, clarify TODO comment * consistent import of tools * insert blank line * remove parameter_set arg from PVSystem methods * lint
1 parent a873462 commit 5b4ba72

14 files changed

+1142
-455
lines changed

docs/sphinx/source/api.rst

+24-11
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ AOI modifiers
221221
pvsystem.ashraeiam
222222
pvsystem.sapm_aoi_loss
223223

224+
PV temperature models
225+
---------------------
226+
227+
.. autosummary::
228+
:toctree: generated/
229+
230+
temperature.sapm_cell
231+
temperature.sapm_module
232+
temperature.pvsyst_cell
233+
224234
Single diode models
225235
-------------------
226236

@@ -258,29 +268,31 @@ Functions relevant for the SAPM model.
258268

259269
pvsystem.sapm
260270
pvsystem.sapm_effective_irradiance
261-
pvsystem.sapm_celltemp
262271
pvsystem.sapm_spectral_loss
263272
pvsystem.sapm_aoi_loss
264273
pvsystem.snlinverter
274+
temperature.sapm_cell
265275

266-
PVWatts model
276+
Pvsyst model
267277
-------------
268278

279+
Functions relevant for the Pvsyst model.
280+
269281
.. autosummary::
270282
:toctree: generated/
271283

272-
pvsystem.pvwatts_dc
273-
pvsystem.pvwatts_ac
274-
pvsystem.pvwatts_losses
275-
pvsystem.pvwatts_losses
284+
temperature.pvsyst_cell
276285

277-
PVsyst model
278-
------------
286+
PVWatts model
287+
-------------
279288

280289
.. autosummary::
281290
:toctree: generated/
282291

283-
pvsystem.pvsyst_celltemp
292+
pvsystem.pvwatts_dc
293+
pvsystem.pvwatts_ac
294+
pvsystem.pvwatts_losses
295+
pvsystem.pvwatts_losses
284296

285297
Other
286298
-----
@@ -472,7 +484,7 @@ ModelChain properties that are aliases for your specific modeling functions.
472484
modelchain.ModelChain.ac_model
473485
modelchain.ModelChain.aoi_model
474486
modelchain.ModelChain.spectral_model
475-
modelchain.ModelChain.temp_model
487+
modelchain.ModelChain.temperature_model
476488
modelchain.ModelChain.losses_model
477489
modelchain.ModelChain.effective_irradiance_model
478490

@@ -500,6 +512,7 @@ ModelChain model definitions.
500512
modelchain.ModelChain.sapm_spectral_loss
501513
modelchain.ModelChain.no_spectral_loss
502514
modelchain.ModelChain.sapm_temp
515+
modelchain.ModelChain.pvsyst_temp
503516
modelchain.ModelChain.pvwatts_losses
504517
modelchain.ModelChain.no_extra_losses
505518

@@ -516,7 +529,7 @@ on the information in the associated :py:class:`~pvsystem.PVSystem` object.
516529
modelchain.ModelChain.infer_ac_model
517530
modelchain.ModelChain.infer_aoi_model
518531
modelchain.ModelChain.infer_spectral_model
519-
modelchain.ModelChain.infer_temp_model
532+
modelchain.ModelChain.infer_temperature_model
520533
modelchain.ModelChain.infer_losses_model
521534

522535
Functions

docs/sphinx/source/clearsky.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ returns a :py:class:`pandas.DataFrame`.
6868

6969
In [1]: tus = Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
7070

71-
In [1]: times = pd.DatetimeIndex(start='2016-07-01', end='2016-07-04', freq='1min', tz=tus.tz)
71+
In [1]: times = pd.date_range(start='2016-07-01', end='2016-07-04', freq='1min', tz=tus.tz)
7272

7373
In [1]: cs = tus.get_clearsky(times) # ineichen with climatology table by default
7474

@@ -168,7 +168,7 @@ varies from 300 m to 1500 m.
168168

169169
.. ipython::
170170

171-
In [1]: times = pd.DatetimeIndex(start='2015-01-01', end='2016-01-01', freq='1D')
171+
In [1]: times = pd.date_range(start='2015-01-01', end='2016-01-01', freq='1D')
172172

173173
In [1]: sites = [(32, -111, 'Tucson1'), (32.2, -110.9, 'Tucson2'),
174174
...: (33.5, -112.1, 'Phoenix'), (35.1, -106.6, 'Albuquerque')]
@@ -608,7 +608,7 @@ GHI data. We first generate and plot the clear sky and measured data.
608608
609609
abq = Location(35.04, -106.62, altitude=1619)
610610
611-
times = pd.DatetimeIndex(start='2012-04-01 10:30:00', tz='Etc/GMT+7', periods=30, freq='1min')
611+
times = pd.date_range(start='2012-04-01 10:30:00', tz='Etc/GMT+7', periods=30, freq='1min')
612612
613613
cs = abq.get_clearsky(times)
614614

docs/sphinx/source/forecasts.rst

+5-6
Original file line numberDiff line numberDiff line change
@@ -440,19 +440,18 @@ for details.
440440
.. ipython:: python
441441
442442
from pvlib.pvsystem import PVSystem, retrieve_sam
443+
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
443444
from pvlib.tracking import SingleAxisTracker
444445
from pvlib.modelchain import ModelChain
445446
446447
sandia_modules = retrieve_sam('sandiamod')
447448
cec_inverters = retrieve_sam('cecinverter')
448449
module = sandia_modules['Canadian_Solar_CS5P_220M___2009_']
449450
inverter = cec_inverters['SMA_America__SC630CP_US_315V__CEC_2012_']
451+
temperature_model_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
450452
451453
# model a big tracker for more fun
452-
system = SingleAxisTracker(module_parameters=module,
453-
inverter_parameters=inverter,
454-
modules_per_string=15,
455-
strings_per_inverter=300)
454+
system = SingleAxisTracker(module_parameters=module, inverter_parameters=inverter, temperature_model_parameters=temperature_model_parameters, modules_per_string=15, strings_per_inverter=300)
456455
457456
# fx is a common abbreviation for forecast
458457
fx_model = GFS()
@@ -480,9 +479,9 @@ Here's the forecast plane of array irradiance...
480479

481480
.. ipython:: python
482481
483-
mc.temps.plot();
482+
mc.cell_temperature.plot();
484483
@savefig pv_temps.png width=6in
485-
plt.ylabel('Temperature (C)');
484+
plt.ylabel('Cell Temperature (C)');
486485
@suppress
487486
plt.close();
488487

docs/sphinx/source/introexamples.rst

+12-8
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ configuration at a handful of sites listed below.
3030
import pandas as pd
3131
import matplotlib.pyplot as plt
3232
33-
naive_times = pd.DatetimeIndex(start='2015', end='2016', freq='1h')
33+
naive_times = pd.date_range(start='2015', end='2016', freq='1h')
3434
3535
# very approximate
3636
# latitude, longitude, name, altitude, timezone
@@ -46,6 +46,7 @@ configuration at a handful of sites listed below.
4646
sapm_inverters = pvlib.pvsystem.retrieve_sam('cecinverter')
4747
module = sandia_modules['Canadian_Solar_CS5P_220M___2009_']
4848
inverter = sapm_inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_']
49+
temperature_model_parameters = pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
4950
5051
# specify constant ambient air temp and wind for simplicity
5152
temp_air = 20
@@ -88,12 +89,13 @@ to accomplish our system modeling goal:
8889
cs['dni'], cs['ghi'], cs['dhi'],
8990
dni_extra=dni_extra,
9091
model='haydavies')
91-
temps = pvlib.pvsystem.sapm_celltemp(total_irrad['poa_global'],
92-
wind_speed, temp_air)
92+
tcell = pvlib.temperature.sapm_cell(total_irrad['poa_global'],
93+
temp_air, wind_speed,
94+
**temperature_model_parameters)
9395
effective_irradiance = pvlib.pvsystem.sapm_effective_irradiance(
9496
total_irrad['poa_direct'], total_irrad['poa_diffuse'],
9597
am_abs, aoi, module)
96-
dc = pvlib.pvsystem.sapm(effective_irradiance, temps['temp_cell'], module)
98+
dc = pvlib.pvsystem.sapm(effective_irradiance, tcell, module)
9799
ac = pvlib.pvsystem.snlinverter(dc['v_mp'], dc['p_mp'], inverter)
98100
annual_energy = ac.sum()
99101
energies[name] = annual_energy
@@ -149,7 +151,8 @@ by examining the parameters defined for the module.
149151
from pvlib.modelchain import ModelChain
150152
151153
system = PVSystem(module_parameters=module,
152-
inverter_parameters=inverter)
154+
inverter_parameters=inverter,
155+
temperature_model_parameters=temperature_model_parameters)
153156
154157
energies = {}
155158
for latitude, longitude, name, altitude, timezone in coordinates:
@@ -214,6 +217,7 @@ modeling goal:
214217
for latitude, longitude, name, altitude, timezone in coordinates:
215218
localized_system = LocalizedPVSystem(module_parameters=module,
216219
inverter_parameters=inverter,
220+
temperature_model_parameters=temperature_model_parameters,
217221
surface_tilt=latitude,
218222
surface_azimuth=180,
219223
latitude=latitude,
@@ -229,15 +233,15 @@ modeling goal:
229233
clearsky['dni'],
230234
clearsky['ghi'],
231235
clearsky['dhi'])
232-
temps = localized_system.sapm_celltemp(total_irrad['poa_global'],
233-
wind_speed, temp_air)
236+
tcell = localized_system.sapm_celltemp(total_irrad['poa_global'],
237+
temp_air, wind_speed)
234238
aoi = localized_system.get_aoi(solar_position['apparent_zenith'],
235239
solar_position['azimuth'])
236240
airmass = localized_system.get_airmass(solar_position=solar_position)
237241
effective_irradiance = localized_system.sapm_effective_irradiance(
238242
total_irrad['poa_direct'], total_irrad['poa_diffuse'],
239243
airmass['airmass_absolute'], aoi)
240-
dc = localized_system.sapm(effective_irradiance, temps['temp_cell'])
244+
dc = localized_system.sapm(effective_irradiance, tcell)
241245
ac = localized_system.snlinverter(dc['v_mp'], dc['p_mp'])
242246
annual_energy = ac.sum()
243247
energies[name] = annual_energy

docs/sphinx/source/modelchain.rst

+47-14
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ objects, module data, and inverter data.
4545
from pvlib.pvsystem import PVSystem
4646
from pvlib.location import Location
4747
from pvlib.modelchain import ModelChain
48+
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
49+
temperature_model_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
4850
4951
# load some module and inverter specifications
5052
sandia_modules = pvlib.pvsystem.retrieve_sam('SandiaMod')
@@ -61,7 +63,8 @@ object.
6163
location = Location(latitude=32.2, longitude=-110.9)
6264
system = PVSystem(surface_tilt=20, surface_azimuth=200,
6365
module_parameters=sandia_module,
64-
inverter_parameters=cec_inverter)
66+
inverter_parameters=cec_inverter,
67+
temperature_model_parameters=temperature_model_parameters)
6568
mc = ModelChain(system, location)
6669
6770
Printing a ModelChain object will display its models.
@@ -87,6 +90,10 @@ examples are shown below.
8790
8891
mc.aoi
8992
93+
.. ipython:: python
94+
95+
mc.cell_temperature
96+
9097
.. ipython:: python
9198
9299
mc.dc
@@ -141,8 +148,11 @@ model, AC model, AOI loss model, and spectral loss model.
141148

142149
.. ipython:: python
143150
144-
sapm_system = PVSystem(module_parameters=sandia_module, inverter_parameters=cec_inverter)
145-
mc = ModelChain(system, location)
151+
sapm_system = PVSystem(
152+
module_parameters=sandia_module,
153+
inverter_parameters=cec_inverter,
154+
temperature_model_parameters=temperature_model_parameters)
155+
mc = ModelChain(sapm_system, location)
146156
print(mc)
147157
148158
.. ipython:: python
@@ -160,7 +170,10 @@ information to determine which of those models to choose.
160170

161171
.. ipython:: python
162172
163-
pvwatts_system = PVSystem(module_parameters={'pdc0': 240, 'gamma_pdc': -0.004})
173+
pvwatts_system = PVSystem(
174+
module_parameters={'pdc0': 240, 'gamma_pdc': -0.004},
175+
inverter_parameters={'pdc0': 240},
176+
temperature_model_parameters=temperature_model_parameters)
164177
mc = ModelChain(pvwatts_system, location,
165178
aoi_model='physical', spectral_model='no_loss')
166179
print(mc)
@@ -176,8 +189,11 @@ functions for a PVSystem that contains SAPM-specific parameters.
176189

177190
.. ipython:: python
178191
179-
sapm_system = PVSystem(module_parameters=sandia_module, inverter_parameters=cec_inverter)
180-
mc = ModelChain(system, location, aoi_model='physical', spectral_model='no_loss')
192+
sapm_system = PVSystem(
193+
module_parameters=sandia_module,
194+
inverter_parameters=cec_inverter,
195+
temperature_model_parameters=temperature_model_parameters)
196+
mc = ModelChain(sapm_system, location, aoi_model='physical', spectral_model='no_loss')
181197
print(mc)
182198
183199
.. ipython:: python
@@ -264,21 +280,24 @@ the ModelChain.pvwatts_dc method is shown below. Its only argument is
264280
265281
The ModelChain.pvwatts_dc method calls the pvwatts_dc method of the
266282
PVSystem object that we supplied using data that is stored in its own
267-
``effective_irradiance`` and ``temps`` attributes. Then it assigns the
283+
``effective_irradiance`` and ``cell_temperature`` attributes. Then it assigns the
268284
result to the ``dc`` attribute of the ModelChain object. The code below
269285
shows a simple example of this.
270286

271287
.. ipython:: python
272288
273289
# make the objects
274-
pvwatts_system = PVSystem(module_parameters={'pdc0': 240, 'gamma_pdc': -0.004})
290+
pvwatts_system = PVSystem(
291+
module_parameters={'pdc0': 240, 'gamma_pdc': -0.004},
292+
inverter_parameters={'pdc0': 240},
293+
temperature_model_parameters=temperature_model_parameters)
275294
mc = ModelChain(pvwatts_system, location,
276295
aoi_model='no_loss', spectral_model='no_loss')
277296
278297
# manually assign data to the attributes that ModelChain.pvwatts_dc will need.
279298
# for standard workflows, run_model would assign these attributes.
280299
mc.effective_irradiance = pd.Series(1000, index=[pd.Timestamp('20170401 1200-0700')])
281-
mc.temps = pd.DataFrame({'temp_cell': 50, 'temp_module': 50}, index=[pd.Timestamp('20170401 1200-0700')])
300+
mc.cell_temperature = pd.Series(50, index=[pd.Timestamp('20170401 1200-0700')])
282301
283302
# run ModelChain.pvwatts_dc and look at the result
284303
mc.pvwatts_dc();
@@ -304,13 +323,16 @@ PVSystem.scale_voltage_current_power method.
304323
.. ipython:: python
305324
306325
# make the objects
307-
sapm_system = PVSystem(module_parameters=sandia_module, inverter_parameters=cec_inverter)
326+
sapm_system = PVSystem(
327+
module_parameters=sandia_module,
328+
inverter_parameters=cec_inverter,
329+
temperature_model_parameters=temperature_model_parameters)
308330
mc = ModelChain(sapm_system, location)
309331
310332
# manually assign data to the attributes that ModelChain.sapm will need.
311333
# for standard workflows, run_model would assign these attributes.
312334
mc.effective_irradiance = pd.Series(1000, index=[pd.Timestamp('20170401 1200-0700')])
313-
mc.temps = pd.DataFrame({'temp_cell': 50, 'temp_module': 50}, index=[pd.Timestamp('20170401 1200-0700')])
335+
mc.cell_temperature = pd.Series(50, index=[pd.Timestamp('20170401 1200-0700')])
314336
315337
# run ModelChain.sapm and look at the result
316338
mc.sapm();
@@ -333,7 +355,10 @@ section.
333355

334356
.. ipython:: python
335357
336-
pvwatts_system = PVSystem(module_parameters={'pdc0': 240, 'gamma_pdc': -0.004})
358+
pvwatts_system = PVSystem(
359+
module_parameters={'pdc0': 240, 'gamma_pdc': -0.004},
360+
inverter_parameters={'pdc0': 240},
361+
temperature_model_parameters=temperature_model_parameters)
337362
mc = ModelChain(pvwatts_system, location,
338363
aoi_model='no_loss', spectral_model='no_loss')
339364
mc.dc_model.__func__
@@ -403,18 +428,26 @@ function if you wanted to.
403428
return mc
404429
405430
406-
def pvusa_ac_mc_wrapper(mc):
431+
def pvusa_ac_mc(mc):
407432
# keep it simple
408433
mc.ac = mc.dc
409434
return mc
410435
436+
437+
def no_loss_temperature(mc):
438+
# keep it simple
439+
mc.cell_temperature = mc.weather['temp_air']
440+
return mc
441+
442+
411443
.. ipython:: python
412444
413445
module_parameters = {'a': 0.2, 'b': 0.00001, 'c': 0.001, 'd': -0.00005}
414446
pvusa_system = PVSystem(module_parameters=module_parameters)
415447
416448
mc = ModelChain(pvusa_system, location,
417-
dc_model=pvusa_mc_wrapper, ac_model=pvusa_ac_mc_wrapper,
449+
dc_model=pvusa_mc_wrapper, ac_model=pvusa_ac_mc,
450+
temperature_model=no_loss_temperature,
418451
aoi_model='no_loss', spectral_model='no_loss')
419452
420453
A ModelChain object uses Python’s functools.partial function to assign

0 commit comments

Comments
 (0)