Fitting Datasheet to Sandia Inverter Parameters

332 views
Skip to first unread message

Orçun Başlak

unread,
Oct 1, 2023, 2:11:43 PM10/1/23
to pvlib-python
Dear all,

I'm trying to calculate Sandia inverter parameters from OND file but my resulting values underestimates the production compared to the same inverter from Sandia database.

I managed to find Huawei 40kTL both in PVSYST and Sandia database and tried my runs with it.

The values from Sandia database are as follows.

sandia_web_inverter = {
"name" : "SUN2000-40KTL-US [480V] 480V [CEC 2018]",
"Vac": 480.,
"Paco": 40000.,
"Vdco": 720.,
"Pdco": 40649.7,
"C0": -1.05E-07,
"C1": -1.80E-05,
"C2": -2.11E-03,
"C3": 3.84E-03,
"Pso": 57.1,
"Pnt": 1.8,
"Vdcmax": 850.,
"Idcmax": 56.457937,
"Mppt_low": 530.,
"Mppt_high": 850.
}

The data from OND file is as below.

inverter_model = inverter_parameters['pvGInverter']['pvCommercial']['Manufacturer']

nominal_ac_voltage = float(inverter_parameters['pvGInverter']['TConverter']['VOutConv'])
nominal_ac_power = float(inverter_parameters['pvGInverter']['TConverter']['PNomConv']) * 1000

nominal_dc_voltage = float(inverter_parameters['pvGInverter']['TConverter']['VmppNom'])
nominal_dc_power = float(inverter_parameters['pvGInverter']['TConverter']['PMaxOUT']) * 1000

maximum_dc_voltage = float(inverter_parameters['pvGInverter']['TConverter']['VMPPMax'])
maximum_dc_current = float(inverter_parameters['pvGInverter']['TConverter']['IMaxDC'])

mppt_low = float(inverter_parameters['pvGInverter']['TConverter']['VMppMin'])
mppt_high = float(inverter_parameters['pvGInverter']['TConverter']['VMPPMax'])

pso = float(inverter_parameters['pvGInverter']['TConverter']['PSeuil'])
p_nt = 0 #float(inverter_parameters['pvGInverter']['Night_Loss'])

inverter_voltages = inverter_parameters['pvGInverter']['TConverter']['VNomEff'].split(",")
powerThreshold = float(inverter_parameters['pvGInverter']['TConverter']['PSeuil'])

# dc voltage at min, nom and max
dc_voltage = [[float(inverter_voltages[0])], [float(inverter_voltages[1])], [float(inverter_voltages[2])]]

# calculate dc power
inverter_power = float(inverter_parameters['pvGInverter']['TConverter']['PMaxOUT'])

inverter_eff_vmin = inverter_parameters['pvGInverter']['TConverter']['ProfilPIOV1']
inverter_eff_vnom = inverter_parameters['pvGInverter']['TConverter']['ProfilPIOV2']
inverter_eff_vmax = inverter_parameters['pvGInverter']['TConverter']['ProfilPIOV3']

p_ac_min = [
float(inverter_eff_vmin['Point_1'].split(",")[1]),
float(inverter_eff_vmin['Point_2'].split(",")[1]),
float(inverter_eff_vmin['Point_3'].split(",")[1]),
float(inverter_eff_vmin['Point_4'].split(",")[1]),
float(inverter_eff_vmin['Point_5'].split(",")[1]),
float(inverter_eff_vmin['Point_6'].split(",")[1]),
float(inverter_eff_vmin['Point_7'].split(",")[1]),
float(inverter_eff_vmin['Point_8'].split(",")[1]),
]

p_ac_nom = [
float(inverter_eff_vnom['Point_1'].split(",")[1]),
float(inverter_eff_vnom['Point_2'].split(",")[1]),
float(inverter_eff_vnom['Point_3'].split(",")[1]),
float(inverter_eff_vnom['Point_4'].split(",")[1]),
float(inverter_eff_vnom['Point_5'].split(",")[1]),
float(inverter_eff_vnom['Point_6'].split(",")[1]),
float(inverter_eff_vnom['Point_7'].split(",")[1]),
float(inverter_eff_vnom['Point_8'].split(",")[1]),
]

