8000 Implement CEC model (#560) · aliyevsultan/pvlib-python@710e27e · GitHub
[go: up one dir, main page]

Skip to content

Commit 710e27e

Browse files
cwhansewholmgren
authored andcommitted
Implement CEC model (pvlib#560)
* Implement CEC model * Add cec to test_infer_dc_model * Adjust test_infer_dc_model for desoto, singlediode cases * Reapply edits to DC_MODEL_PARAMS * Fix stickler comments * Add test for pvsystem.calcparams_cec, extend test for calcparams_desoto, update whatnews.rst and api.rst * Remove whitespace * Replace np.round with check_less_precise in pd.Series tests * Correct expression for alpha_sc in calcparams_cec * Fix whatsnew * Remove old API test from calcparams_cec
1 parent 2b51d4a commit 710e27e

File tree

6 files changed

+236
-17
lines changed

6 files changed

+236
-17
lines changed

docs/sphinx/source/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ Functions relevant for single diode models.
212212
.. autosummary::
213213
:toctree: generated/
214214

215+
pvsystem.calcparams_cec
215216
pvsystem.calcparams_desoto
216217
pvsystem.calcparams_pvsyst
217218
pvsystem.i_from_v
@@ -419,6 +420,7 @@ ModelChain model definitions.
419420
:toctree: generated/
420421

421422
modelchain.ModelChain.sapm
423+
modelchain.ModelChain.cec
422424
modelchain.ModelChain.desoto
423425
modelchain.ModelChain.pvsyst
424426
modelchain.ModelChain.pvwatts_dc

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,13 @@ API Changes
5353
dirindex functions. (:issue:`311`, :issue:`396`)
5454
* Method ModelChain.infer_dc_model now returns a tuple (function handle, model name string)
5555
instead of only the function handle (:issue:`417`)
56-
* Add DC model methods desoto and pvsyst to ModelChain, and deprecates DC model method singlediode
57-
(singlediode defaults to desoto until v0.7.0) (:issue:`487`)
56+
* Add DC model methods desoto and pvsyst to ModelChain, and deprecates DC model method
57+
singlediode (singlediode defaults to desoto until v0.7.0) (:issue:`487`)
58+
* Add the CEC module model in pvsystem.calcparams_cec and ModelChain.cec. The CEC model
59+
differs from the desoto model by using the parameter Adjust. Modules selected from
60+
the SAM CEC library sam-library-cec-modules-2017-6-5.csv include the Adjust parameter
61+
and ModelChain.infer_dc_model will now select the cec model rather than the desoto model.
62+
(:issue:`463`)
5863
* The behavior of irradiance.perez(return_components=True) has changed.
5964
The function previously returned a tuple of total sky diffuse and
6065
an OrderedDict/DataFrame of components. The function now returns
@@ -111,6 +116,8 @@ Enhancements
111116
* Add irradiance.clearness_index function. (:issue:`396`)
112117
* Add irradiance.clearness_index_zenith_independent function. (:issue:`396`)
113118
* Add checking for consistency between module_parameters and dc_model. (:issue:`417`)
119+
* Add DC model methods ``'desoto'`` and ``'pvsyst'`` to ModelChain (:issue:`487`)
120+
* Add the CEC module model in `pvsystem.calcparams_cec` and `ModelChain.cec`. (:issue:`463`)
114121
* Add DC model methods desoto and pvsyst to ModelChain (:issue:`487`)
115122
* Set default alpha to 1.14 in :func:`~pvlib.atmosphere.angstrom_aod_at_lambda` (:issue:`563`)
116123

pvlib/modelchain.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ class ModelChain(object):
247247
dc_model: None, str, or function, default None
248248
If None, the model will be inferred from the contents of
249249
system.module_parameters. Valid strings are 'sapm',
250-
'desoto', 'pvsyst', 'pvwatts'. The ModelChain instance will
250+
'desoto', 'cec', 'pvsyst', 'pvwatts'. The ModelChain instance will
251251
be passed as the first argument to a user-defined function.
252252
253253
ac_model: None, str, or function, default None
@@ -376,6 +376,8 @@ def dc_model(self, model):
376376
self._dc_model = self.sapm
377377
elif model == 'desoto':
378378
self._dc_model = self.desoto
379+
elif model == 'cec':
380+
self._dc_model = self.cec
379381
elif model == 'pvsyst':
380382
self._dc_model = self.pvsyst
381383
elif model == 'pvwatts':
@@ -396,7 +398,11 @@ def infer_dc_model(self):
396398
params = set(self.system.module_parameters.keys())
397399
if set(['A0', 'A1', 'C7']) <= params:
398400
return self.sapm, 'sapm'
399-
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s']) <= params:
401+
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
402+
'R_s', 'Adjust']) <= params:
403+
return self.cec, 'cec'
404+
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
405+
'R_s']) <= params:
400406
return self.desoto, 'desoto'
401407
elif set(['gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref',
402408
'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s']) <= params:
@@ -433,6 +439,24 @@ def desoto(self):
433439

