Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ Functions relevant for single diode models.
.. autosummary::
:toctree: generated/

pvsystem.calcparams_cec
pvsystem.calcparams_desoto
pvsystem.calcparams_pvsyst
pvsystem.i_from_v
Expand Down Expand Up @@ -419,6 +420,7 @@ ModelChain model definitions.
:toctree: generated/

modelchain.ModelChain.sapm
modelchain.ModelChain.cec
modelchain.ModelChain.desoto
modelchain.ModelChain.pvsyst
modelchain.ModelChain.pvwatts_dc
Expand Down
12 changes: 9 additions & 3 deletions docs/sphinx/source/whatsnew/v0.6.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,13 @@ API Changes
dirindex functions. (:issue:`311`, :issue:`396`)
* Method ModelChain.infer_dc_model now returns a tuple (function handle, model name string)
instead of only the function handle (:issue:`417`)
* Add DC model methods desoto and pvsyst to ModelChain, and deprecates DC model method singlediode
(singlediode defaults to desoto until v0.7.0) (:issue:`487`)
* Add DC model methods desoto and pvsyst to ModelChain, and deprecates DC model method
singlediode (singlediode defaults to desoto until v0.7.0) (:issue:`487`)
* Add the CEC module model in pvsystem.calcparams_cec and ModelChain.cec. The CEC model
differs from the desoto model by using the parameter Adjust. Modules selected from
the SAM CEC library sam-library-cec-modules-2017-6-5.csv include the Adjust parameter
and ModelChain.infer_dc_model will now select the cec model rather than the desoto model.
(:issue:`463`)


Enhancements
Expand Down Expand Up @@ -106,7 +111,8 @@ Enhancements
* Add irradiance.clearness_index function. (:issue:`396`)
* Add irradiance.clearness_index_zenith_independent function. (:issue:`396`)
* Add checking for consistency between module_parameters and dc_model. (:issue:`417`)
* Add DC model methods desoto and pvsyst to ModelChain (:issue:`487`)
* Add DC model methods ``'desoto'`` and ``'pvsyst'`` to ModelChain (:issue:`487`)
* Add the CEC module model in `pvsystem.calcparams_cec` and `ModelChain.cec`. (:issue:`463`)


Bug fixes
Expand Down
28 changes: 26 additions & 2 deletions pvlib/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ class ModelChain(object):
dc_model: None, str, or function, default None
If None, the model will be inferred from the contents of
system.module_parameters. Valid strings are 'sapm',
'desoto', 'pvsyst', 'pvwatts'. The ModelChain instance will
'desoto', 'cec', 'pvsyst', 'pvwatts'. The ModelChain instance will
be passed as the first argument to a user-defined function.

ac_model: None, str, or function, default None
Expand Down Expand Up @@ -376,6 +376,8 @@ def dc_model(self, model):
self._dc_model = self.sapm
elif model == 'desoto':
self._dc_model = self.desoto
elif model == 'cec':
self._dc_model = self.cec
elif model == 'pvsyst':
self._dc_model = self.pvsyst
elif model == 'pvwatts':
Expand All @@ -396,7 +398,11 @@ def infer_dc_model(self):
params = set(self.system.module_parameters.keys())
if set(['A0', 'A1', 'C7']) <= params:
return self.sapm, 'sapm'
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s']) <= params:
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
'R_s', 'Adjust']) <= params:
return self.cec, 'cec'
elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
'R_s']) <= params:
return self.desoto, 'desoto'
elif set(['gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref',
'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s']) <= params:
Expand Down Expand Up @@ -433,6 +439,24 @@ def desoto(self):

return self

def cec(self):
(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) = (
self.system.calcparams_cec(self.effective_irradiance,
self.temps['temp_cell']))

self.diode_params = (photocurrent, saturation_current,
resistance_series,
resistance_shunt, nNsVth)

self.dc = self.system.singlediode(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)

self.dc = self.system.scale_voltage_current_power(self.dc).fillna(0)

return self

