def test_newton_fs_495(method, cec_module_fs_495): """test pvsystem.singlediode with different methods on FS495""" 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'], 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=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) # 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)
def test_newton_fs_495(): """test pvsystem.singlediode with Newton 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='newton') 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 test_newton_fs_495(): """test pvsystem.singlediode with Newton 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='newton') 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 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
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 = 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'], EgRef=1.121, dEgdT=-0.0002677) il, io, rs, rsh, nnsvt = x pvs = pvsystem.singlediode(*x, method='lambertw') 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) # 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)
def _update_io(voc, iph, io, rs, rsh, nnsvth): """ Adjusts Io to match Voc using other parameter values. Helper function for fit_pvsyst_sandia, fit_desoto_sandia Description ----------- Io is updated iteratively 10 times or until successive values are less than 0.000001 % different. The updating is similar to Newton's method. Parameters ---------- voc: a numpy array of length N of values for Voc (V) iph: a numpy array of length N of values for lighbt current IL (A) io: a numpy array of length N of initial values for Io (A) rs: a numpy array of length N of values for the series resistance (ohm) rsh: a numpy array of length N of values for the shunt resistance (ohm) nnsvth: a numpy array of length N of values for the diode factor x thermal voltage for the module, equal to Ns (number of cells in series) x Vth (thermal voltage per cell). Returns ------- new_io - a numpy array of length N of updated values for io References ---------- .. [1] PVLib MATLAB https://github.com/sandialabs/MATLAB_PV_LIB .. [2] C. Hansen, Parameter Estimation for Single Diode Models of Photovoltaic Modules, Sandia National Laboratories Report SAND2015-2065 .. [3] C. Hansen, Estimation of Parameteres for Single Diode Models using Measured IV Curves, Proc. of the 39th IEEE PVSC, June 2013. """ eps = 1e-6 niter = 10 k = 1 maxerr = 1 tio = io # Current Estimate of Io while maxerr > eps and k < niter: # Predict Voc pvoc = v_from_i(rsh, rs, nnsvth, 0., tio, iph) # Difference in Voc dvoc = pvoc - voc # Update Io with np.errstate(invalid="ignore", divide="ignore"): new_io = tio * (1. + (2. * dvoc) / (2. * nnsvth - dvoc)) # Calculate Maximum Percent Difference maxerr = np.max(np.abs(new_io - tio) / tio) * 100. tio = new_io k += 1. return new_io
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
def test_v_from_i(fixture_v_from_i, method, atol): # Solution set loaded from fixture Rsh = fixture_v_from_i['Rsh'] Rs = fixture_v_from_i['Rs'] nNsVth = fixture_v_from_i['nNsVth'] I = fixture_v_from_i['I'] I0 = fixture_v_from_i['I0'] IL = fixture_v_from_i['IL'] V_expected = fixture_v_from_i['V_expected'] V = pvsystem.v_from_i(Rsh, Rs, nNsVth, I, I0, IL, method=method) assert (isinstance(V, type(V_expected))) if isinstance(V, type(np.ndarray)): assert (isinstance(V.dtype, type(V_expected.dtype))) assert (V.shape == V_expected.shape) assert_allclose(V, V_expected, atol=atol)
def test_v_from_i(fixture_v_from_i): # Solution set loaded from fixture Rsh = fixture_v_from_i['Rsh'] Rs = fixture_v_from_i['Rs'] nNsVth = fixture_v_from_i['nNsVth'] I = fixture_v_from_i['I'] I0 = fixture_v_from_i['I0'] IL = fixture_v_from_i['IL'] V_expected = fixture_v_from_i['V_expected'] # Convergence criteria atol = 1.e-11 V = pvsystem.v_from_i(Rsh, Rs, nNsVth, I, I0, IL) assert(isinstance(V, type(V_expected))) if isinstance(V, type(np.ndarray)): assert(isinstance(V.dtype, type(V_expected.dtype))) assert(V.shape == V_expected.shape) assert_allclose(V, V_expected, atol=atol)
def test_v_from_i_size(): with pytest.raises(ValueError): pvsystem.v_from_i(20, [0.1] * 2, 0.5, [3.0] * 3, 6.0e-7, 7.0) with pytest.raises(ValueError): pvsystem.v_from_i(20, [0.1] * 2, 0.5, [3.0] * 3, 6.0e-7, 7.0, method='brentq') with pytest.raises(ValueError): pvsystem.v_from_i(20, [0.1], 0.5, [3.0] * 3, 6.0e-7, np.array([7., 7.]), method='newton')
def test_v_from_i(): output = pvsystem.v_from_i(20, .1, .5, 3, 6e-7, 7) assert_allclose(7.5049875193450521, output, atol=1e-5)
def test_v_from_i_big(): output = pvsystem.v_from_i(500, 10, 4.06, 0, 6e-10, 1.2) assert_almost_equals(86.320000493521079, output, 5)
def test_v_from_i(): output = pvsystem.v_from_i(20, .1, .5, 3, 6e-7, 7) assert_almost_equals(7.5049875193450521, output, 5)
def update_io_known_n(rsh, rs, nnsvth, io, il, voc): """ update_io_known_n adjusts io to match voc using other parameter values. Syntax ------ outio = update_io_known_n(rsh, rs, nnsvth, io, il, voc) Description ----------- update_io_known_n adjusts io to match voc using other parameter values, i.e., Rsh (shunt resistance), Rs (Series Resistance), n (diode factor), and IL (Light Current). Io is updated iteratively 10 times or until successive values are less than 0.000001 % different. The updating is similar to Newton's method. Parameters ---------- rsh: a numpy array of length N of values for the shunt resistance (ohm) rs: a numpy array of length N of values for the series resistance (ohm) nnsvth: a numpy array of length N of values for the diode factor x thermal voltage for the module, equal to Ns (number of cells in series) x Vth (thermal voltage per cell). io: a numpy array of length N of initial values for Io (A) il: a numpy array of length N of values for lighbt current IL (A) voc: a numpy array of length N of values for Voc (V) Returns ------- outio - a numpy array of lenght N of updated values for Io References ---------- [1] PVLib MATLAB [2] C. Hansen, Parameter Estimation for Single Diode Models of Photovoltaic Modules, Sandia National Laboratories Report SAND2015-XXXX [3] C. Hansen, Estimation of Parameteres for Single Diode Models using Measured IV Curves, Proc. of the 39th IEEE PVSC, June 2013. """ eps = 1e-6 niter = 10 k = 1 maxerr = 1 tio = io # Current Estimate of Io while maxerr > eps and k < niter: # Predict Voc pvoc = v_from_i(rsh, rs, nnsvth, 0., tio, il) # Difference in Voc dvoc = pvoc - voc # Update Io next_io = tio * (1. + (2. * dvoc) / (2. * nnsvth - dvoc)) # Calculate Maximum Percent Difference maxerr = np.max(np.abs(next_io - tio) / tio) * 100. tio = next_io k += 1. outio = tio return outio
def test_v_from_i_bigger(): # 1000 W/m^2 on a Canadian Solar 220M with 20 C ambient temp # github issue 225 output = pvsystem.v_from_i(190, 1.065, 2.89, 0, 7.05196029e-08, 10.491262) assert_allclose(54.303958833791455, output, atol=1e-5)
def test_v_from_i_big(): output = pvsystem.v_from_i(500, 10, 4.06, 0, 6e-10, 1.2) assert_allclose(86.320000493521079, output, atol=1e-5)
def test_v_from_i(): output = pvsystem.v_from_i(20, .1, .5, 3, 6e-7, 7) assert_allclose(7.5049875193450521, output, atol=1e-5)
def test_v_from_i_big(): output = pvsystem.v_from_i(500, 10, 4.06, 0, 6e-10, 1.2) assert_allclose(86.320000493521079, output, atol=1e-5)
def test_v_from_i_bigger(): # 1000 W/m^2 on a Canadian Solar 220M with 20 C ambient temp # github issue 225 output = pvsystem.v_from_i(190, 1.065, 2.89, 0, 7.05196029e-08, 10.491262) assert_allclose(54.303958833791455, output, atol=1e-5)
def test_singlediode_series_ivcurve(cec_module_params): times = pd.date_range(start='2015-06-01', periods=3, freq='6H') effective_irradiance = pd.Series([0.0, 400.0, 800.0], index=times) IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto( effective_irradiance, temp_cell=25, alpha_sc=cec_module_params['alpha_sc'], a_ref=cec_module_params['a_ref'], I_L_ref=cec_module_params['I_L_ref'], I_o_ref=cec_module_params['I_o_ref'], R_sh_ref=cec_module_params['R_sh_ref'], R_s=cec_module_params['R_s'], EgRef=1.121, dEgdT=-0.0002677) out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, ivcurve_pnts=3, method='lambertw') expected = OrderedDict([ ('i_sc', array([0., 3.01054475, 6.00675648])), ('v_oc', array([0., 9.96886962, 10.29530483])), ('i_mp', array([0., 2.65191983, 5.28594672])), ('v_mp', array([0., 8.33392491, 8.4159707])), ('p_mp', array([0., 22.10090078, 44.48637274])), ('i_x', array([0., 2.88414114, 5.74622046])), ('i_xx', array([0., 2.04340914, 3.90007956])), ('v', array([[0., 0., 0.], [0., 4.98443481, 9.96886962], [0., 5.14765242, 10.29530483]])), ('i', array([[0., 0., 0.], [3.01079860e+00, 2.88414114e+00, 3.10862447e-14], [6.00726296e+00, 5.74622046e+00, 0.00000000e+00]])) ]) for k, v in out.items(): assert_allclose(v, expected[k], atol=1e-2) out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, ivcurve_pnts=3) expected['i_mp'] = pvsystem.i_from_v(Rsh, Rs, nNsVth, out['v_mp'], I0, IL, method='lambertw') expected['v_mp'] = pvsystem.v_from_i(Rsh, Rs, nNsVth, out['i_mp'], I0, IL, method='lambertw') expected['i'] = pvsystem.i_from_v(Rsh, Rs, nNsVth, out['v'].T, I0, IL, method='lambertw').T expected['v'] = pvsystem.v_from_i(Rsh, Rs, nNsVth, out['i'].T, I0, IL, method='lambertw').T for k, v in out.items(): assert_allclose(v, expected[k], atol=1e-2)
def test_v_from_i_big(): output = pvsystem.v_from_i(500, 10, 4.06, 0, 6e-10, 1.2) assert_almost_equals(86.320000493521079, output, 5)
def test_v_from_i(): output = pvsystem.v_from_i(20, .1, .5, 3, 6e-7, 7) assert_almost_equals(7.5049875193450521, output, 5)