8000 Implement CEC model by cwhanse · Pull Request #560 · pvlib/pvlib-python · GitHub
[go: up one dir, main page]

Skip to content

Implement CEC model #560

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 8, 2018
Merged
Show file tree
Hide file tree
Changes from 6 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
26 changes: 24 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 @@ -431,6 +437,22 @@ def desoto(self):

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

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):
Expand Down
182 changes: 177 additions & 5 deletions pvlib/pvsystem.py
8000
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,146 @@ 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 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

Notes
-----
The CEC model differs from the De soto et al. model [3] only in the
parameter adjust.
'''

# 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
0