p_ac_max = [
float(inverter_eff_vmax['Point_1'].split(",")[1]),
float(inverter_eff_vmax['Point_2'].split(",")[1]),
float(inverter_eff_vmax['Point_3'].split(",")[1]),
float(inverter_eff_vmax['Point_4'].split(",")[1]),
float(inverter_eff_vmax['Point_5'].split(",")[1]),
float(inverter_eff_vmax['Point_6'].split(",")[1]),
float(inverter_eff_vmax['Point_7'].split(",")[1]),
float(inverter_eff_vmax['Point_8'].split(",")[1]),
]

p_dc_min = [
float(inverter_eff_vmin['Point_1'].split(",")[0]),
float(inverter_eff_vmin['Point_2'].split(",")[0]),
float(inverter_eff_vmin['Point_3'].split(",")[0]),
float(inverter_eff_vmin['Point_4'].split(",")[0]),
float(inverter_eff_vmin['Point_5'].split(",")[0]),
float(inverter_eff_vmin['Point_6'].split(",")[0]),
float(inverter_eff_vmin['Point_7'].split(",")[0]),
float(inverter_eff_vmin['Point_8'].split(",")[0]),
]

p_dc_nom = [
float(inverter_eff_vnom['Point_1'].split(",")[0]),
float(inverter_eff_vnom['Point_2'].split(",")[0]),
float(inverter_eff_vnom['Point_3'].split(",")[0]),
float(inverter_eff_vnom['Point_4'].split(",")[0]),
float(inverter_eff_vnom['Point_5'].split(",")[0]),
float(inverter_eff_vnom['Point_6'].split(",")[0]),
float(inverter_eff_vnom['Point_7'].split(",")[0]),
float(inverter_eff_vnom['Point_8'].split(",")[0]),
]

p_dc_max = [
float(inverter_eff_vmax['Point_1'].split(",")[0]),
float(inverter_eff_vmax['Point_2'].split(",")[0]),
float(inverter_eff_vmax['Point_3'].split(",")[0]),
float(inverter_eff_vmax['Point_4'].split(",")[0]),
float(inverter_eff_vmax['Point_5'].split(",")[0]),
float(inverter_eff_vmax['Point_6'].split(",")[0]),
float(inverter_eff_vmax['Point_7'].split(",")[0]),
float(inverter_eff_vmax['Point_8'].split(",")[0]),
]

ac_power = np.array(p_ac_min + p_ac_nom + p_ac_max)
dc_power = np.array(p_dc_min + p_dc_nom + p_dc_max)



# save all necessary inverter data to a dictionary
sandia_params = {
"ac_power": ac_power,
"dc_power": dc_power,
"dc_voltage": np.array(dc_voltage[0] * 8 + dc_voltage[1] * 8 + dc_voltage[2] * 8),
"dc_voltage_level": np.array(["Vmin"] * 8 + ["Vnom"] * 8 + ["Vmax"] * 8),
"p_ac_0": inverter_power,
"p_nt": p_nt
}

inv_sandia_params = pvlib.inverter.fit_sandia(
sandia_params['ac_power'],
sandia_params['dc_power'],
sandia_params['dc_voltage'],
sandia_params['dc_voltage_level'],
sandia_params['p_ac_0'],
sandia_params['p_nt']
)

inverter_data = {
"name" : inverter_model,
"Vac": nominal_ac_voltage,
"Paco": nominal_ac_power,
"Vdco": nominal_dc_voltage,
"Pdco": nominal_dc_power,
"C0": inv_sandia_params['C0'],
"C1": inv_sandia_params['C1'],
"C2": inv_sandia_params['C2'],
"C3": inv_sandia_params['C3'],
"Pso": pso,
"Pnt": p_nt,
"Vdcmax": maximum_dc_voltage,
"Idcmax": maximum_dc_current,
"Mppt_low": mppt_low,
"Mppt_high": mppt_high
}

Sorry for the ugly code. I'm not a great pythonic writer. :/

When I run the results,

