From 31e3ab6bf4955d322681a623a1bc061dca60e29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Sat, 24 Aug 2019 14:17:39 +0200 Subject: [PATCH 01/10] Add CEC inverter parameters fixture --- pvlib/test/conftest.py | 28 +++++++++++++++ pvlib/test/test_modelchain.py | 65 ++++++++++++----------------------- pvlib/test/test_pvsystem.py | 52 ++++++++++++++++++---------- 3 files changed, 83 insertions(+), 62 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index d26ff00f4b..904e86e518 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -149,3 +149,31 @@ def has_numba(): requires_pvfactors = pytest.mark.skipif(not has_pvfactors, reason='requires pvfactors') + + +@pytest.fixture(scope='function') +def cec_inverter_parameters(): + """ + Define some CEC inverter parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'Name': 'ABB: MICRO-0.25-I-OUTD-US-208 208V [CEC 2014]', + 'Vac': 208.0, + 'Paco': 250.0, + 'Pdco': 259.5220505, + 'Vdco': 40.24260317, + 'Pso': 1.771614224, + 'C0': -2.48e-5, + 'C1': -9.01e-5, + 'C2': 6.69e-4, + 'C3': -0.0189, + 'Pnt': 0.02, + 'Vdcmax': 65.0, + 'Idcmax': 10.0, + 'Mppt_low': 20.0, + 'Mppt_high': 50.0, + } + return parameters diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 7fac62542c..27f1fd6a1f 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -18,60 +18,52 @@ @pytest.fixture -def system(sam_data): +def system(sam_data, cec_inverter_parameters): modules = sam_data['sandiamod'] module = 'Canadian_Solar_CS5P_220M___2009_' module_parameters = modules[module].copy() - 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) + inverter_parameters=cec_inverter_parameters) return system @pytest.fixture -def cec_dc_snl_ac_system(sam_data): +def cec_dc_snl_ac_system(sam_data, cec_inverter_parameters): modules = sam_data['cecmod'] module = 'Canadian_Solar_CS5P_220M' module_parameters = modules[module].copy() module_parameters['b'] = 0.05 module_parameters['EgRef'] = 1.121 module_parameters['dEgdT'] = -0.0002677 - 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) + inverter_parameters=cec_inverter_parameters) return system @pytest.fixture -def cec_dc_native_snl_ac_system(sam_data): +def cec_dc_native_snl_ac_system(sam_data, cec_inverter_parameters): module = 'Canadian_Solar_CS5P_220M' module_parameters = sam_data['cecmod'][module].copy() - 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) + inverter_parameters=cec_inverter_parameters) return system @pytest.fixture -def pvsyst_dc_snl_ac_system(sam_data, pvsyst_module_params): +def pvsyst_dc_snl_ac_system(pvsyst_module_params, cec_inverter_parameters): 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) + inverter_parameters=cec_inverter_parameters) return system @@ -93,13 +85,11 @@ def cec_dc_adr_ac_system(sam_data): @pytest.fixture -def pvwatts_dc_snl_ac_system(sam_data): +def pvwatts_dc_snl_ac_system(cec_inverter_parameters): module_parameters = {'pdc0': 220, 'gamma_pdc': -0.003} - 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_parameters=module_parameters, - inverter_parameters=inverter) + inverter_parameters=cec_inverter_parameters) return system @@ -504,7 +494,7 @@ def test_deprecated_clearsky_07(): @requires_scipy -def test_basic_chain_required(sam_data): +def test_basic_chain_required(sam_data, cec_inverter_parameters): times = pd.date_range(start='20160101 1200-0700', end='20160101 1800-0700', freq='6H') latitude = 32 @@ -512,17 +502,15 @@ def test_basic_chain_required(sam_data): altitude = 700 modules = sam_data['sandiamod'] module_parameters = modules['Canadian_Solar_CS5P_220M___2009_'] - inverters = sam_data['cecinverter'] - inverter_parameters = inverters[ - 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'] with pytest.raises(ValueError): - dc, ac = modelchain.basic_chain(times, latitude, longitude, - module_parameters, inverter_parameters, - altitude=altitude) + dc, ac = modelchain.basic_chain( + times, latitude, longitude, module_parameters, + cec_inverter_parameters, altitude=altitude + ) @requires_scipy -def test_basic_chain_alt_az(sam_data): +def test_basic_chain_alt_az(sam_data, cec_inverter_parameters): times = pd.date_range(start='20160101 1200-0700', end='20160101 1800-0700', freq='6H') latitude = 32.2 @@ -531,12 +519,9 @@ def test_basic_chain_alt_az(sam_data): surface_azimuth = 0 modules = sam_data['sandiamod'] module_parameters = modules['Canadian_Solar_CS5P_220M___2009_'] - inverters = sam_data['cecinverter'] - inverter_parameters = inverters[ - 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'] dc, ac = modelchain.basic_chain(times, latitude, longitude, - module_parameters, inverter_parameters, + module_parameters, cec_inverter_parameters, surface_tilt=surface_tilt, surface_azimuth=surface_azimuth) @@ -546,7 +531,7 @@ def test_basic_chain_alt_az(sam_data): @requires_scipy -def test_basic_chain_strategy(sam_data): +def test_basic_chain_strategy(sam_data, cec_inverter_parameters): times = pd.date_range(start='20160101 1200-0700', end='20160101 1800-0700', freq='6H') latitude = 32.2 @@ -554,12 +539,9 @@ def test_basic_chain_strategy(sam_data): altitude = 700 modules = sam_data['sandiamod'] module_parameters = modules['Canadian_Solar_CS5P_220M___2009_'] - inverters = sam_data['cecinverter'] - inverter_parameters = inverters[ - 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'] dc, ac = modelchain.basic_chain( - times, latitude, longitude, module_parameters, inverter_parameters, + times, latitude, longitude, module_parameters, cec_inverter_parameters, orientation_strategy='south_at_latitude_tilt', altitude=altitude) expected = pd.Series(np.array([ 183.522449305, -2.00000000e-02]), @@ -568,7 +550,7 @@ def test_basic_chain_strategy(sam_data): @requires_scipy -def test_basic_chain_altitude_pressure(sam_data): +def test_basic_chain_altitude_pressure(sam_data, cec_inverter_parameters): times = pd.date_range(start='20160101 1200-0700', end='20160101 1800-0700', freq='6H') latitude = 32.2 @@ -578,12 +560,9 @@ def test_basic_chain_altitude_pressure(sam_data): surface_azimuth = 0 modules = sam_data['sandiamod'] module_parameters = modules['Canadian_Solar_CS5P_220M___2009_'] - inverters = sam_data['cecinverter'] - inverter_parameters = inverters[ - 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_'] dc, ac = modelchain.basic_chain(times, latitude, longitude, - module_parameters, inverter_parameters, + module_parameters, cec_inverter_parameters, surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, pressure=93194) @@ -593,7 +572,7 @@ def test_basic_chain_altitude_pressure(sam_data): assert_series_equal(ac, expected, check_less_precise=1) dc, ac = modelchain.basic_chain(times, latitude, longitude, - module_parameters, inverter_parameters, + module_parameters, cec_inverter_parameters, surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, altitude=altitude) diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index e710c6f063..2520343fcc 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -236,7 +236,6 @@ def sam_data(): data = {} data['cecmod'] = pvsystem.retrieve_sam('cecmod') data['sandiamod'] = pvsystem.retrieve_sam('sandiamod') - data['cecinverter'] = pvsystem.retrieve_sam('cecinverter') data['adrinverter'] = pvsystem.retrieve_sam('adrinverter') return data @@ -1275,22 +1274,20 @@ def test_adrinverter_invalid_and_night(sam_data): assert_allclose(pacs, np.array([np.nan, -0.25, np.nan, np.nan])) -def test_snlinverter(sam_data): - inverters = sam_data['cecinverter'] - testinv = 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_' +def test_snlinverter(cec_inverter_parameters): vdcs = pd.Series(np.linspace(0,50,3)) idcs = pd.Series(np.linspace(0,11,3)) pdcs = idcs * vdcs - pacs = pvsystem.snlinverter(vdcs, pdcs, inverters[testinv]) + pacs = pvsystem.snlinverter(vdcs, pdcs, cec_inverter_parameters) assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) -def test_PVSystem_snlinverter(sam_data): - inverters = sam_data['cecinverter'] - testinv = 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_' - system = pvsystem.PVSystem(inverter=testinv, - inverter_parameters=inverters[testinv]) +def test_PVSystem_snlinverter(cec_inverter_parameters): + system = pvsystem.PVSystem( + inverter=cec_inverter_parameters['Name'], + inverter_parameters=cec_inverter_parameters, + ) vdcs = pd.Series(np.linspace(0,50,3)) idcs = pd.Series(np.linspace(0,11,3)) pdcs = idcs * vdcs @@ -1299,26 +1296,43 @@ def test_PVSystem_snlinverter(sam_data): assert_series_equal(pacs, pd.Series([-0.020000, 132.004308, 250.000000])) -def test_snlinverter_float(sam_data): - inverters = sam_data['cecinverter'] - testinv = 'ABB__MICRO_0_25_I_OUTD_US_208_208V__CEC_2014_' +def test_snlinverter_float(cec_inverter_parameters): vdcs = 25. idcs = 5.5 pdcs = idcs * vdcs - pacs = pvsystem.snlinverter(vdcs, pdcs, inverters[testinv]) + pacs = pvsystem.snlinverter(vdcs, pdcs, cec_inverter_parameters) assert_allclose(pacs, 132.004278, 5) -def test_snlinverter_Pnt_micro(sam_data): - inverters = sam_data['cecinverter'] - testinv = 'Enphase_Energy__M250_60_2LL_S2x___ZC____NA__208V_208V__CEC_2013_' +def test_snlinverter_Pnt_micro(): + """ + Test for issue #140, where some microinverters were giving a positive AC + power output when the DC power was 0. + """ + inverter_parameters = { + 'Name': 'Enphase Energy: M250-60-2LL-S2x (-ZC) (-NA) 208V [CEC 2013]', + 'Vac': 208.0, + 'Paco': 240.0, + 'Pdco': 250.5311318, + 'Vdco': 32.06160667, + 'Pso': 1.12048857, + 'C0': -5.76E-05, + 'C1': -6.24E-04, + 'C2': 8.09E-02, + 'C3': -0.111781106, + 'Pnt': 0.043, + 'Vdcmax': 48.0, + 'Idcmax': 9.8, + 'Mppt_low': 27.0, + 'Mppt_high': 39.0, + } vdcs = pd.Series(np.linspace(0,50,3)) idcs = pd.Series(np.linspace(0,11,3)) pdcs = idcs * vdcs - pacs = pvsystem.snlinverter(vdcs, pdcs, inverters[testinv]) - assert_series_equal(pacs, pd.Series([-0.043000, 132.545914746, 240.000000])) + pacs = pvsystem.snlinverter(vdcs, pdcs, inverter_parameters) + assert_series_equal(pacs, pd.Series([-0.043, 132.545914746, 240.0])) def test_PVSystem_creation(): From 695e494bf17e073ee4bfcf76f61d2670cf60f3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 18:35:11 +0200 Subject: [PATCH 02/10] New module fixture for `test_pvsystem` Do not rely on the SAM module database, as parameters there may change with future updates. --- pvlib/test/conftest.py | 35 +++++++++++++++++++++++++++++++++++ pvlib/test/test_pvsystem.py | 12 +----------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index 904e86e518..17de33654e 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -177,3 +177,38 @@ def cec_inverter_parameters(): 'Mppt_high': 50.0, } return parameters + + +@pytest.fixture(scope='function') +def cec_module_params(): + """ + Define some CEC module parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'Name': 'Example Module', + 'BIPV': 'Y', + 'Date': '4/28/2008', + 'T_NOCT': 65, + 'A_c': 0.67, + 'N_s': 18, + 'I_sc_ref': 7.5, + 'V_oc_ref': 10.4, + 'I_mp_ref': 6.6, + 'V_mp_ref': 8.4, + 'alpha_sc': 0.003, + 'beta_oc': -0.04, + 'a_ref': 0.473, + 'I_L_ref': 7.545, + 'I_o_ref': 1.94e-09, + 'R_s': 0.094, + 'R_sh_ref': 15.72, + 'Adjust': 10.6, + 'gamma_r': -0.5, + 'Version': 'MM105', + 'PTC': 48.9, + 'Technology': 'Multi-c-Si', + } + return parameters diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index 2520343fcc..ddd2b2e1e0 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -248,14 +248,6 @@ def sapm_module_params(sam_data): return module_parameters -@pytest.fixture(scope="session") -def cec_module_params(sam_data): - modules = sam_data['cecmod'] - module = 'Example_Module' - module_parameters = modules[module] - return module_parameters - - @pytest.fixture() def pvsyst_module_params(): module_parameters = {} @@ -1008,9 +1000,7 @@ def test_singlediode_array(): @requires_scipy -def test_singlediode_floats(sam_data): - module = 'Example_Module' - module_parameters = sam_data['cecmod'][module] +def test_singlediode_floats(): out = pvsystem.singlediode(7, 6e-7, .1, 20, .5, method='lambertw') expected = {'i_xx': 4.2498, 'i_mp': 6.1275, From 1bae7e1af0814128d188b00b85d7b165a90ac5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 19:03:49 +0200 Subject: [PATCH 03/10] New module fixture for `test_modelchain` Do not rely on the SAM module database, as parameters there may change with future updates. --- pvlib/test/conftest.py | 35 +++++++++++++++++++++++++++++++++++ pvlib/test/test_modelchain.py | 23 +++++++++-------------- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index 17de33654e..95866aacd5 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -212,3 +212,38 @@ def cec_module_params(): 'Technology': 'Multi-c-Si', } return parameters + + +@pytest.fixture(scope='function') +def cec_module_cs5p_220m(): + """ + Define Canadian Solar CS5P-220M module parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'Name': 'Canadian Solar CS5P-220M', + 'BIPV': 'N', + 'Date': '10/5/2009', + 'T_NOCT': 42.4, + 'A_c': 1.7, + 'N_s': 96, + 'I_sc_ref': 5.1, + 'V_oc_ref': 59.4, + 'I_mp_ref': 4.69, + 'V_mp_ref': 46.9, + 'alpha_sc': 0.004539, + 'beta_oc': -0.22216, + 'a_ref': 2.6373, + 'I_L_ref': 5.114, + 'I_o_ref': 8.196e-10, + 'R_s': 1.065, + 'R_sh_ref': 381.68, + 'Adjust': 8.7, + 'gamma_r': -0.476, + 'Version': 'MM106', + 'PTC': 200.1, + 'Technology': 'Mono-c-Si', + } + return parameters diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 27f1fd6a1f..004af7d70b 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -30,26 +30,23 @@ def system(sam_data, cec_inverter_parameters): @pytest.fixture -def cec_dc_snl_ac_system(sam_data, cec_inverter_parameters): - modules = sam_data['cecmod'] - module = 'Canadian_Solar_CS5P_220M' - module_parameters = modules[module].copy() +def cec_dc_snl_ac_system(cec_module_cs5p_220m, cec_inverter_parameters): + module_parameters = cec_module_cs5p_220m.copy() module_parameters['b'] = 0.05 module_parameters['EgRef'] = 1.121 module_parameters['dEgdT'] = -0.0002677 system = PVSystem(surface_tilt=32.2, surface_azimuth=180, - module=module, + module=module_parameters['Name'], module_parameters=module_parameters, inverter_parameters=cec_inverter_parameters) return system @pytest.fixture -def cec_dc_native_snl_ac_system(sam_data, cec_inverter_parameters): - module = 'Canadian_Solar_CS5P_220M' - module_parameters = sam_data['cecmod'][module].copy() +def cec_dc_native_snl_ac_system(cec_module_cs5p_220m, cec_inverter_parameters): + module_parameters = cec_module_cs5p_220m.copy() system = PVSystem(surface_tilt=32.2, surface_azimuth=180, - module=module, + module=module_parameters['Name'], module_parameters=module_parameters, inverter_parameters=cec_inverter_parameters) return system @@ -68,17 +65,15 @@ def pvsyst_dc_snl_ac_system(pvsyst_module_params, cec_inverter_parameters): @pytest.fixture -def cec_dc_adr_ac_system(sam_data): - modules = sam_data['cecmod'] - module = 'Canadian_Solar_CS5P_220M' - module_parameters = modules[module].copy() +def cec_dc_adr_ac_system(sam_data, cec_module_cs5p_220m): + module_parameters = cec_module_cs5p_220m.copy() module_parameters['b'] = 0.05 module_parameters['EgRef'] = 1.121 module_parameters['dEgdT'] = -0.0002677 inverters = sam_data['adrinverter'] inverter = inverters['Zigor__Sunzet_3_TL_US_240V__CEC_2011_'].copy() system = PVSystem(surface_tilt=32.2, surface_azimuth=180, - module=module, + module=module_parameters['Name'], module_parameters=module_parameters, inverter_parameters=inverter) return system From d0135efab87ce4ba952ea84b434a46534ab5ec67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 19:34:11 +0200 Subject: [PATCH 04/10] Parametrize methods in single diode tests --- pvlib/test/test_singlediode.py | 74 ++++------------------------------ 1 file changed, 8 insertions(+), 66 deletions(-) diff --git a/pvlib/test/test_singlediode.py b/pvlib/test/test_singlediode.py index c2c556cb23..567926c7f8 100644 --- a/pvlib/test/test_singlediode.py +++ b/pvlib/test/test_singlediode.py @@ -15,8 +15,9 @@ @requires_scipy -def test_newton_spr_e20_327(): - """test pvsystem.singlediode with Newton method on SPR-E20-327""" +@pytest.mark.parametrize('method', ['brentq', 'newton']) +def test_method_spr_e20_327(method): + """test pvsystem.singlediode with different methods on SPR-E20-327""" spr_e20_327 = CECMOD.SunPower_SPR_E20_327 x = pvsystem.calcparams_desoto( effective_irradiance=POA, temp_cell=TCELL, @@ -26,7 +27,7 @@ def test_newton_spr_e20_327(): EgRef=1.121, dEgdT=-0.0002677) il, io, rs, rsh, nnsvt = x pvs = pvsystem.singlediode(*x, method='lambertw') - out = pvsystem.singlediode(*x, method='newton') + out = pvsystem.singlediode(*x, method=method) isc, voc, imp, vmp, pmp, ix, ixx = out.values() assert np.isclose(pvs['i_sc'], isc) assert np.isclose(pvs['v_oc'], voc) @@ -40,12 +41,12 @@ def test_newton_spr_e20_327(): pvs_ixx = pvsystem.i_from_v(rsh, rs, nnsvt, (voc + vmp)/2, io, il, method='lambertw') assert np.isclose(pvs_ixx, ixx) - return isc, voc, imp, vmp, pmp, pvs @requires_scipy -def test_newton_fs_495(): - """test pvsystem.singlediode with Newton method on FS495""" +@pytest.mark.parametrize('method', ['brentq', 'newton']) +def test_newton_fs_495(method): + """test pvsystem.singlediode with different methods on FS495""" fs_495 = CECMOD.First_Solar_FS_495 x = pvsystem.calcparams_desoto( effective_irradiance=POA, temp_cell=TCELL, @@ -55,7 +56,7 @@ def test_newton_fs_495(): il, io, rs, rsh, nnsvt = x x += (101, ) pvs = pvsystem.singlediode(*x, method='lambertw') - out = pvsystem.singlediode(*x, method='newton') + out = pvsystem.singlediode(*x, method=method) isc, voc, imp, vmp, pmp, ix, ixx, i, v = out.values() assert np.isclose(pvs['i_sc'], isc) assert np.isclose(pvs['v_oc'], voc) @@ -69,65 +70,6 @@ def test_newton_fs_495(): pvs_ixx = pvsystem.i_from_v(rsh, rs, nnsvt, (voc + vmp)/2, io, il, method='lambertw') assert np.isclose(pvs_ixx, ixx) - return isc, voc, imp, vmp, pmp, i, v, pvs - - -@requires_scipy -def test_brentq_spr_e20_327(): - """test pvsystem.singlediode with Brent method on SPR-E20-327""" - spr_e20_327 = CECMOD.SunPower_SPR_E20_327 - x = pvsystem.calcparams_desoto( - effective_irradiance=POA, temp_cell=TCELL, - alpha_sc=spr_e20_327.alpha_sc, a_ref=spr_e20_327.a_ref, - I_L_ref=spr_e20_327.I_L_ref, I_o_ref=spr_e20_327.I_o_ref, - R_sh_ref=spr_e20_327.R_sh_ref, R_s=spr_e20_327.R_s, - EgRef=1.121, dEgdT=-0.0002677) - il, io, rs, rsh, nnsvt = x - pvs = pvsystem.singlediode(*x, method='lambertw') - out = pvsystem.singlediode(*x, method='brentq') - isc, voc, imp, vmp, pmp, ix, ixx = out.values() - assert np.isclose(pvs['i_sc'], isc) - assert np.isclose(pvs['v_oc'], voc) - # the singlediode method doesn't actually get the MPP correct - pvs_imp = pvsystem.i_from_v(rsh, rs, nnsvt, vmp, io, il, method='lambertw') - pvs_vmp = pvsystem.v_from_i(rsh, rs, nnsvt, imp, io, il, method='lambertw') - assert np.isclose(pvs_imp, imp) - assert np.isclose(pvs_vmp, vmp) - assert np.isclose(pvs['p_mp'], pmp) - assert np.isclose(pvs['i_x'], ix) - pvs_ixx = pvsystem.i_from_v(rsh, rs, nnsvt, (voc + vmp)/2, io, il, - method='lambertw') - assert np.isclose(pvs_ixx, ixx) - return isc, voc, imp, vmp, pmp, pvs - - -@requires_scipy -def test_brentq_fs_495(): - """test pvsystem.singlediode with Brent method on FS495""" - fs_495 = CECMOD.First_Solar_FS_495 - x = pvsystem.calcparams_desoto( - effective_irradiance=POA, temp_cell=TCELL, - alpha_sc=fs_495.alpha_sc, a_ref=fs_495.a_ref, I_L_ref=fs_495.I_L_ref, - I_o_ref=fs_495.I_o_ref, R_sh_ref=fs_495.R_sh_ref, R_s=fs_495.R_s, - EgRef=1.475, dEgdT=-0.0003) - il, io, rs, rsh, nnsvt = x - x += (101, ) - pvs = pvsystem.singlediode(*x, method='lambertw') - out = pvsystem.singlediode(*x, method='brentq') - isc, voc, imp, vmp, pmp, ix, ixx, i, v = out.values() - assert np.isclose(pvs['i_sc'], isc) - assert np.isclose(pvs['v_oc'], voc) - # the singlediode method doesn't actually get the MPP correct - pvs_imp = pvsystem.i_from_v(rsh, rs, nnsvt, vmp, io, il, method='lambertw') - pvs_vmp = pvsystem.v_from_i(rsh, rs, nnsvt, imp, io, il, method='lambertw') - assert np.isclose(pvs_imp, imp) - assert np.isclose(pvs_vmp, vmp) - assert np.isclose(pvs['p_mp'], pmp) - assert np.isclose(pvs['i_x'], ix) - pvs_ixx = pvsystem.i_from_v(rsh, rs, nnsvt, (voc + vmp)/2, io, il, - method='lambertw') - assert np.isclose(pvs_ixx, ixx) - return isc, voc, imp, vmp, pmp, i, v, pvs def get_pvsyst_fs_495(): From f8eaab695c93d4b89e6acca2515c80773208bcd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 19:42:36 +0200 Subject: [PATCH 05/10] New module fixtures for `test_singlediode` Do not rely on the SAM module database, as parameters there may change with future updates. --- pvlib/test/conftest.py | 70 ++++++++++++++++++++++++++++++++++ pvlib/test/test_singlediode.py | 20 +++++----- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index 95866aacd5..fd0e2d1c9b 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -247,3 +247,73 @@ def cec_module_cs5p_220m(): 'Technology': 'Mono-c-Si', } return parameters + + +@pytest.fixture(scope='function') +def cec_module_spr_e20_327(): + """ + Define SunPower SPR-E20-327 module parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'Name': 'SunPower SPR-E20-327', + 'BIPV': 'N', + 'Date': '1/14/2013', + 'T_NOCT': 46, + 'A_c': 1.631, + 'N_s': 96, + 'I_sc_ref': 6.46, + 'V_oc_ref': 65.1, + 'I_mp_ref': 5.98, + 'V_mp_ref': 54.7, + 'alpha_sc': 0.004522, + 'beta_oc': -0.23176, + 'a_ref': 2.6868, + 'I_L_ref': 6.468, + 'I_o_ref': 1.88e-10, + 'R_s': 0.37, + 'R_sh_ref': 298.13, + 'Adjust': -0.1862, + 'gamma_r': -0.386, + 'Version': 'NRELv1', + 'PTC': 301.4, + 'Technology': 'Mono-c-Si', + } + return parameters + + +@pytest.fixture(scope='function') +def cec_module_fs_495(): + """ + Define First Solar FS-495 module parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'Name': 'First Solar FS-495', + 'BIPV': 'N', + 'Date': '9/18/2014', + 'T_NOCT': 44.6, + 'A_c': 0.72, + 'N_s': 216, + 'I_sc_ref': 1.55, + 'V_oc_ref': 86.5, + 'I_mp_ref': 1.4, + 'V_mp_ref': 67.9, + 'alpha_sc': 0.000924, + 'beta_oc': -0.22741, + 'a_ref': 2.9482, + 'I_L_ref': 1.563, + 'I_o_ref': 2.64e-13, + 'R_s': 6.804, + 'R_sh_ref': 806.27, + 'Adjust': -10.65, + 'gamma_r': -0.264, + 'Version': 'NRELv1', + 'PTC': 89.7, + 'Technology': 'CdTe', + } + return parameters diff --git a/pvlib/test/test_singlediode.py b/pvlib/test/test_singlediode.py index 567926c7f8..2d5074c884 100644 --- a/pvlib/test/test_singlediode.py +++ b/pvlib/test/test_singlediode.py @@ -11,19 +11,18 @@ POA = 888 TCELL = 55 -CECMOD = pvsystem.retrieve_sam('cecmod') @requires_scipy @pytest.mark.parametrize('method', ['brentq', 'newton']) -def test_method_spr_e20_327(method): +def test_method_spr_e20_327(method, cec_module_spr_e20_327): """test pvsystem.singlediode with different methods on SPR-E20-327""" - spr_e20_327 = CECMOD.SunPower_SPR_E20_327 + spr_e20_327 = cec_module_spr_e20_327 x = pvsystem.calcparams_desoto( effective_irradiance=POA, temp_cell=TCELL, - alpha_sc=spr_e20_327.alpha_sc, a_ref=spr_e20_327.a_ref, - I_L_ref=spr_e20_327.I_L_ref, I_o_ref=spr_e20_327.I_o_ref, - R_sh_ref=spr_e20_327.R_sh_ref, R_s=spr_e20_327.R_s, + alpha_sc=spr_e20_327['alpha_sc'], a_ref=spr_e20_327['a_ref'], + I_L_ref=spr_e20_327['I_L_ref'], I_o_ref=spr_e20_327['I_o_ref'], + R_sh_ref=spr_e20_327['R_sh_ref'], R_s=spr_e20_327['R_s'], EgRef=1.121, dEgdT=-0.0002677) il, io, rs, rsh, nnsvt = x pvs = pvsystem.singlediode(*x, method='lambertw') @@ -45,13 +44,14 @@ def test_method_spr_e20_327(method): @requires_scipy @pytest.mark.parametrize('method', ['brentq', 'newton']) -def test_newton_fs_495(method): +def test_newton_fs_495(method, cec_module_fs_495): """test pvsystem.singlediode with different methods on FS495""" - fs_495 = CECMOD.First_Solar_FS_495 + fs_495 = cec_module_fs_495 x = pvsystem.calcparams_desoto( effective_irradiance=POA, temp_cell=TCELL, - alpha_sc=fs_495.alpha_sc, a_ref=fs_495.a_ref, I_L_ref=fs_495.I_L_ref, - I_o_ref=fs_495.I_o_ref, R_sh_ref=fs_495.R_sh_ref, R_s=fs_495.R_s, + alpha_sc=fs_495['alpha_sc'], a_ref=fs_495['a_ref'], + I_L_ref=fs_495['I_L_ref'], I_o_ref=fs_495['I_o_ref'], + R_sh_ref=fs_495['R_sh_ref'], R_s=fs_495['R_s'], EgRef=1.475, dEgdT=-0.0003) il, io, rs, rsh, nnsvt = x x += (101, ) From f99630fc859898b37452b18425bd9ff9373852a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 20:07:34 +0200 Subject: [PATCH 06/10] Refactor numerical precision test To avoid using module parameters from SAM module database, as parameters there may change with future updates. --- pvlib/test/test_numerical_precision.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pvlib/test/test_numerical_precision.py b/pvlib/test/test_numerical_precision.py index 50b86c6e3a..ab84b3431a 100644 --- a/pvlib/test/test_numerical_precision.py +++ b/pvlib/test/test_numerical_precision.py @@ -32,15 +32,19 @@ DATA_PATH = os.path.join(PVLIB_PATH, 'data', TEST_DATA) POA = 888 TCELL = 55 -CECMOD = pvsystem.retrieve_sam('cecmod') -# get module from cecmod and apply temp/irrad desoto corrections -SPR_E20_327 = CECMOD.SunPower_SPR_E20_327 +# module parameters from CEC module SunPower SPR-E20-327 +SPR_E20_327 = { + 'alpha_sc': 0.004522, + 'a_ref': 2.6868, + 'I_L_ref': 6.468, + 'I_o_ref': 1.88e-10, + 'R_s': 0.37, + 'R_sh_ref': 298.13, +} +# apply temp/irrad desoto corrections ARGS = pvsystem.calcparams_desoto( effective_irradiance=POA, temp_cell=TCELL, - alpha_sc=SPR_E20_327.alpha_sc, a_ref=SPR_E20_327.a_ref, - I_L_ref=SPR_E20_327.I_L_ref, I_o_ref=SPR_E20_327.I_o_ref, - R_sh_ref=SPR_E20_327.R_sh_ref, R_s=SPR_E20_327.R_s, - EgRef=1.121, dEgdT=-0.0002677 + EgRef=1.121, dEgdT=-0.0002677, **SPR_E20_327, ) IL, I0, RS, RSH, NNSVTH = ARGS IVCURVE_NPTS = 100 From 01ac084b1acf77031e11b4483269d6198d25a328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 20:09:28 +0200 Subject: [PATCH 07/10] Remove unused cecmod data from `sam_data` fixture --- pvlib/test/test_pvsystem.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index ddd2b2e1e0..6ec10e823c 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -234,7 +234,6 @@ def test_iam_interp(): @pytest.fixture(scope="session") def sam_data(): data = {} - data['cecmod'] = pvsystem.retrieve_sam('cecmod') data['sandiamod'] = pvsystem.retrieve_sam('sandiamod') data['adrinverter'] = pvsystem.retrieve_sam('adrinverter') return data From 08adb3921f31f6f08fe34a31a3e8ffd32fab8038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 20:26:08 +0200 Subject: [PATCH 08/10] Add tests for `retrive_sam` function In particular for the CEC module and inverter data. --- pvlib/test/test_pvsystem.py | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index 6ec10e823c..7ba7b9fca3 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -273,6 +273,69 @@ def test_retrieve_sam_raise_no_parameters(): assert 'A name or path must be provided!' == str(error.value) +def test_retrieve_sam_cecmod(): + """ + Test the expected data is retrieved from the CEC module database. In + particular, check for a known module in the database and check for the + expected keys for that module. + """ + data = pvsystem.retrieve_sam('cecmod') + keys = [ + 'BIPV', + 'Date', + 'T_NOCT', + 'A_c', + 'N_s', + 'I_sc_ref', + 'V_oc_ref', + 'I_mp_ref', + 'V_mp_ref', + 'alpha_sc', + 'beta_oc', + 'a_ref', + 'I_L_ref', + 'I_o_ref', + 'R_s', + 'R_sh_ref', + 'Adjust', + 'gamma_r', + 'Version', + 'PTC', + 'Technology', + ] + module = 'iTek_iT_300_HE' + assert module in data + assert set(data[module].keys()) == set(keys) + + +def test_retrieve_sam_cecinverter(): + """ + Test the expected data is retrieved from the CEC inverter database. In + particular, check for a known inverter in the database and check for the + expected keys for that inverter. + """ + data = pvsystem.retrieve_sam('cecinverter') + keys = [ + 'Vac', + 'Paco', + 'Pdco', + 'Vdco', + 'Pso', + 'C0', + 'C1', + 'C2', + 'C3', + 'Pnt', + 'Vdcmax', + 'Idcmax', + 'Mppt_low', + 'Mppt_high', + ] + inverter = 'Solectria__PVI_5300_5300_P_208V__CEC_2008_' + assert inverter in data + assert set(data[inverter].keys()) == set(keys) + + def test_sapm(sapm_module_params): times = pd.date_range(start='2015-01-01', periods=5, freq='12H') From 83ca5f2a11ccaaf58474463cc56c6251357bf04a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 23:04:48 +0200 Subject: [PATCH 09/10] Move `sam_data` fixture to `conftest.py` --- pvlib/test/conftest.py | 8 ++++++++ pvlib/test/test_modelchain.py | 2 +- pvlib/test/test_pvsystem.py | 9 --------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index fd0e2d1c9b..faf32c7bc4 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -151,6 +151,14 @@ def has_numba(): reason='requires pvfactors') +@pytest.fixture(scope="session") +def sam_data(): + data = {} + data['sandiamod'] = pvlib.pvsystem.retrieve_sam('sandiamod') + data['adrinverter'] = pvlib.pvsystem.retrieve_sam('adrinverter') + return data + + @pytest.fixture(scope='function') def cec_inverter_parameters(): """ diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 004af7d70b..977baef218 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -13,7 +13,7 @@ from pandas.util.testing import assert_series_equal import pytest -from test_pvsystem import sam_data, pvsyst_module_params +from test_pvsystem import pvsyst_module_params from conftest import fail_on_pvlib_version, requires_scipy, requires_tables diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index 7ba7b9fca3..64ba27f71c 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -230,15 +230,6 @@ def test_iam_interp(): pvsystem.iam_interp(0.0, [0, 90], [1, -1]) -# if this completes successfully we'll be able to do more tests below. -@pytest.fixture(scope="session") -def sam_data(): - data = {} - data['sandiamod'] = pvsystem.retrieve_sam('sandiamod') - data['adrinverter'] = pvsystem.retrieve_sam('adrinverter') - return data - - @pytest.fixture(scope="session") def sapm_module_params(sam_data): modules = sam_data['sandiamod'] From 5aa88fefe52257e0b3583a0b6b0d8e8f782fb4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20S=C3=A1nchez=20de=20Le=C3=B3n=20Peque?= Date: Wed, 28 Aug 2019 23:10:57 +0200 Subject: [PATCH 10/10] Move PVSyst module params fixture to `conftest.py` --- pvlib/test/conftest.py | 24 ++++++++++++++++++++++++ pvlib/test/test_modelchain.py | 1 - pvlib/test/test_pvsystem.py | 17 ----------------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/pvlib/test/conftest.py b/pvlib/test/conftest.py index faf32c7bc4..ee50b5277e 100644 --- a/pvlib/test/conftest.py +++ b/pvlib/test/conftest.py @@ -159,6 +159,30 @@ def sam_data(): return data +@pytest.fixture(scope="function") +def pvsyst_module_params(): + """ + Define some PVSyst module parameters for testing. + + The scope of the fixture is set to ``'function'`` to allow tests to modify + parameters if required without affecting other tests. + """ + parameters = { + 'gamma_ref': 1.05, + 'mu_gamma': 0.001, + 'I_L_ref': 6.0, + 'I_o_ref': 5e-9, + 'EgRef': 1.121, + 'R_sh_ref': 300, + 'R_sh_0': 1000, + 'R_s': 0.5, + 'R_sh_exp': 5.5, + 'cells_in_series': 60, + 'alpha_sc': 0.001, + } + return parameters + + @pytest.fixture(scope='function') def cec_inverter_parameters(): """ diff --git a/pvlib/test/test_modelchain.py b/pvlib/test/test_modelchain.py index 977baef218..fd2ef40f79 100644 --- a/pvlib/test/test_modelchain.py +++ b/pvlib/test/test_modelchain.py @@ -13,7 +13,6 @@ from pandas.util.testing import assert_series_equal import pytest -from test_pvsystem import pvsyst_module_params from conftest import fail_on_pvlib_version, requires_scipy, requires_tables diff --git a/pvlib/test/test_pvsystem.py b/pvlib/test/test_pvsystem.py index 64ba27f71c..ce854bed5d 100644 --- a/pvlib/test/test_pvsystem.py +++ b/pvlib/test/test_pvsystem.py @@ -238,23 +238,6 @@ def sapm_module_params(sam_data): return module_parameters -@pytest.fixture() -def pvsyst_module_params(): - module_parameters = {} - module_parameters['gamma_ref'] = 1.05 - module_parameters['mu_gamma'] = 0.001 - module_parameters['I_L_ref'] = 6.0 - module_parameters['I_o_ref'] = 5e-9 - module_parameters['EgRef'] = 1.121 - module_parameters['R_sh_ref'] = 300 - module_parameters['R_sh_0'] = 1000 - module_parameters['R_s'] = 0.5 - module_parameters['R_sh_exp'] = 5.5 - module_parameters['cells_in_series'] = 60 - module_parameters['alpha_sc'] = 0.001 - return module_parameters - - def test_retrieve_sam_raise_no_parameters(): """ Raise an exception if no parameters are provided to `retrieve_sam()`.