Skip to content

Commit e24e62f

Browse files
committed
add SDM parameter estimation and key point functions
1 parent d8988c6 commit e24e62f

5 files changed

Lines changed: 151 additions & 6 deletions

File tree

docs/sphinx/source/reference/pv_modeling/sdm.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Functions relevant for single diode models.
1717
pvsystem.v_from_i
1818
pvsystem.max_power_point
1919
ivtools.sdm.pvsyst_temperature_coeff
20+
singlediode.batzelis_keypoints
2021

2122
Low-level functions for solving the single diode equation.
2223

@@ -37,3 +38,4 @@ Functions for fitting diode models
3738
ivtools.sde.fit_sandia_simple
3839
ivtools.sdm.fit_cec_sam
3940
ivtools.sdm.fit_desoto
41+
ivtools.sdm.fit_desoto_batzelis

pvlib/ivtools/sdm/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
fitting method.
55
"""
66

7+
from pvlib.ivtools.sdm.batzelis import ( # noqa: F401
8+
fit_desoto_batzelis,
9+
)
10+
711
from pvlib.ivtools.sdm.cec import ( # noqa: F401
812
fit_cec_sam,
913
)

pvlib/ivtools/sdm/batzelis.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
Batzelis's method for estimating single-diode model parameters from
3+
datasheet values.
4+
"""
5+
6+
import numpy as np
7+
from scipy.special import lambertw
8+
9+
10+
def fit_desoto_batzelis(isc0, voc0, imp0, vmp0, alpha_sc, beta_voc):
11+
"""
12+
Determine De Soto single-diode model parameters from datasheet values
13+
using Batzelis's method.
14+
15+
This method is described in Section II.C of [1]_.
16+
17+
Parameters
18+
----------
19+
isc0 : float
20+
Short-circuit current at STC. [A]
21+
voc0 : float
22+
Open-circuit voltage at STC. [V]
23+
imp0 : float
24+
Maximum power point current at STC. [A]
25+
vmp0 : float
26+
Maximum power point voltage at STC. [V]
27+
alpha_sc : float
28+
Short-circuit current temperature coefficient at STC. [1/K]
29+
beta_voc : float
30+
Open-circuit voltage temperature coefficient at STC. [1/K]
31+
32+
Returns
33+
-------
34+
dict
35+
The returned dict contains the keys:
36+
37+
* ``alpha_sc`` [A/K]
38+
* ``a_ref`` [V]
39+
* ``I_L_ref`` [A]
40+
* ``I_o_ref`` [A]
41+
* ``R_sh_ref`` [Ohm]
42+
* ``R_s`` [Ohm]
43+
44+
References
45+
----------
46+
.. [1] E. I. Batzelis, "Simple PV Performance Equations Theoretically Well
47+
Founded on the Single-Diode Model," Journal of Photovoltaics vol. 7,
48+
no. 5, pp. 1400-1409, Sep 2017, :doi:`10.1109/JPHOTOV.2017.2711431`
49+
"""
50+
t0 = 298.15 # K
51+
del0 = (1 - beta_voc * t0) / (50.1 - alpha_sc * t0) # Eq 9
52+
w0 = lambertw(np.exp(1/del0 + 1)).real
53+
54+
# Eqs 11-15
55+
a0 = del0 * voc0
56+
Rs0 = (a0 * (w0 - 1) - vmp0) / imp0
57+
Rsh0 = a0 * (w0 - 1) / (isc0 * (1 - 1/w0) - imp0)
58+
Iph0 = (1 + Rs0 / Rsh0) * isc0
59+
Isat0 = Iph0 * np.exp(-1/del0)
60+
61+
return {
62+
'alpha_sc': alpha_sc * isc0, # convert 1/K to A/K
63+
'a_ref': a0,
64+
'I_L_ref': Iph0,
65+
'I_o_ref': Isat0,
66+
'R_sh_ref': Rsh0,
67+
'R_s': Rs0,
68+
}