def pvsyst(self):
(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) = (
Expand Down
179 changes: 174 additions & 5 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,26 @@

# a dict of required parameter names for each DC power model
DC_MODEL_PARAMS = {
'sapm' : set([
'sapm': set([
'A0', 'A1', 'A2', 'A3', 'A4', 'B0', 'B1', 'B2', 'B3',
'B4', 'B5', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6',
'C7', 'Isco', 'Impo', 'Aisc', 'Aimp', 'Bvoco',
'Mbvoc', 'Bvmpo', 'Mbvmp', 'N', 'Cells_in_Series',
'IXO', 'IXXO', 'FD']),
'desoto' : set([
'desoto': set([
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
'R_sh_ref', 'R_s']),
'pvsyst' : set([
'cec': set([
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
'R_sh_ref', 'R_s', 'Adjust']),
'pvsyst': set([
'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref',
'R_sh_ref', 'R_sh_0', 'R_s', 'alpha_sc', 'EgRef',
'cells_in_series']),
'singlediode' : set([
'singlediode': set([
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
'R_sh_ref', 'R_s']),
'pvwatts' : set(['pdc0', 'gamma_pdc'])
'pvwatts': set(['pdc0', 'gamma_pdc'])
}


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

return calcparams_desoto(effective_irradiance, temp_cell, **kwargs)

def calcparams_cec(self, effective_irradiance, temp_cell, **kwargs):
"""
Use the :py:func:`calcparams_cec` function, the input
parameters and ``self.module_parameters`` to calculate the
module currents and resistances.

Parameters
----------
effective_irradiance : numeric
The irradiance (W/m2) that is converted to photocurrent.

temp_cell : float or Series
The average cell temperature of cells within a module in C.

**kwargs
See pvsystem.calcparams_cec for details

Returns
-------
See pvsystem.calcparams_cec for details
"""

kwargs = _build_kwargs(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref',
'R_s', 'alpha_sc', 'Adjust', 'EgRef', 'dEgdT',
'irrad_ref', 'temp_ref'],
self.module_parameters)

return calcparams_cec(effective_irradiance, temp_cell, **kwargs)

def calcparams_pvsyst(self, effective_irradiance, temp_cell):
"""
Use the :py:func:`calcparams_pvsyst` function, the input
Expand Down Expand Up @@ -1223,6 +1255,143 @@ def calcparams_desoto(effective_irradiance, temp_cell,
return IL, I0, Rs, Rsh, nNsVth


def calcparams_cec(effective_irradiance, temp_cell,
alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s,
Adjust, EgRef=1.121, dEgdT=-0.0002677,
irrad_ref=1000, temp_ref=25):
'''
Calculates five parameter values for the single diode equation at
effective irradiance and cell temperature using the CEC
model described in [1]. The CEC model differs from the De soto et al.
model [3] by the parameter Adjust. The five values returned by
calcparams_cec can be used by singlediode to calculate an IV curve.

Parameters
----------
effective_irradiance : numeric
The irradiance (W/m2) that is converted to photocurrent.

temp_cell : numeric
The average cell temperature of cells within a module in C.

alpha_sc : float
The short-circuit current temperature coefficient of the
module in units of A/C.

a_ref : float
The product of the usual diode ideality factor (n, unitless),
number of cells in series (Ns), and cell thermal voltage at reference
conditions, in units of V.

I_L_ref : float
The light-generated current (or photocurrent) at reference conditions,
in amperes.

I_o_ref : float
The dark or diode reverse saturation current at reference conditions,
in amperes.

R_sh_ref : float
The shunt resistance at reference conditions, in ohms.

R_s : float
The series resistance at reference conditions, in ohms.

Adjust : float
The adjustment to the temperature coefficient for short circuit
current, in percent

EgRef : float
The energy bandgap at reference temperature in units of eV.
1.121 eV for crystalline silicon. EgRef must be >0. For parameters
from the SAM CEC module database, EgRef=1.121 is implicit for all
cell types in the parameter estimation algorithm used by NREL.

dEgdT : float
The temperature dependence of the energy bandgap at reference
conditions in units of 1/K. May be either a scalar value
(e.g. -0.0002677 as in [3]) or a DataFrame (this may be useful if
dEgdT is a modeled as a function of temperature). For parameters from
the SAM CEC module database, dEgdT=-0.0002677 is implicit for all cell
types in the parameter estimation algorithm used by NREL.

irrad_ref : float (optional, default=1000)
Reference irradiance in W/m^2.

temp_ref : float (optional, default=25)
Reference cell temperature in C.

Returns
-------
Tuple of the following results:

photocurrent : numeric
Light-generated current in amperes

saturation_current : numeric
Diode saturation curent in amperes

resistance_series : float
Series resistance in ohms

resistance_shunt : numeric
Shunt resistance in ohms

nNsVth : numeric
The product of the usual diode ideality factor (n, unitless),
number of cells in series (Ns), and cell thermal voltage at
specified effective irradiance and cell temperature.

References
----------
[1] A. Dobos, "An Improved Coefficient Calculator for the California
Energy Commission 6 Parameter Photovoltaic Module Model", Journal of
Solar Energy Engineering, vol 134, 2012.

[2] System Advisor Model web page. https://sam.nrel.gov.

[3] W. De Soto et al., "Improvement and validation of a model for
photovoltaic array performance", Solar Energy, vol 80, pp. 78-88,
2006.

See Also
--------
calcparams_desoto
singlediode
retrieve_sam

'''

# test for use of function pre-v0.6.0 API change
if isinstance(a_ref, dict) or \
(isinstance(a_ref, pd.Series) and ('a_ref' in a_ref.keys())):
import warnings
warnings.warn('module_parameters detected as fourth positional'
+ ' argument of calcparams_cec. calcparams_cec'
+ ' will require one argument for each module model'
+ ' parameter in v0.7.0 and later', DeprecationWarning)
try:
module_parameters = a_ref
a_ref = module_parameters['a_ref']
I_L_ref = module_parameters['I_L_ref']
I_o_ref = module_parameters['I_o_ref']
R_sh_ref = module_parameters['R_sh_ref']
R_s = module_parameters['R_s']
except Exception as e:
raise e('Module parameters could not be extracted from fourth'
+ ' positional argument of calcparams_desoto. Check that'
+ ' parameters are from the CEC database and/or update'
+ ' your code for the new API for calcparams_desoto')

# pass adjusted temperature coefficient to desoto
return calcparams_desoto(effective_irradiance, temp_cell,
alpha_sc*Adjust/100,
a_ref, I_L_ref, I_o_ref,
R_sh_ref, R_s,
EgRef=1.121, dEgdT=-0.0002677,
irrad_ref=1000, temp_ref=25)


def calcparams_pvsyst(effective_irradiance, temp_cell,
alpha_sc, gamma_ref, mu_gamma,
I_L_ref, I_o_ref,
Expand Down
6 changes: 6 additions & 0 deletions pvlib/test/test_modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ def poadc(mc):

@pytest.mark.parametrize('dc_model', [
'sapm',
pytest.param('cec', marks=requires_scipy),
pytest.param('desoto', marks=requires_scipy),
pytest.param('pvsyst', marks=requires_scipy),
pytest.param('singlediode', marks=requires_scipy),
Expand All @@ -227,16 +228,21 @@ def test_infer_dc_model(system, cec_dc_snl_ac_system, pvsyst_dc_snl_ac_system,
pvwatts_dc_pvwatts_ac_system, location, dc_model,
weather, mocker):
dc_systems = {'sapm': system,
'cec': cec_dc_snl_ac_system,
'desoto': cec_dc_snl_ac_system,
'pvsyst': pvsyst_dc_snl_ac_system,
'singlediode': cec_dc_snl_ac_system,
'pvwatts_dc': pvwatts_dc_pvwatts_ac_system}
dc_model_function = {'sapm': 'sapm',
'cec': 'calcparams_cec',
'desoto': 'calcparams_desoto',
'pvsyst': 'calcparams_pvsyst',
'singlediode': 'calcparams_desoto',
'pvwatts_dc': 'pvwatts_dc'}
system = dc_systems[dc_model]
# remove Adjust from model parameters for desoto, singlediode
if dc_model in ['desoto', 'singlediode']:
system.module_parameters.pop('Adjust')
m = mocker.spy(system, dc_model_function[dc_model])
mc = ModelChain(system, location,
aoi_model='no_loss', spectral_model='no_loss')
Expand Down
Loading