From 0b147e83f07fcf01bcbcd5b6f5f88b5fc6e485d3 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Mon, 16 Sep 2024 10:57:40 -0700 Subject: [PATCH 1/6] functions and tests --- pvlib/ivtools/sdm.py | 290 +++++++++++++++++++++++++++++++- pvlib/tests/ivtools/test_sdm.py | 47 +++++- 2 files changed, 335 insertions(+), 2 deletions(-) diff --git a/pvlib/ivtools/sdm.py b/pvlib/ivtools/sdm.py index 07bd6e2396..643d261586 100644 --- a/pvlib/ivtools/sdm.py +++ b/pvlib/ivtools/sdm.py @@ -7,12 +7,14 @@ """ import numpy as np +import pandas as pd from scipy import constants from scipy import optimize from scipy.special import lambertw -from pvlib.pvsystem import calcparams_pvsyst, singlediode, v_from_i +from pvlib.pvsystem import (calcparams_pvsyst, calcparams_cec, singlediode, + v_from_i) from pvlib.singlediode import bishop88_mpp from pvlib.ivtools.utils import rectify_iv_curve, _numdiff @@ -24,6 +26,17 @@ CONSTANTS = {'E0': 1000.0, 'T0': 25.0, 'k': constants.k, 'q': constants.e} +IEC61853 = pd.DataFrame( + columns=['effective_irradiance', 'temp_cell'], + data = np.array( + [[100, 100, 100, 100, 200, 200, 200, 200, 400, 400, 400, 400, + 600, 600, 600, 600, 800, 800, 800, 800, 1000, 1000, 1000, 1000, + 1100, 1100, 1100, 1100], + [15, 25, 50, 75, 15, 25, 50, 75, 15, 25, 50, 75, 15, 25, 50, 75, + 15, 25, 50, 75, 15, 25, 50, 75, 15, 25, 50, 75]]).T, + dtype=np.float64) + + def fit_cec_sam(celltype, v_mp, i_mp, v_oc, i_sc, alpha_sc, beta_voc, gamma_pmp, cells_in_series, temp_ref=25): """ @@ -1354,3 +1367,278 @@ def maxp(temp_cell, irrad_ref, alpha_sc, gamma_ref, mu_gamma, I_L_ref, gamma_pdc = _first_order_centered_difference(maxp, x0=temp_ref, args=args) return gamma_pdc / pmp + + +def _pvsyst_objfun(pvs_mod, cec_ivs, ee, tc, cs): + + # translate the guess into named args that are used in the functions + # order : [alpha_sc, gamma_ref, mu_gamma, I_L_ref, I_o_ref, + # R_sh_mult, R_sh_ref, R_s] + # cec_ivs : DataFrame with columns i_sc, v_oc, i_mp, v_mp, p_mp + # ee : effective irradiance + # tc : cell temperature + # cs : cells in series + alpha_sc = pvs_mod[0] + gamma_ref = pvs_mod[1] + mu_gamma = pvs_mod[2] + I_L_ref = pvs_mod[3] + I_o_ref = pvs_mod[4] + R_sh_mult = pvs_mod[5] + R_sh_ref = pvs_mod[6] + R_s = pvs_mod[7] + + R_sh_0 = R_sh_ref * R_sh_mult + + pvs_params = calcparams_pvsyst( + ee, tc, alpha_sc, gamma_ref, mu_gamma, I_L_ref, I_o_ref, R_sh_ref, + R_sh_0, R_s, cs) + + pvsyst_ivs = singlediode(*pvs_params) + + isc_diff = np.abs((pvsyst_ivs['i_sc'] - cec_ivs['i_sc']) / + cec_ivs['i_sc']).mean() + imp_diff = np.abs((pvsyst_ivs['i_mp'] - cec_ivs['i_mp']) / + cec_ivs['i_mp']).mean() + voc_diff = np.abs((pvsyst_ivs['v_oc'] - cec_ivs['v_oc']) / + cec_ivs['v_oc']).mean() + vmp_diff = np.abs((pvsyst_ivs['v_mp'] - cec_ivs['v_mp']) / + cec_ivs['v_mp']).mean() + pmp_diff = np.abs((pvsyst_ivs['p_mp'] - cec_ivs['p_mp']) / + cec_ivs['p_mp']).mean() + + mean_abs_diff = (isc_diff + imp_diff + voc_diff + vmp_diff + pmp_diff) / 5 + + return mean_abs_diff + + +def convert_cec_pvsyst(cec_model, cells_in_series): + r""" + Convert a CEC model to a PVsyst model. + + Uses optimization to fit the PVsyst model to :math:`I_{sc}`, + :math:`V_{oc}`, :math:`V_{mp}`, :math:`I_{mp}`, and :math:`P_{mp}`, + calculated using the input CEC model at the IEC 61853-3 conditions [2]_. + + Parameters + ---------- + cec_model : dict or DataFrame + Must include keys: 'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', + 'R_sh_ref', 'R_s', 'Adjust' + cell_in_series : int + Number of cells in series. + + Returns + ------- + dict with the following elements: + alpha_sc : float + Short-circuit current temperature coefficient [A/C] . + I_L_ref : float + The light-generated current (or photocurrent) at reference + conditions [A]. + I_o_ref : float + The dark or diode reverse saturation current at reference + conditions [A]. + EgRef : float + The energy bandgap at reference temperature [eV]. + R_s : float + The series resistance at reference conditions [ohm]. + R_sh_ref : float + The shunt resistance at reference conditions [ohm]. + R_sh_0 : float + Shunt resistance at zero irradiance [ohm]. + R_sh_exp : float + Exponential factor defining decrease in shunt resistance with + increasing effective irradiance [unitless]. + gamma_ref : float + Diode (ideality) factor at reference conditions [unitless]. + mu_gamma : float + Temperature coefficient for diode (ideality) factor at reference + conditions [1/K]. + cells_in_series : int + Number of cells in series. + + Notes + ----- + Reference conditions are irradiance of 1000 W/m⁻² and cell temperature of + 25 °C. + + References + ---------- + .. [1] L. Deville et al., "Parameter Translation for Photovoltaic Single + Diode Models", submitted. 2024 + + .. [2] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy + rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. + """ + + # calculate target IV curve values + cec_params = calcparams_cec( + IEC61853['effective_irradiance'], + IEC61853['temp_cell'], + **cec_model) + cec_ivs = singlediode(*cec_params) + + # initial guess at PVsyst parameters + # Order in list is alpha_sc, gamma_ref, mu_gamma, I_L_ref, I_o_ref, + # Rsh_mult = R_sh_0 / R_sh_ref, R_sh_ref, R_s + initial = [0, 1.2, 0.001, cec_model['I_L_ref'], cec_model['I_o_ref'], + 12, 1000, cec_model['R_s']] + + # bounds for PVsyst parameters + b_alpha = (-1, 1) + b_gamma = (1, 2) + b_mu = (-1, 1) + b_IL = (1e-12, 100) + b_Io = (1e-24, 0.1) + b_Rmult = (1, 20) + b_Rsh = (100, 1e6) + b_Rs = (1e-12, 10) + bounds = [b_alpha, b_gamma, b_mu, b_IL, b_Io, b_Rmult, b_Rsh, b_Rs] + + # optimization to find PVsyst parameters + result = optimize.minimize( + _pvsyst_objfun, initial, + args=(cec_ivs, IEC61853['effective_irradiance'], + IEC61853['temp_cell'], cells_in_series), + method='Nelder-Mead', bounds=bounds, + options={'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001}) + alpha_sc, gamma, mu_gamma, I_L_ref, I_o_ref, Rsh_mult, R_sh_ref, R_s = \ + result.x + + R_sh_0 = Rsh_mult * R_sh_ref + R_sh_exp = 5.5 + EgRef = 1.121 # default for all modules in the CEC model + return {'alpha_sc': alpha_sc, + 'I_L_ref': I_L_ref, 'I_o_ref': I_o_ref, 'EgRef': EgRef, 'R_s': R_s, + 'R_sh_ref': R_sh_ref, 'R_sh_0': R_sh_0, 'R_sh_exp': R_sh_exp, + 'gamma_ref': gamma, 'mu_gamma': mu_gamma, + 'cells_in_series': cells_in_series, + } + + +def _cec_objfun(cec_mod, pvs_ivs, ee, tc, alpha_sc): + # translate the guess into named args that are used in the functions + # order : [I_L_ref, I_o_ref, a_ref, R_sh_ref, R_s, alpha_sc, Adjust] + # pvs_ivs : DataFrame with columns i_sc, v_oc, i_mp, v_mp, p_mp + # ee : effective irradiance + # tc : cell temperature + # alpha_sc : temperature coefficient for Isc + I_L_ref = cec_mod[0] + I_o_ref = cec_mod[1] + a_ref = cec_mod[2] + R_sh_ref = cec_mod[3] + R_s = cec_mod[4] + Adjust = cec_mod[5] + alpha_sc = alpha_sc + + cec_params = calcparams_cec( + ee, tc, alpha_sc, a_ref, I_L_ref, I_o_ref, R_sh_ref, R_s, Adjust) + cec_ivs = singlediode(*cec_params) + + isc_rss = np.sqrt(sum((cec_ivs['i_sc'] - pvs_ivs['i_sc'])**2)) + imp_rss = np.sqrt(sum((cec_ivs['i_mp'] - pvs_ivs['i_mp'])**2)) + voc_rss = np.sqrt(sum((cec_ivs['v_oc'] - pvs_ivs['v_oc'])**2)) + vmp_rss = np.sqrt(sum((cec_ivs['v_mp'] - pvs_ivs['v_mp'])**2)) + pmp_rss = np.sqrt(sum((cec_ivs['p_mp'] - pvs_ivs['p_mp'])**2)) + + mean_diff = (isc_rss+imp_rss+voc_rss+vmp_rss+pmp_rss) / 5 + + return mean_diff + + +def convert_pvsyst_cec(pvsyst_model): + r""" + Convert a PVsyst model to a CEC model. + + Uses optimization to fit the CEC model to :math:`I_{sc}`, + :math:`V_{oc}`, :math:`V_{mp}`, :math:`I_{mp}`, and :math:`P_{mp}`, + calculated using the input PVsyst model at the IEC 61853-3 conditions [2]_. + + Parameters + ---------- + cec_model : dict or DataFrame + Must include keys: 'alpha_sc', 'I_L_ref', 'I_o_ref', 'EgRef', 'R_s', + 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'gamma_ref', 'mu_gamma', + 'cells_in_series' + + Returns + ------- + dict with the following elements: + I_L_ref : float + The light-generated current (or photocurrent) at reference + conditions [A]. + I_o_ref : float + The dark or diode reverse saturation current at reference + conditions [A]. + R_s : float + The series resistance at reference conditions [ohm]. + R_sh_ref : float + The shunt resistance at reference conditions [ohm]. + 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 [V]. + Adjust : float + The adjustment to the temperature coefficient for short circuit + current, in percent. + EgRef : float + The energy bandgap at reference temperature [eV]. + dEgdT : float + The temperature dependence of the energy bandgap at reference + conditions [1/K]. + + Notes + ----- + Reference conditions are irradiance of 1000 W/m⁻² and cell temperature of + 25 °C. + + References + ---------- + .. [1] L. Deville et al., "Parameter Translation for Photovoltaic Single + Diode Models", submitted. 2024. + + .. [2] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy + rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. + """ + # calculate target IV curve values + pvs_params = calcparams_pvsyst( + IEC61853['effective_irradiance'], + IEC61853['temp_cell'], + **pvsyst_model) + pvsyst_ivs = singlediode(*pvs_params) + + # set EgRef and dEgdT to CEC defaults + EgRef = 1.121 + dEgdT = -0.0002677 + + # initial guess + # order must match _pvsyst_objfun + # order : [I_L_ref, I_o_ref, a_ref, R_sh_ref, R_s, alpha_sc, Adjust] + nNsVth = pvsyst_model['gamma_ref'] * pvsyst_model['cells_in_series'] \ + * 0.025 + initial = [pvsyst_model['I_L_ref'], pvsyst_model['I_o_ref'], + nNsVth, pvsyst_model['R_sh_ref'], pvsyst_model['R_s'], + 0] + + # bounds for PVsyst parameters + b_IL = (1e-12, 100) + b_Io = (1e-24, 0.1) + b_aref = (1e-12, 1000) + b_Rsh = (100, 1e6) + b_Rs = (1e-12, 10) + b_Adjust = (-100, 100) + bounds = [b_IL, b_Io, b_aref, b_Rsh, b_Rs, b_Adjust] + + result = optimize.minimize( + _cec_objfun, initial, + args=(pvsyst_ivs, IEC61853['effective_irradiance'], + IEC61853['temp_cell'], pvsyst_model['alpha_sc']), + method='Nelder-Mead', bounds=bounds, + options={'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001}) + I_L_ref, I_o_ref, a_ref, R_sh_ref, R_s, Adjust = result.x + + return {'alpha_sc': pvsyst_model['alpha_sc'], + 'a_ref': a_ref, 'I_L_ref': I_L_ref, 'I_o_ref': I_o_ref, + 'R_sh_ref': R_sh_ref, 'R_s': R_s, 'Adjust': Adjust, + 'EgRef': EgRef, 'dEgdT': dEgdT + } diff --git a/pvlib/tests/ivtools/test_sdm.py b/pvlib/tests/ivtools/test_sdm.py index d4cc7db141..ae28a0045d 100644 --- a/pvlib/tests/ivtools/test_sdm.py +++ b/pvlib/tests/ivtools/test_sdm.py @@ -6,7 +6,6 @@ from pvlib.ivtools import sdm from pvlib import pvsystem -from pvlib._deprecation import pvlibDeprecationWarning from pvlib.tests.conftest import requires_pysam, requires_statsmodels @@ -405,3 +404,49 @@ def test_pvsyst_temperature_coeff(): params['I_L_ref'], params['I_o_ref'], params['R_sh_ref'], params['R_sh_0'], params['R_s'], params['cells_in_series']) assert_allclose(gamma_pdc, expected, rtol=0.0005) + + +def test_convert_cec_pvsyst(): + cells_in_series = 66 + trina660_cec = {'I_L_ref': 18.4759, 'I_o_ref': 5.31e-12, + 'EgRef': 1.121, 'dEgdT': -0.0002677, + 'R_s': 0.159916, 'R_sh_ref': 113.991, 'a_ref': 1.59068, + 'Adjust': 6.42247, 'alpha_sc': 0.00629} + trina660_pvsyst_est = sdm.convert_cec_pvsyst(trina660_cec, + cells_in_series) + pvsyst_expected = {'alpha_sc': 0.007478218748188788, + 'I_L_ref': 18.227679597516214, + 'I_o_ref': 2.7418999402908e-11, + 'EgRef': 1.121, + 'R_s': 0.16331908293164496, + 'R_sh_ref': 5267.928954454954, + 'R_sh_0': 60171.206687871425, + 'R_sh_exp': 5.5, + 'gamma_ref': 1.0, + 'mu_gamma': -6.349173477135307e-05, + 'cells_in_series': 66} + + assert np.all([np.isclose(trina660_pvsyst_est[k], pvsyst_expected[k], + rtol=1e-3) + for k in pvsyst_expected]) + + +def test_convert_pvsyst_cec(): + trina660_pvsyst = {'alpha_sc': 0.0074, 'I_o_ref': 3.3e-11, 'EgRef': 1.121, + 'R_s': 0.156, 'R_sh_ref': 200, 'R_sh_0': 800, + 'R_sh_exp': 5.5, 'gamma_ref': 1.002, 'mu_gamma': 1e-3, + 'cells_in_series': 66} + trina660_cec_est = sdm.convert_pvsyst_cec(trina660_pvsyst) + cec_expected = {'alpha_sc': 0.0074, + 'I_L_ref': 18.05154226834071, + 'I_o_ref': 2.6863417875143392e-14, + 'EgRef': 1.121, + 'dEgdT': -0.0002677, + 'R_s': 0.09436341848926795, + 'a_ref': 1.2954800250731866, + 'Adjust': 0.0011675969492410047, + 'cells_in_series': 66} + + assert np.all([np.isclose(trina660_cec_est[k], cec_expected[k], + rtol=1e-3) + for k in cec_expected]) From 480c01bbb9224e29bbccdc06fba374da718e5d78 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Thu, 19 Sep 2024 11:18:19 -0700 Subject: [PATCH 2/6] fix test --- pvlib/ivtools/sdm.py | 4 ++-- pvlib/tests/ivtools/test_sdm.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pvlib/ivtools/sdm.py b/pvlib/ivtools/sdm.py index 643d261586..3a857d599c 100644 --- a/pvlib/ivtools/sdm.py +++ b/pvlib/ivtools/sdm.py @@ -28,7 +28,7 @@ IEC61853 = pd.DataFrame( columns=['effective_irradiance', 'temp_cell'], - data = np.array( + data=np.array( [[100, 100, 100, 100, 200, 200, 200, 200, 400, 400, 400, 400, 600, 600, 600, 600, 800, 800, 800, 800, 1000, 1000, 1000, 1000, 1100, 1100, 1100, 1100], @@ -1556,7 +1556,7 @@ def convert_pvsyst_cec(pvsyst_model): Parameters ---------- - cec_model : dict or DataFrame + pvsyst_model : dict or DataFrame Must include keys: 'alpha_sc', 'I_L_ref', 'I_o_ref', 'EgRef', 'R_s', 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'gamma_ref', 'mu_gamma', 'cells_in_series' diff --git a/pvlib/tests/ivtools/test_sdm.py b/pvlib/tests/ivtools/test_sdm.py index ae28a0045d..b4fd8ef556 100644 --- a/pvlib/tests/ivtools/test_sdm.py +++ b/pvlib/tests/ivtools/test_sdm.py @@ -432,7 +432,8 @@ def test_convert_cec_pvsyst(): def test_convert_pvsyst_cec(): - trina660_pvsyst = {'alpha_sc': 0.0074, 'I_o_ref': 3.3e-11, 'EgRef': 1.121, + trina660_pvsyst = {'alpha_sc': 0.0074, 'I_L_ref': 18.464391, + 'I_o_ref': 3.3e-11, 'EgRef': 1.121, 'R_s': 0.156, 'R_sh_ref': 200, 'R_sh_0': 800, 'R_sh_exp': 5.5, 'gamma_ref': 1.002, 'mu_gamma': 1e-3, 'cells_in_series': 66} From 22d51ee628b43d9fa1823f34624f3008088abac7 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Thu, 19 Sep 2024 11:34:36 -0700 Subject: [PATCH 3/6] build doc pages --- docs/sphinx/source/reference/pv_modeling/parameters.rst | 8 ++++++++ pvlib/ivtools/sdm.py | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/docs/sphinx/source/reference/pv_modeling/parameters.rst b/docs/sphinx/source/reference/pv_modeling/parameters.rst index 9b1817bd01..6b54cfedfd 100644 --- a/docs/sphinx/source/reference/pv_modeling/parameters.rst +++ b/docs/sphinx/source/reference/pv_modeling/parameters.rst @@ -21,6 +21,14 @@ Functions for fitting the single diode equation ivtools.sde.fit_sandia_simple +Functions for converting between single diode models + +.. autosummary:: + :toctree: ../generated/ + + ivtools.sdm.convert_cec_pvsyst + ivtools.sdm.convert_pvsyst_cec + Utilities for working with IV curve data .. autosummary:: diff --git a/pvlib/ivtools/sdm.py b/pvlib/ivtools/sdm.py index 3a857d599c..8a9a3b247e 100644 --- a/pvlib/ivtools/sdm.py +++ b/pvlib/ivtools/sdm.py @@ -1462,6 +1462,10 @@ def convert_cec_pvsyst(cec_model, cells_in_series): Reference conditions are irradiance of 1000 W/m⁻² and cell temperature of 25 °C. + See Also + -------- + pvlib.ivtools.sdm.convert_pvsyst_cec + References ---------- .. [1] L. Deville et al., "Parameter Translation for Photovoltaic Single @@ -1592,6 +1596,10 @@ def convert_pvsyst_cec(pvsyst_model): Reference conditions are irradiance of 1000 W/m⁻² and cell temperature of 25 °C. + See Also + -------- + pvlib.ivtools.sdm.convert_cec_pvsyst + References ---------- .. [1] L. Deville et al., "Parameter Translation for Photovoltaic Single From d65b57f049d1395b16ca706d7131c090597cae89 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Thu, 19 Sep 2024 11:47:25 -0700 Subject: [PATCH 4/6] really fix test --- pvlib/tests/ivtools/test_sdm.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pvlib/tests/ivtools/test_sdm.py b/pvlib/tests/ivtools/test_sdm.py index b4fd8ef556..5c0b4091d8 100644 --- a/pvlib/tests/ivtools/test_sdm.py +++ b/pvlib/tests/ivtools/test_sdm.py @@ -445,8 +445,7 @@ def test_convert_pvsyst_cec(): 'dEgdT': -0.0002677, 'R_s': 0.09436341848926795, 'a_ref': 1.2954800250731866, - 'Adjust': 0.0011675969492410047, - 'cells_in_series': 66} + 'Adjust': 0.0011675969492410047} assert np.all([np.isclose(trina660_cec_est[k], cec_expected[k], rtol=1e-3) From bc01aa78c6a46f04f520a47241408e64becbb143 Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Mon, 23 Sep 2024 09:22:26 -0700 Subject: [PATCH 5/6] add kwargs --- pvlib/ivtools/sdm.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/pvlib/ivtools/sdm.py b/pvlib/ivtools/sdm.py index 8a9a3b247e..ac76fbf968 100644 --- a/pvlib/ivtools/sdm.py +++ b/pvlib/ivtools/sdm.py @@ -1411,7 +1411,8 @@ def _pvsyst_objfun(pvs_mod, cec_ivs, ee, tc, cs): return mean_abs_diff -def convert_cec_pvsyst(cec_model, cells_in_series): +def convert_cec_pvsyst(cec_model, cells_in_series, method='Nelder-Mead', + options=None): r""" Convert a CEC model to a PVsyst model. @@ -1426,6 +1427,10 @@ def convert_cec_pvsyst(cec_model, cells_in_series): 'R_sh_ref', 'R_s', 'Adjust' cell_in_series : int Number of cells in series. + method : str, default 'Nelder-Mead' + Method for scipy.optimize.minimize. + options : dict, optional + Solver options passed to scipy.optimize.minimize Returns ------- @@ -1474,6 +1479,8 @@ def convert_cec_pvsyst(cec_model, cells_in_series): .. [2] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. """ + if options==None: + options = {'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001} # calculate target IV curve values cec_params = calcparams_cec( @@ -1504,8 +1511,10 @@ def convert_cec_pvsyst(cec_model, cells_in_series): _pvsyst_objfun, initial, args=(cec_ivs, IEC61853['effective_irradiance'], IEC61853['temp_cell'], cells_in_series), - method='Nelder-Mead', bounds=bounds, - options={'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001}) + method='Nelder-Mead', + bounds=bounds, + options=options) + alpha_sc, gamma, mu_gamma, I_L_ref, I_o_ref, Rsh_mult, R_sh_ref, R_s = \ result.x @@ -1550,7 +1559,7 @@ def _cec_objfun(cec_mod, pvs_ivs, ee, tc, alpha_sc): return mean_diff -def convert_pvsyst_cec(pvsyst_model): +def convert_pvsyst_cec(pvsyst_model, method='Nelder-Mead', options=None): r""" Convert a PVsyst model to a CEC model. @@ -1564,6 +1573,10 @@ def convert_pvsyst_cec(pvsyst_model): Must include keys: 'alpha_sc', 'I_L_ref', 'I_o_ref', 'EgRef', 'R_s', 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'gamma_ref', 'mu_gamma', 'cells_in_series' + method : str, default 'Nelder-Mead' + Method for scipy.optimize.minimize. + options : dict, optional + Solver options passed to scipy.optimize.minimize Returns ------- @@ -1608,6 +1621,10 @@ def convert_pvsyst_cec(pvsyst_model): .. [2] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. """ + + if options==None: + options = {'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001} + # calculate target IV curve values pvs_params = calcparams_pvsyst( IEC61853['effective_irradiance'], @@ -1641,8 +1658,10 @@ def convert_pvsyst_cec(pvsyst_model): _cec_objfun, initial, args=(pvsyst_ivs, IEC61853['effective_irradiance'], IEC61853['temp_cell'], pvsyst_model['alpha_sc']), - method='Nelder-Mead', bounds=bounds, - options={'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001}) + method='Nelder-Mead', + bounds=bounds, + options=options) + I_L_ref, I_o_ref, a_ref, R_sh_ref, R_s, Adjust = result.x return {'alpha_sc': pvsyst_model['alpha_sc'], From ae4346bbb3951f2cd19377af71c3f2faa3cf1cad Mon Sep 17 00:00:00 2001 From: Cliff Hansen Date: Mon, 23 Sep 2024 10:14:04 -0700 Subject: [PATCH 6/6] docstring edits --- pvlib/ivtools/sdm.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pvlib/ivtools/sdm.py b/pvlib/ivtools/sdm.py index ac76fbf968..2e85e6b2c2 100644 --- a/pvlib/ivtools/sdm.py +++ b/pvlib/ivtools/sdm.py @@ -1414,11 +1414,13 @@ def _pvsyst_objfun(pvs_mod, cec_ivs, ee, tc, cs): def convert_cec_pvsyst(cec_model, cells_in_series, method='Nelder-Mead', options=None): r""" - Convert a CEC model to a PVsyst model. + Convert a set of CEC model parameters to an equivalent set of PVsyst model + parameters. - Uses optimization to fit the PVsyst model to :math:`I_{sc}`, - :math:`V_{oc}`, :math:`V_{mp}`, :math:`I_{mp}`, and :math:`P_{mp}`, - calculated using the input CEC model at the IEC 61853-3 conditions [2]_. + Parameter conversion uses optimization as described in [1]_ to fit the + PVsyst model to :math:`I_{sc}`, :math:`V_{oc}`, :math:`V_{mp}`, + :math:`I_{mp}`, and :math:`P_{mp}`, calculated using the input CEC model + at the IEC 61853-3 conditions [2]_. Parameters ---------- @@ -1430,7 +1432,7 @@ def convert_cec_pvsyst(cec_model, cells_in_series, method='Nelder-Mead', method : str, default 'Nelder-Mead' Method for scipy.optimize.minimize. options : dict, optional - Solver options passed to scipy.optimize.minimize + Solver options passed to scipy.optimize.minimize. Returns ------- @@ -1479,7 +1481,7 @@ def convert_cec_pvsyst(cec_model, cells_in_series, method='Nelder-Mead', .. [2] "IEC 61853-3 Photovoltaic (PV) module performance testing and energy rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. """ - if options==None: + if options is None: options = {'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001} # calculate target IV curve values @@ -1561,11 +1563,13 @@ def _cec_objfun(cec_mod, pvs_ivs, ee, tc, alpha_sc): def convert_pvsyst_cec(pvsyst_model, method='Nelder-Mead', options=None): r""" - Convert a PVsyst model to a CEC model. + Convert a set of PVsyst model parameters to an equivalent set of CEC model + parameters. - Uses optimization to fit the CEC model to :math:`I_{sc}`, - :math:`V_{oc}`, :math:`V_{mp}`, :math:`I_{mp}`, and :math:`P_{mp}`, - calculated using the input PVsyst model at the IEC 61853-3 conditions [2]_. + Parameter conversion uses optimization as described in [1]_ to fit the + CEC model to :math:`I_{sc}`, :math:`V_{oc}`, :math:`V_{mp}`, + :math:`I_{mp}`, and :math:`P_{mp}`, calculated using the input PVsyst model + at the IEC 61853-3 conditions [2]_. Parameters ---------- @@ -1576,7 +1580,7 @@ def convert_pvsyst_cec(pvsyst_model, method='Nelder-Mead', options=None): method : str, default 'Nelder-Mead' Method for scipy.optimize.minimize. options : dict, optional - Solver options passed to scipy.optimize.minimize + Solver options passed to scipy.optimize.minimize. Returns ------- @@ -1622,7 +1626,7 @@ def convert_pvsyst_cec(pvsyst_model, method='Nelder-Mead', options=None): rating - Part 3: Energy rating of PV modules". IEC, Geneva, 2018. """ - if options==None: + if options is None: options = {'maxiter': 5000, 'maxfev': 5000, 'xatol': 0.001} # calculate target IV curve values