pvlib/pvarray.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,13 +429,13 @@ def batzelis(effective_irradiance, temp_cell,
429429
Returns
430430
-------
431431
dict
432-
The returned dict-like object always contains the keys/columns:
432+
The returned dict-like object contains the keys/columns:
433433
434-
* p_mp - power at maximum power point. [W]
435-
* i_mp - current at maximum power point. [A]
436-
* v_mp - voltage at maximum power point. [V]
437-
* i_sc - short circuit current. [A]
438-
* v_oc - open circuit voltage. [V]
434+
* ``p_mp`` - power at maximum power point. [W]
435+
* ``i_mp`` - current at maximum power point. [A]
436+
* ``v_mp`` - voltage at maximum power point. [V]
437+
* ``i_sc`` - short circuit current. [A]
438+
* ``v_oc`` - open circuit voltage. [V]
439439
440440
Notes
441441
-----
@@ -505,6 +505,7 @@ def batzelis(effective_irradiance, temp_cell,
505505
vmp = np.clip(vmp, a_min=0, a_max=None)
506506
voc = np.clip(voc, a_min=0, a_max=None)
507507

508+
# TODO return dataframe for is_pandas
508509
return {
509510
'p_mp': vmp * imp,
510511
'i_mp': imp,

pvlib/singlediode.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,3 +861,73 @@ def _pwr_optfcn(df, loc):
861861
df['resistance_shunt'], df['nNsVth'])
862862

863863
return current * df[loc]
864+
865+
866+
def batzelis_keypoints(photocurrent, saturation_current, resistance_series,
867+
resistance_shunt, nNsVth):
868+
"""
869+
Estimate maximum power, open-circuit, and short-circuit values
870+
using Batzelis's method.
871+
872+
This method is described in Section II.B of [1]_.
873+
874+
Parameters
875+
----------
876+
photocurrent : numeric
877+
Light-generated current. [A]
878+
879+
saturation_current : numeric
880+
Diode saturation current. [A]
881+
882+
resistance_series : numeric
883+
Series resistance. [Ohm]
884+
885+
resistance_shunt : numeric
886+
Shunt resistance. [Ohm]
887+
888+
nNsVth : numeric
889+
The product of the usual diode ideality factor (n, unitless),
890+
number of cells in series (Ns), and cell thermal voltage at
891+
specified effective irradiance and cell temperature. [V]
892+
893+
Returns
894+
-------
895+
dict
896+
The returned dict-like object contains the keys/columns:
897+
898+
* ``p_mp`` - power at maximum power point. [W]
899+
* ``i_mp`` - current at maximum power point. [A]
900+
* ``v_mp`` - voltage at maximum power point. [V]
901+
* ``i_sc`` - short circuit current. [A]
902+
* ``v_oc`` - open circuit voltage. [V]
903+
904+
References
905+
----------
906+
.. [1] E. I. Batzelis, "Simple PV Performance Equations Theoretically Well
907+
Founded on the Single-Diode Model," Journal of Photovoltaics vol. 7,
908+
no. 5, pp. 1400-1409, Sep 2017, :doi:`10.1109/JPHOTOV.2017.2711431`
909+
"""
910+
# convenience variables
911+
Iph = photocurrent
912+
Is = saturation_current
913+
Rsh = resistance_shunt
914+
Rs = resistance_series
915+
a = nNsVth
916+
917+
# Eqs 3-4
918+
isc = Iph * Rsh / (Rs + Rsh)
919+
voc = a * np.log(Iph / Is)
920+
921+
# Eqs 5-8
922+
w = lambertw(np.e * Iph / Is).real
923+
#vmp = (1 + Rs/Rsh) * a * (w - 1) - Rs * Iph * (1 - 1/w) # not needed
924+
imp = Iph * (1 - 1/w) - a * (w - 1) / Rsh
925+
vmp = a * (w - 1) - Rs * imp
926+
927+
return {
928+
'p_mp': imp * vmp,
929+
'i_mp': imp,
930+
'v_mp': vmp,
931+
'i_sc': isc,
932+
'v_oc': voc,
933+
}

0 commit comments

Comments
 (0)