diff --git a/pvlib/data/Huawei_Sun2000_40KTL_US_SLR.OND b/pvlib/data/Huawei_Sun2000_40KTL_US_SLR.OND new file mode 100644 index 0000000000..7fff2f1cb0 --- /dev/null +++ b/pvlib/data/Huawei_Sun2000_40KTL_US_SLR.OND @@ -0,0 +1,130 @@ +PVObject_=pvGInverter + Comment=Huawei Technologies SUN2000-40KTL-US Manufacturer 2018 + Version=7.3.1 + ParObj1=2017 + ParObj2=2020 + Flags=$803C1540 + + PVObject_Commercial=pvCommercial + Comment=www.huawei.com (China) + Flags=$0041 + Manufacturer=Huawei Technologies + Model=SUN2000-40KTL-US + DataSource=Manufacturer 2018 + YearBeg=2017 + YearEnd=2020 + Width=0.930 + Height=0.550 + Depth=0.260 + Weight=60.000 + NPieces=100 + PriceDate=25/04/23 12:26 + Remarks, Count=3 + Str_1=Technology: transformerless, 16 kHz, IGBT + Str_2=Protection: -25 - +60°C, IP 65, outdoor installation + Str_3=Control: LED indicator, Bluetooth + APP, USB data cable + APP + End of Remarks=Control: LED indicator, Bluetooth + APP, USB data cable + APP + End of PVObject pvCommercial + Transfo=Without + + Converter=TConverter + PNomConv=40.000 + PMaxOUT=44.000 + VOutConv=480.0 + VMppMin=200 + VMPPMax=1000 + VmppNom=720.0 + VAbsMax=1000 + PSeuil=80.0 + EfficMax=98.90 + EfficEuro=0.00 + FResNorm=0.00 + ModeOper=MPPT + CompPMax=Lim + CompVMax=Lim + MonoTri=Tri + ModeAffEnum=Efficf_PIn + UnitAffEnum=kW + PMaxDC=45.000 + IDCMax=0.0 + IMaxDC=88.0 + INomAC=48.2 + IMaxAC=53.0 + TPNom=50.0 + TPMax=45.0 + TPLim1=60.0 + TPLimAbs=62.0 + PLim1=32.000 + HasdefaultPThresh=False + VNomEff=530.0,720.0,850.0, + EfficMaxV=98.100,98.900,98.500, + EfficEuroV=97.810,98.700,98.260, + + ProfilPIOV1=TCubicProfile + NPtsMax=11 + NPtsEff=8 + LastCompile=$8089 + Mode=1 + Point_1=80.0,0.0 + Point_2=4000.0,3868.0 + Point_3=8000.0,7816.0 + Point_4=12000.0,11748.0 + Point_5=20000.0,19620.0 + Point_6=30000.0,29400.0 + Point_7=40000.0,39160.0 + Point_8=44000.0,43032.0 + Point_9=0.0,0.0 + Point_10=0.0,0.0 + Point_11=0.0,0.0 + End of TCubicProfile + + ProfilPIOV2=TCubicProfile + NPtsMax=11 + NPtsEff=8 + LastCompile=$8089 + Mode=1 + Point_1=80.0,0.0 + Point_2=4000.0,3924.0 + Point_3=8000.0,7896.0 + Point_4=12000.0,11856.0 + Point_5=20000.0,19780.0 + Point_6=30000.0,29640.0 + Point_7=40000.0,39520.0 + Point_8=44000.0,43428.0 + Point_9=0.0,0.0 + Point_10=0.0,0.0 + Point_11=0.0,0.0 + End of TCubicProfile + + ProfilPIOV3=TCubicProfile + NPtsMax=11 + NPtsEff=8 + LastCompile=$8089 + Mode=1 + Point_1=80.0,0.0 + Point_2=4000.0,3892.0 + Point_3=8000.0,7856.0 + Point_4=12000.0,11808.0 + Point_5=20000.0,19700.0 + Point_6=30000.0,29520.0 + Point_7=40000.0,39360.0 + Point_8=44000.0,43252.0 + Point_9=0.0,0.0 + Point_10=0.0,0.0 + Point_11=0.0,0.0 + End of TCubicProfile + End of TConverter + NbInputs=8 + NbMPPT=4 + TanPhiMin=-0.750 + TanPhiMax=0.750 + NbMSInterne=2 + MasterSlave=No_M_S + IsolSurvey =Yes + DC_Switch=Yes + AC_Switch=No + DiscAdjust=Yes + ENS_Protec=Yes + MS_Thresh=0.8 + Night_Loss=1.00 +End of PVObject pvGInverter diff --git a/pvlib/inverter.py b/pvlib/inverter.py index 0b57e14d2d..9788d6a67c 100644 --- a/pvlib/inverter.py +++ b/pvlib/inverter.py @@ -547,3 +547,57 @@ def extract_c(x_d, add): # prepare dict and return return {'Paco': p_ac_0, 'Pdco': p_dc0, 'Vdco': v_nom, 'Pso': p_s0, 'C0': c0, 'C1': c1, 'C2': c2, 'C3': c3, 'Pnt': p_nt} + + +def ond_to_sandia_inv(content): + """ + Get parameters for :py:func:`pvlib.inverter.sandia` from content of a + PVsyst OND file. + + Parameters + ---------- + content : dict + OND file content from the nested dict returned from + :py:func:`pvlib.iotools.panond.read_panond` + + Returns + ------- + dict + Parameters for :py:func:`pvlib.inverter.sandia` + + """ + # get power unit + if content['Converter']['UnitAffEnum'] == 'kW': + multiplier = 1000. + else: + multiplier = 1. + # to fit pvlib.inverter.sandia, we need ac_power, dc_power, dc_voltage, + # dc_voltage_level, p_ac_0, p_nt + p_ac_0 = content['Converter']['PNomConv'] * multiplier + p_nt = content['Night_Loss'] + # assemble ac_power and dc_power + ac_power = [] + dc_power = [] + dc_voltage = [] + dc_voltage_level = [] + voltages = content['Converter']['VNomEff'] + if voltages[-1] =='': + voltages = voltages[:-1] + voltage_lvls = ['Vmin', 'Vnom', 'Vmax'] + for v, lvl, profile in zip(voltages, voltage_lvls, + ['ProfilPIOV1', 'ProfilPIOV2', 'ProfilPIOV3']): + data = content['Converter'][profile] + npts = int(data['NPtsEff']) + for p in range(1, npts+1): + dc_voltage.append(v) + dc_voltage_level.append(lvl) + vals = data['Point_' + str(p)] + ac_power.append(vals[1]) + dc_power.append(vals[0]) + dc_power = np.array(dc_power) + ac_power = np.array(ac_power) + dc_voltage = np.array(dc_voltage) + dc_voltage_level = np.array(dc_voltage_level) + return fit_sandia(ac_power, dc_power, + dc_voltage, dc_voltage_level, + p_ac_0, p_nt) diff --git a/pvlib/tests/test_inverter.py b/pvlib/tests/test_inverter.py index 4962d3e495..e52b08aa18 100644 --- a/pvlib/tests/test_inverter.py +++ b/pvlib/tests/test_inverter.py @@ -8,6 +8,7 @@ import pytest from pvlib import inverter +from pvlib.iotools import read_panond def test_adr(adr_inverter_parameters): @@ -211,3 +212,20 @@ def test_fit_sandia(infilen, expected): dc_voltage_level=curves['dc_voltage_level'], p_ac_0=expected['Paco'], p_nt=expected['Pnt']) assert expected == pytest.approx(result, rel=1e-3) + + +OND_FILE = DATA_DIR / 'Huawei_Sun2000_40KTL_US_SLR.OND' +def test_ond_to_sandia(): + content = read_panond(OND_FILE, encoding='utf-8-sig') + data = content['PVObject_'] + result = inverter.ond_to_sandia_inv(data) + expected = {'Paco': 40000., + 'Pdco': 40667.958855217, + 'Pnt': 1.0, + 'Pso': 73.847630974, + 'Vdco': 720.0, + 'C0': -1.6657324233698e-7, + 'C1': -1.7961032678822e-5, + 'C2': -0.0004676856528, + 'C3': -0.0009031894907} + assert expected == pytest.approx(result, rel=1e-8)