Inverter AC Output (PVLIB_FIT_SANDIA) : 70,208.8kWh
Inverter AC Output (SANDIA_DATABASE) : 76,522.8kWh
Inverter AC Output (PVSYST_ITSELF) : 76,672.5kWh

The values provided from the CEC database and the OND file attached run using PVSYST are very close. But the CEC parameters I fit using the function is way off.

My point is; there are many inverters are coming up every month and we only have access to a one-page datasheet. I've read comments on https://github.com/pvlib/pvlib-python/issues/1002 which are very useful but I don't obsess over being very PVSYST close but a model that can work out of the box just using the data from the datasheet would be useful (like PVWATTS).

Best, 

--
Orçun Başlak
Huawei_Sun2000_40KTL_US_SLR.OND

Will Hobbs

unread,
Oct 2, 2023, 4:41:47 PM10/2/23
to pvlib-python
Would it be possible to share code with a full working example?

Orçun Başlak

unread,
Oct 8, 2023, 12:36:08 PM10/8/23
to pvlib-python
Sure,

You can find the files attached. Please put *.pkl, *.OND and *.CSV to /data/ folder.
You need to manually install PVSYST tools for parsing OND files. (Currenty .iotools.read_panond() does not do some calculations needed by pvlib, it just parses so I'm not using it.)

pip install pvsyst_tools/

Thank you,
ArrayDCData.pkl
Project_PVSYST_Output.CSV
inverter.py
Huawei_Sun2000_40KTL_US_SLR.OND

Solar PV World

unread,
Oct 10, 2023, 1:01:11 PM10/10/23
to Orçun Başlak, pvlib-python
Hello Orcum Baslak,
Hope you are doing well!
Could please share this project details and code with us do the practice, I am very much interested and want to learn more about the same

It would be great to share this information from scratch to get clear idea

Thank you!

Regards
Mahesh Kawarkhe 

Thanking you






--
You received this message because you are subscribed to the Google Groups "pvlib-python" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pvlib-python...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pvlib-python/44559a99-73b4-4017-97ba-add37085ebd1n%40googlegroups.com.

cwh...@sandia.gov

unread,
Oct 10, 2023, 1:15:33 PM10/10/23
to pvlib-python
Orçun,

I think these two lines are in error:

# calculate dc power

# calculate dc power
inverter_power = float(inverter_parameters['pvGInverter']['TConverter']['PMaxOUT'])

should be

inverter_power = nominal_ac_power

Because inverter_power is later mapped to P_ac_0 when input to the fit_sandia function.

and

inverter_ac_output = pvlib.inverter.sandia(array_dc_data['v_mp'], array_dc_data['p_mp'], inverter_data)

should be

inverter_ac_output = pvlib.inverter.sandia(array_dc_data['v_mp'], array_dc_data['p_mp'], inv_sandia_params)

With these changes I get 

#######
Inverter AC Output (PVLIB_FIT_SANDIA) : 76,533.6kWh
#######

#######

Inverter AC Output (SANDIA_DATABASE) : 76,522.8kWh
#######

#######
Inverter AC Output (PVSYST) : 76,672.5kWh
#######

I'll note that the Pnt parameter for the Sandia model is in the OND file, as Pseuil. I don't know what the unit is, I'd guess W.

Best,

Cliff

Orçun Başlak

unread,
Oct 15, 2023, 8:12:20 AM10/15/23
to pvlib-python
Hello Cliff,

Your solution works. The main issue is the nominal power being set to maximum PV power. Now it is fixed.

I think this code can be integrated into pvlib as an OND -> Sandia reader. 

I'm not good with using Git. Maybe someone knows how to can add it as get_sandia_parameters_from_ond(filepath) ?

Thank you,

Message has been deleted

cwh...@sandia.gov

unread,
Oct 16, 2023, 9:52:28 AM10/16/23
to pvlib-python
I've already started, please take a look https://github.com/pvlib/pvlib-python/pull/1888
Your sample code filled in a few gaps and made this possible. Your comments and corrections are very welcome.
Best,
Cliff
Reply all
Reply to author
Forward
0 new messages