From b4737d31bf5260aa828e291e976870ef8f0efab2 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 10:52:37 -0600 Subject: [PATCH 01/12] Add desoto and pvsyst as dc_model options to ModelChain --- pvlib/modelchain.py | 57 ++++++++++++++++++++++++++++++++--- pvlib/pvsystem.py | 4 +++ pvlib/test/test_modelchain.py | 27 +++++++++++++++-- 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index dece562297..13f7ce5326 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -251,8 +251,8 @@ 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', - 'singlediode', 'pvwatts'. The ModelChain instance will be passed - as the first argument to a user-defined function. + 'desoto', '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 If None, the model will be inferred from the contents of @@ -379,10 +379,19 @@ def dc_model(self, model): str(missing_params)) if model == 'sapm': self._dc_model = self.sapm - elif model == 'singlediode': - self._dc_model = self.singlediode + elif model == 'desoto': + self._dc_model = self.desoto + elif model == 'pvsyst': + self._dc_model = self.pvsyst elif model == 'pvwatts': self._dc_model = self.pvwatts_dc + elif model == 'singlediode': + warnings.warn('DC model keyword singlediode used for ' + 'ModelChain object. singlediode is ' + 'ambiguous, use desoto instead. singlediode ' + 'keyword will be removed in v0.7.0 and ' + 'later', DeprecationWarning) + self._dc_model = self.desoto else: raise ValueError(model + ' is not a valid DC power model') else: @@ -393,7 +402,10 @@ def infer_dc_model(self): 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: - return self.singlediode, 'singlediode' + 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: + return self.pvsyst, 'pvsyst' elif set(['pdc0', 'gamma_pdc']) <= params: return self.pvwatts_dc, 'pvwatts' else: @@ -408,6 +420,41 @@ def sapm(self): return self + def desoto(self): + (photocurrent, saturation_current, resistance_series, + resistance_shunt, nNsVth) = ( + self.system.calcparams_desoto(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) = ( + self.system.calcparams_pvsyst(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 + + # singlediode should be deprecated def singlediode(self): (photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth) = ( diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 2d08052056..444eecfc4b 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -34,6 +34,10 @@ 'singlediode' : set(['alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s']), + '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']), 'pvwatts' : set(['pdc0', 'gamma_pdc']) } diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 1083cf97d3..51785f72d5 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -18,7 +18,7 @@ from pandas.util.testing import assert_series_equal, assert_frame_equal import pytest -from test_pvsystem import sam_data +from test_pvsystem import sam_data, pvsyst_module_params from conftest import requires_scipy @@ -53,6 +53,20 @@ def cec_dc_snl_ac_system(sam_data): return system +@pytest.fixture +def pvsyst_dc_snl_ac_system(): + module = 'PVsyst test module' + module_parameters = pvsyst_module_params() + module_parameters['b'] = 0.05 + inverters = sam_data['cecinverter'] + inverter = inverters['ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'].copy() + system = PVSystem(surface_tilt=32.2, surface_azimuth=180, + module=module, + module_parameters=module_parameters, + inverter_parameters=inverter) + return system + + @pytest.fixture def cec_dc_adr_ac_system(sam_data): modules = sam_data['cecmod'] @@ -203,11 +217,18 @@ def poadc(mc): @pytest.mark.parametrize('dc_model', [ - 'sapm', pytest.param('singlediode', marks=requires_scipy), 'pvwatts_dc']) + 'sapm', + pytest.param('desoto', marks=requires_scipy), + pytest.param('pvsyst', marks=requires_scipy), + pytest.param('singlediode', marks=requires_scipy), + 'pvwatts_dc']) def test_infer_dc_model(system, cec_dc_snl_ac_system, pvwatts_dc_pvwatts_ac_system, location, dc_model, weather, mocker): - dc_systems = {'sapm': system, 'singlediode': cec_dc_snl_ac_system, + dc_systems = {'sapm': 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} system = dc_systems[dc_model] m = mocker.spy(system, dc_model) From e7fb500e291dcc50a378daa0bcebf1baae0fc462 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 11:28:44 -0600 Subject: [PATCH 02/12] Add desoto to DC_MODEL_PARAMS --- pvlib/pvsystem.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 444eecfc4b..1ecdac4f1e 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -31,13 +31,16 @@ 'C7', 'Isco', 'Impo', 'Aisc', 'Aimp', 'Bvoco', 'Mbvoc', 'Bvmpo', 'Mbvmp', 'N', 'Cells_in_Series', 'IXO', 'IXXO', 'FD']), - 'singlediode' : + 'desoto' : set(['alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s']), '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(['alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', + 'R_sh_ref', 'R_s']), 'pvwatts' : set(['pdc0', 'gamma_pdc']) } From 4c621c6da84b7c5d9b4e14135ec54a516e6bc997 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 12:57:03 -0600 Subject: [PATCH 03/12] Change to pvlibDeprecationWarning, add v0.7 test for singlediode keyword --- pvlib/modelchain.py | 3 ++- pvlib/test/test_modelchain.py | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 13f7ce5326..bbde882ba6 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -14,6 +14,7 @@ from pvlib.tracking import SingleAxisTracker import pvlib.irradiance # avoid name conflict with full import from pvlib.pvsystem import DC_MODEL_PARAMS +from pvlib._deprecation import pvlibDeprecationWarning def basic_chain(times, latitude, longitude, @@ -390,7 +391,7 @@ def dc_model(self, model): 'ModelChain object. singlediode is ' 'ambiguous, use desoto instead. singlediode ' 'keyword will be removed in v0.7.0 and ' - 'later', DeprecationWarning) + 'later', pvlibDeprecationWarning) self._dc_model = self.desoto else: raise ValueError(model + ' is not a valid DC power model') diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 51785f72d5..13ab0f573a 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -14,12 +14,13 @@ from pvlib.pvsystem import PVSystem from pvlib.tracking import SingleAxisTracker from pvlib.location import Location +from pvlib._deprecation import pvlibDeprecationWarning from pandas.util.testing import assert_series_equal, assert_frame_equal import pytest from test_pvsystem import sam_data, pvsyst_module_params -from conftest import requires_scipy +from conftest import fail_on_pvlib_version, requires_scipy @pytest.fixture @@ -431,6 +432,14 @@ def test_bad_get_orientation(): modelchain.get_orientation('bad value') +@fail_on_pvlib_version('0.7') +def test_deprecated_07(): + with pytest.warns(pvlibDeprecationWarning): + mc = ModelChain(cec_dc_snl_ac_system, location, + dc_model='singlediode', # this should fail after 0.7 + aoi_model='no_loss', spectral_model='no_loss') + + @requires_scipy def test_basic_chain_required(sam_data): times = pd.DatetimeIndex(start='20160101 1200-0700', From 9777ba6ca99ea83bcd4c46e6710f67d4add0ed93 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 13:47:16 -0600 Subject: [PATCH 04/12] Fix model function reference in test_infer_dc_model --- pvlib/test/test_modelchain.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 13ab0f573a..69fd10c647 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -231,8 +231,13 @@ def test_infer_dc_model(system, 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': pvsystem.sapm, + 'desoto': pvsystem.calcparams_desoto, + 'pvsyst': pvsystem.calcparams_pvsyst, + 'singlediode': pvsystem.calcparams_desoto, + 'pvwatts_dc': pvsystem.pvwatts_dc} system = dc_systems[dc_model] - m = mocker.spy(system, dc_model) + m = mocker.spy(system, dc_model_function[dc_model]) mc = ModelChain(system, location, aoi_model='no_loss', spectral_model='no_loss') mc.run_model(weather.index, weather=weather) From f2d8fe199cf852d6e1c767e2be119c1f141d967d Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 13:59:55 -0600 Subject: [PATCH 05/12] Change function object to strings --- pvlib/test/test_modelchain.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 69fd10c647..ab405ab0ed 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -231,11 +231,11 @@ def test_infer_dc_model(system, 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': pvsystem.sapm, - 'desoto': pvsystem.calcparams_desoto, - 'pvsyst': pvsystem.calcparams_pvsyst, - 'singlediode': pvsystem.calcparams_desoto, - 'pvwatts_dc': pvsystem.pvwatts_dc} + dc_model_function = {'sapm': 'sapm', + 'desoto': 'calcparams_desoto', + 'pvsyst': 'calcparams_pvsyst', + 'singlediode': 'calcparams_desoto', + 'pvwatts_dc': 'pvwatts_dc'} system = dc_systems[dc_model] m = mocker.spy(system, dc_model_function[dc_model]) mc = ModelChain(system, location, From 3a3afc61abfa0aeb76f91b87c38b2c6aa64fbcc3 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 14:29:51 -0600 Subject: [PATCH 06/12] Add pvsyst_dc_snl_ac_system to test_infer_dc_models argument list --- pvlib/test/test_modelchain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index ab405ab0ed..a3fc27fa6e 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -223,7 +223,7 @@ def poadc(mc): pytest.param('pvsyst', marks=requires_scipy), pytest.param('singlediode', marks=requires_scipy), 'pvwatts_dc']) -def test_infer_dc_model(system, cec_dc_snl_ac_system, +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, From df3a55feffa5900132284d4eeb57bd0142a1e31d Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Tue, 4 Sep 2018 14:46:20 -0600 Subject: [PATCH 07/12] Add sam_data argument to pvsyst_dc_snl_ac_system --- pvlib/test/test_modelchain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index a3fc27fa6e..dac2dd5fd6 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -55,7 +55,7 @@ def cec_dc_snl_ac_system(sam_data): @pytest.fixture -def pvsyst_dc_snl_ac_system(): +def pvsyst_dc_snl_ac_system(sam_data): module = 'PVsyst test module' module_parameters = pvsyst_module_params() module_parameters['b'] = 0.05 From 219e8f4c79245b4fb543febf48ea5da068c5e31e Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Wed, 5 Sep 2018 09:00:53 -0600 Subject: [PATCH 08/12] Update whatsnew, api.rst --- docs/sphinx/source/api.rst | 10 ++++++---- docs/sphinx/source/whatsnew/v0.6.0.rst | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 5f6fdd2800..c66fc324a8 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -204,10 +204,10 @@ AOI modifiers pvsystem.ashraeiam pvsystem.sapm_aoi_loss -Single diode model ------------------- +Single diode models +------------------- -Functions relevant for the single diode model. +Functions relevant for single diode models. .. autosummary:: :toctree: generated/ @@ -419,7 +419,9 @@ ModelChain model definitions. :toctree: generated/ modelchain.ModelChain.sapm - modelchain.ModelChain.singlediode + modelchain.ModelChain.desoto + modelchain.ModelChain.pvsyst + modelchain.ModelChain.singlediode (deprecated) modelchain.ModelChain.pvwatts_dc modelchain.ModelChain.snlinverter modelchain.ModelChain.adrinverter diff --git a/docs/sphinx/source/whatsnew/v0.6.0.rst b/docs/sphinx/source/whatsnew/v0.6.0.rst index 9a6b514c19..ed7c0e57c6 100644 --- a/docs/sphinx/source/whatsnew/v0.6.0.rst +++ b/docs/sphinx/source/whatsnew/v0.6.0.rst @@ -53,6 +53,8 @@ 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`) Enhancements @@ -104,6 +106,7 @@ 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`) Bug fixes From 7bf8a30af0b8e2c526ab894a11d7127bb9f151c4 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Wed, 5 Sep 2018 09:53:54 -0600 Subject: [PATCH 09/12] Add deprecated to ModelChain.singlediode docstring --- docs/sphinx/source/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index c66fc324a8..280b1b6453 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -421,7 +421,7 @@ ModelChain model definitions. modelchain.ModelChain.sapm modelchain.ModelChain.desoto modelchain.ModelChain.pvsyst - modelchain.ModelChain.singlediode (deprecated) + modelchain.ModelChain.singlediode modelchain.ModelChain.pvwatts_dc modelchain.ModelChain.snlinverter modelchain.ModelChain.adrinverter From b5ed45fdafded5a76f187e71efc673f0969f38d1 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Wed, 5 Sep 2018 09:54:46 -0600 Subject: [PATCH 10/12] Revert "Add deprecated to ModelChain.singlediode docstring" This reverts commit 7bf8a30af0b8e2c526ab894a11d7127bb9f151c4. --- docs/sphinx/source/api.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 280b1b6453..c66fc324a8 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -421,7 +421,7 @@ ModelChain model definitions. modelchain.ModelChain.sapm modelchain.ModelChain.desoto modelchain.ModelChain.pvsyst - modelchain.ModelChain.singlediode + modelchain.ModelChain.singlediode (deprecated) modelchain.ModelChain.pvwatts_dc modelchain.ModelChain.snlinverter modelchain.ModelChain.adrinverter From 85e9aac3ec05a7fea489109fac0b8b901e3b2846 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Wed, 5 Sep 2018 09:55:51 -0600 Subject: [PATCH 11/12] Add deprecated to ModelChain.singlediode docstring --- pvlib/modelchain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index bbde882ba6..5efacc8828 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -455,8 +455,8 @@ def pvsyst(self): return self - # singlediode should be deprecated def singlediode(self): + """Deprecated""" (photocurrent, saturation_current, resistance_series, resistance_shunt, nNsVth) = ( self.system.calcparams_desoto(self.effective_irradiance, From 230349c738fc6410a281540bce15eb255252f5b1 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Wed, 5 Sep 2018 10:02:52 -0600 Subject: [PATCH 12/12] Fix indents, remove ModelChain.singlediode from api.rst --- docs/sphinx/source/api.rst | 1 - pvlib/modelchain.py | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index c66fc324a8..2c9504a091 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -421,7 +421,6 @@ ModelChain model definitions. modelchain.ModelChain.sapm modelchain.ModelChain.desoto modelchain.ModelChain.pvsyst - modelchain.ModelChain.singlediode (deprecated) modelchain.ModelChain.pvwatts_dc modelchain.ModelChain.snlinverter modelchain.ModelChain.adrinverter diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 5efacc8828..b76660ad85 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -427,8 +427,9 @@ def desoto(self): self.system.calcparams_desoto(self.effective_irradiance, self.temps['temp_cell'])) - self.diode_params = (photocurrent, saturation_current, resistance_series, - resistance_shunt, nNsVth) + self.diode_params = (photocurrent, saturation_current, + resistance_series, + resistance_shunt, nNsVth) self.dc = self.system.singlediode( photocurrent, saturation_current, resistance_series, @@ -444,8 +445,9 @@ def pvsyst(self): self.system.calcparams_pvsyst(self.effective_irradiance, self.temps['temp_cell'])) - self.diode_params = (photocurrent, saturation_current, resistance_series, - resistance_shunt, nNsVth) + self.diode_params = (photocurrent, saturation_current, + resistance_series, + resistance_shunt, nNsVth) self.dc = self.system.singlediode( photocurrent, saturation_current, resistance_series,