434440
return self
435441

442+
def cec(self):
443+
(photocurrent, saturation_current, resistance_series,
444+
resistance_shunt, nNsVth) = (
445+
self.system.calcparams_cec(self.effective_irradiance,
446+
self.temps['temp_cell']))
447+
448+
self.diode_params = (photocurrent, saturation_current,
449+
resistance_series,
450+
resistance_shunt, nNsVth)
451+
452+
self.dc = self.system.singlediode(
453+
10000 photocurrent, saturation_current, resistance_series,
454+
resistance_shunt, nNsVth)
455+
456+
self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0)
457+
458+
return self
459+
436460
def pvsyst(self):
437461
(photocurrent, saturation_current, resistance_series,
438462
resistance_shunt, nNsVth) = (

pvlib/pvsystem.py

Lines changed: 153 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,26 @@
2323

2424
# a dict of required parameter names for each DC power model
2525
DC_MODEL_PARAMS = {
26-
'sapm' : set([
26+
'sapm': set([
2727
'A0', 'A1', 'A2', 'A3', 'A4', 'B0', 'B1', 'B2', 'B3',
2828
'B4', 'B5', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6',
2929
'C7', 'Isco', 'Impo', 'Aisc', 'Aimp', 'Bvoco',
3030
'Mbvoc', 'Bvmpo', 'Mbvmp', 'N', 'Cells_in_Series',
3131
'IXO', 'IXXO', 'FD']),
32-
'desoto' : set([
32+
'desoto': set([
3333
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
3434
'R_sh_ref', 'R_s']),
35-
'pvsyst' : set([
35+
'cec': set([
36+
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
37+
'R_sh_ref', 'R_s', 'Adjust']),
38+
'pvsyst': set([
3639
'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref',
3740
'R_sh_ref', 'R_sh_0', 'R_s', 'alpha_sc', 'EgRef',
3841
'cells_in_series']),
39-
'singlediode' : set([
42+
'singlediode': set([
4043
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
4144
'R_sh_ref', 'R_s']),
42-
'pvwatts' : set(['pdc0', 'gamma_pdc'])
45+
'pvwatts': set(['pdc0', 'gamma_pdc'])
4346
}
4447

4548

@@ -336,6 +339,35 @@ def calcparams_desoto(self, effective_irradiance, temp_cell, **kwargs):
336339

337340
return calcparams_desoto(effective_irradiance, temp_cell, **kwargs)
338341

342+
def calcparams_cec(self, effective_irradiance, temp_cell, **kwargs):
343+
"""
344+
Use the :py:func:`calcparams_cec` function, the input
345+
parameters and ``self.module_parameters`` to calculate the
346+
module currents and resistances.
347+
348+
Parameters
349+
----------
350+
effective_irradiance : numeric
351+
The irradiance (W/m2) that is converted to photocurrent.
352+
353+
temp_cell : float or Series
354+
The average cell temperature of cells within a module in C.
355+
356+
**kwargs
357+
See pvsystem.calcparams_cec for details
358+
359+
Returns
360+
-------
361+
See pvsystem.calcparams_cec for details
362+
"""
363+
364+
kwargs = _build_kwargs(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
365+
'R_s', 'alpha_sc', 'Adjust', 'EgRef', 'dEgdT',
366+
'irrad_ref', 'temp_ref'],
367+
self.module_parameters)
368+
369+
return calcparams_cec(effective_irradiance, temp_cell, **kwargs)
370+
339371
def calcparams_pvsyst(self, effective_irradiance, temp_cell):
340372
"""
341373
Use the :py:func:`calcparams_pvsyst` function, the input
@@ -1223,6 +1255,122 @@ def calcparams_desoto(effective_irradiance, temp_cell,
12231255
return IL, I0, Rs, Rsh, nNsVth
12241256

12251257

1258+
def calcparams_cec(effective_irradiance, temp_cell,
1259+
alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s,
1260+
Adjust, EgRef=1.121, dEgdT=-0.0002677,
1261+
irrad_ref=1000, temp_ref=25):
1262+
'''
1263+
Calculates five parameter values for the single diode equation at
1264+
effective irradiance and cell temperature using the CEC
1265+
model described in [1]. The CEC model differs from the De soto et al.
1266+
model [3] by the parameter Adjust. The five values returned by
1267+
calcparams_cec can be used by singlediode to calculate an IV curve.
1268+
1269+
Parameters
1270+
----------
1271+
effective_irradiance : numeric
1272+
The irradiance (W/m2) that is converted to photocurrent.
1273+
1274+
temp_cell : numeric
1275+
The average cell temperature of cells within a module in C.
1276+
1277+
alpha_sc : float
1278+
The short-circuit current temperature coefficient of the
1279+
module in units of A/C.
1280+
1281+
a_ref : float
1282+
The product of the usual diode ideality factor (n, unitless),
1283+
number of cells in series (Ns), and cell thermal voltage at reference
1284+
conditions, in units of V.
1285+
1286+
I_L_ref : float
1287+
The light-generated current (or photocurrent) at reference conditions,
1288+
in amperes.
1289+
1290+
I_o_ref : float
1291+
The dark or diode reverse saturation current at reference conditions,
1292+
in amperes.
1293+
1294+
R_sh_ref : float
1295+
The shunt resistance at reference conditions, in ohms.
1296+
1297+
R_s : float
1298+
The series resistance at reference conditions, in ohms.
1299+
1300+
Adjust : float
1301+
The adjustment to the temperature coefficient for short circuit
1302+
current, in percent
1303+
1304+
EgRef : float
1305+
The energy bandgap at reference temperature in units of eV.
< 10000 /td>1306+
1.121 eV for crystalline silicon. EgRef must be >0. For parameters
1307+
from the SAM CEC module database, EgRef=1.121 is implicit for all
1308+
cell types in the parameter estimation algorithm used by NREL.
1309+
1310+
dEgdT : float
1311+
The temperature dependence of the energy bandgap at reference
1312+
conditions in units of 1/K. May be either a scalar value
1313+
(e.g. -0.0002677 as in [3]) or a DataFrame (this may be useful if
1314+
dEgdT is a modeled as a function of temperature). For parameters from
1315+
the SAM CEC module database, dEgdT=-0.0002677 is implicit for all cell
1316+
types in the parameter estimation algorithm used by NREL.
1317+
1318+
irrad_ref : float (optional, default=1000)
1319+
Reference irradiance in W/m^2.
1320+
1321+
temp_ref : float (optional, default=25)
1322+
Reference cell temperature in C.
1323+
1324+
Returns
1325+
-------
1326+
Tuple of the following results:
1327+
1328+
photocurrent : numeric
1329+
Light-generated current in amperes
1330+
1331+
saturation_current : numeric
1332+
Diode saturation curent in amperes
1333+
1334+
resistance_series : float
1335+
Series resistance in ohms
1336+
1337+
resistance_shunt : numeric
1338+
Shunt resistance in ohms
1339+
1340+
nNsVth : numeric
1341+
The product of the usual diode ideality factor (n, unitless),
1342+
number of cells in series (Ns), and cell thermal voltage at
1343+
specified effective irradiance and cell temperature.
1344+
1345+
References
1346+
----------
1347+
[1] A. Dobos, "An Improved Coefficient Calculator for the California
1348+
Energy Commission 6 Parameter Photovoltaic Module Model", Journal of
1349+
Solar Energy Engineering, vol 134, 2012.
1350+
1351+
[2] System Advisor Model web page. https://sam.nrel.gov.
1352+
1353+
[3] W. De Soto et al., "Improvement and validation of a model for
1354+
photovoltaic array performance", Solar Energy, vol 80, pp. 78-88,
1355+
2006.
1356+
1357+
See Also
1358+
--------
1359+
calcparams_desoto
1360+
singlediode
1361+
retrieve_sam
1362+
1363+
'''
1364+
1365+
# pass adjusted temperature coefficient to desoto
1366+
return calcparams_desoto(effective_irradiance, temp_cell,
1367+
alpha_sc*(1.0 - Adjust/100),
1368+
a_ref, I_L_ref, I_o_ref,
1369+
R_sh_ref, R_s,
1370+
EgRef=1.121, dEgdT=-0.0002677,
1371+
irrad_ref=1000, temp_ref=25)
1372+
1373+
12261374
def calcparams_pvsyst(effective_irradiance, temp_cell,
12271375
alpha_sc, gamma_ref, mu_gamma,
12281376
I_L_ref, I_o_ref,

pvlib/test/test_modelchain.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ def poadc(mc):
219219

220220
@pytest.mark.parametrize('dc_model', [
221221
'sapm',
222+
pytest.param('cec', marks=requires_scipy),
222223
pytest.param('desoto', marks=requires_scipy),
223224
pytest.param('pvsyst', marks=requires_scipy),
224225
pytest.param('singlediode', marks=requires_scipy),
@@ -227,16 +228,21 @@ def test_infer_dc_model(system, cec_dc_snl_ac_system, pvsyst_dc_snl_ac_system,
227228
pvwatts_dc_pvwatts_ac_system, location, dc_model,
228229
weather, mocker):
229230
dc_systems = {'sapm': system,
231+
'cec': cec_dc_snl_ac_system,
230232
'desoto': cec_dc_snl_ac_system,
231233
'pvsyst': pvsyst_dc_snl_ac_system,
232234
'singlediode': cec_dc_snl_ac_system,
233235
'pvwatts_dc': pvwatts_dc_pvwatts_ac_system}
234236
dc_model_function = {'sapm': 'sapm',
237+
'cec': 'calcparams_cec',
235238
'desoto': 'calcparams_desoto',
236239
'pvsyst': 'calcparams_pvsyst',
237240
'singlediode': 'calcparams_desoto',
238241
'pvwatts_dc': 'pvwatts_dc'}
239242
system = dc_systems[dc_model]
243+
# remove Adjust from model parameters for desoto, singlediode
244+
if dc_model in ['desoto', 'singlediode']:
245+
system.module_parameters.pop('Adjust')
240246
m = mocker.spy(system, dc_model_function[dc_model])
241247
mc = ModelChain(system, location,
242248
aoi_model='no_loss', spectral_model='no_loss')

pvlib/test/test_pvsystem.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,9 @@ def test_PVSystem_sapm_effective_irradiance(sapm_module_params, mocker):
379379

380380

381381
def test_calcparams_desoto(cec_module_params):
382-
times = pd.DatetimeIndex(start='2015-01-01', periods=2, freq='12H')
383-
effective_irradiance = pd.Series([0.0, 800.0], index=times)
384-
temp_cell = pd.Series([25, 25], index=times)
382+
times = pd.DatetimeIndex(start='2015-01-01', periods=3, freq='12H')
383+
effective_irradiance = pd.Series([0.0, 800.0, 800.0], index=times)
384+
temp_cell = pd.Series([25, 25, 50], index=times)
385385

386386
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
387387
effective_irradiance,
@@ -395,12 +395,44 @@ def test_calcparams_desoto(cec_module_params):
395395
EgRef=1.121,
396396
dEgdT=-0.0002677)
397397

398-
assert_series_equal(np.round(IL, 3), pd.Series([0.0, 6.036], index=times))
399-
# changed value in GH 444 for 2017-6-5 module file
400-
assert_allclose(I0, 1.94e-9)
398+
assert_series_equal(IL, pd.Series([0.0, 6.036, 6.096], index=times),
399+
check_less_precise=3)
400+
assert_series_equal(I0, pd.Series([0.0, 1.94e-9, 7.419e-8], index=times),
401+
check_less_precise=3)
402+
assert_allclose(Rs, 0.094)
403+
assert_series_equal(Rsh, pd.Series([np.inf, 19.65, 19.65], index=times),
404+
check_less_precise=3)
405+
assert_series_equal(nNsVth, pd.Series([0.473, 0.473, 0.5127], index=times),
406+
check_less_precise=3)
407+
408+
409+
def test_calcparams_cec(cec_module_params):
410+
times = pd.DatetimeIndex(start='2015-01-01', periods=3, freq='12H')
411+
effective_irradiance = pd.Series([0.0, 800.0, 800.0], index=times)
412+
temp_cell = pd.Series([25, 25, 50], index=times)
413+
414+
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_cec(
415+
effective_irradiance,
416+
temp_cell,
417+
alpha_sc=cec_module_params['alpha_sc'],
418+
a_ref=cec_module_params['a_ref'],
419+
I_L_ref=cec_module_params['I_L_ref'],
420+
I_o_ref=cec_module_params['I_o_ref'],
421+
R_sh_ref=cec_module_params['R_sh_ref'],
422+
R_s=cec_module_params['R_s'],
423+
Adjust=cec_module_params['Adjust'],
424+
EgRef=1.121,
425+
dEgdT=-0.0002677)
426+
427+
assert_series_equal(IL, pd.Series([0.0, 6.036, 6.0896], index=times),
428+
check_less_precise=3)
429+
assert_series_equal(I0, pd.Series([0.0, 1.94e-9, 7.419e-8], index=times),
430+
check_less_precise=3)
401431
assert_allclose(Rs, 0.094)
402-
assert_series_equal(np.round(Rsh, 3), pd.Series([np.inf, 19.65], index=times))
403-
assert_allclose(nNsVth, 0.473)
432+
assert_series_equal(Rsh, pd.Series([np.inf, 19.65, 19.65], index=times),
433+
check_less_precise=3)
434+
assert_series_equal(nNsVth, pd.Series([0.473, 0.473, 0.5127], index=times),
435+
check_less_precise=3)
404436

405437

406438
def test_calcparams_pvsyst(pvsyst_module_params):

0 commit comments

Comments
 (0)
0