Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1563,9 +1563,13 @@ def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times):
"""
if use_delta_kt_prime:
# Perez eqn 2
delta_kt_prime = 0.5*((kt_prime - kt_prime.shift(1)).abs().add(
(kt_prime - kt_prime.shift(-1)).abs(),
fill_value=0))
kt_next = kt_prime.shift(-1)
kt_previous = kt_prime.shift(1)
kt_next.iloc[-1] = kt_previous.iloc[-1]
kt_previous.iloc[0] = kt_next.iloc[0]
delta_kt_prime = 0.5 * ((kt_prime - kt_next).abs().add(
(kt_prime - kt_previous).abs(),
fill_value=0))
else:
# do not change unless also modifying _dirint_bins
delta_kt_prime = pd.Series(-1, index=times)
Expand Down
63 changes: 52 additions & 11 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ def _infer_cell_type(self):

def singlediode(self, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
ivcurve_pnts=None):
d2mutau=0, NsVbi=np.Inf, ivcurve_pnts=None):
"""Wrapper around the :py:func:`singlediode` function.

Parameters
Expand All @@ -613,7 +613,7 @@ def singlediode(self, photocurrent, saturation_current,
"""
return singlediode(photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
ivcurve_pnts=ivcurve_pnts)
d2mutau, NsVbi, ivcurve_pnts=ivcurve_pnts)

def i_from_v(self, resistance_shunt, resistance_series, nNsVth, voltage,
saturation_current, photocurrent):
Expand Down Expand Up @@ -2113,8 +2113,8 @@ def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,


def singlediode(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, ivcurve_pnts=None,
method='lambertw'):
resistance_shunt, nNsVth, d2mutau=0, NsVbi=np.Inf,
ivcurve_pnts=None, method='lambertw'):
"""
Solve the single-diode model to obtain a photovoltaic IV curve.

Expand Down Expand Up @@ -2166,6 +2166,16 @@ def singlediode(photocurrent, saturation_current, resistance_series,
q is the charge of an electron (coulombs).
0 < nNsVth

d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]

NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``

ivcurve_pnts : None or int, default None
Number of points in the desired IV curve. If None or 0, no
IV curves will be produced.
Expand Down Expand Up @@ -2258,7 +2268,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
# methods. Voltages are determined by first solving the single diode
# equation for the diode voltage V_d then backing out voltage
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) # collect args
resistance_shunt, nNsVth, d2mutau, NsVbi) # collect args
v_oc = _singlediode.bishop88_v_from_i(
0.0, *args, method=method.lower()
)
Expand Down Expand Up @@ -2304,7 +2314,8 @@ def singlediode(photocurrent, saturation_current, resistance_series,


def max_power_point(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method='brentq'):
resistance_shunt, nNsVth, d2mutau=0, NsVbi=np.Inf,
method='brentq'):
"""
Given the single diode equation coefficients, calculates the maximum power
point (MPP).
Expand All @@ -2322,6 +2333,14 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
nNsVth : numeric
product of thermal voltage ``Vth`` [V], diode ideality factor ``n``,
and number of serices cells ``Ns``
d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]
NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``
method : str
either ``'newton'`` or ``'brentq'``

Expand All @@ -2339,7 +2358,7 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
"""
i_mp, v_mp, p_mp = _singlediode.bishop88_mpp(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method=method.lower()
resistance_shunt, nNsVth, d2mutau, NsVbi, method=method.lower()
)
if isinstance(photocurrent, pd.Series):
ivp = {'i_mp': i_mp, 'v_mp': v_mp, 'p_mp': p_mp}
Expand All @@ -2353,7 +2372,8 @@ def max_power_point(photocurrent, saturation_current, resistance_series,


def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
saturation_current, photocurrent, method='lambertw'):
saturation_current, photocurrent, d2mutau=0, NsVbi=np.Inf,
method='lambertw'):
'''
Device voltage at the given device current for the single diode model.

Expand Down Expand Up @@ -2402,6 +2422,16 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
IV curve conditions. Often abbreviated ``I_L``.
0 <= photocurrent

d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]

NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``

method : str
Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
``'brentq'`` is limited to 1st quadrant only.
Expand All @@ -2426,7 +2456,7 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
# methods. Voltages are determined by first solving the single diode
# equation for the diode voltage V_d then backing out voltage
args = (current, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth)
resistance_series, resistance_shunt, nNsVth, d2mutau, NsVbi)
V = _singlediode.bishop88_v_from_i(*args, method=method.lower())
# find the right size and shape for returns
size, shape = _singlediode._get_size_and_shape(args)
Expand All @@ -2441,7 +2471,8 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,


def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
saturation_current, photocurrent, method='lambertw'):
saturation_current, photocurrent, d2mutau=0,
NsVbi=np.Inf, method='lambertw'):
'''
Device current at the given device voltage for the single diode model.

Expand Down Expand Up @@ -2490,6 +2521,16 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
IV curve conditions. Often abbreviated ``I_L``.
0 <= photocurrent

d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]

NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``

method : str
Method to use: ``'lambertw'``, ``'newton'``, or ``'brentq'``. *Note*:
``'brentq'`` is limited to 1st quadrant only.
Expand All @@ -2514,7 +2555,7 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
# methods. Voltages are determined by first solving the single diode
# equation for the diode voltage V_d then backing out voltage
args = (voltage, photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
resistance_shunt, nNsVth, d2mutau, NsVbi)
I = _singlediode.bishop88_i_from_v(*args, method=method.lower())
# find the right size and shape for returns
size, shape = _singlediode._get_size_and_shape(args)
Expand Down
46 changes: 38 additions & 8 deletions pvlib/singlediode.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ def bishop88(diode_voltage, photocurrent, saturation_current,
available technology", André Mermoud and Thibault Lejeune, 25th EUPVSEC,
2010
:doi:`10.4229/25thEUPVSEC2010-4BV.1.114`

[4] K. J. Sauer, T. Roessler, C. W. Hansen, Modeling the Irradiance
and Temperature Dependence of Photovoltaic Modules in PVsyst, J. of
Photovoltaics 5(1), Jan. 2015.
:doi:`10.1109/JPHOTOV.2014.2364133`
"""
# calculate recombination loss current where d2mutau > 0
is_recomb = d2mutau > 0 # True where there is thin-film recombination loss
Expand Down Expand Up @@ -172,8 +177,8 @@ def bishop88(diode_voltage, photocurrent, saturation_current,


def bishop88_i_from_v(voltage, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
method='newton'):
resistance_series, resistance_shunt, nNsVth, d2mutau=0,
NsVbi=np.Inf, method='newton'):
"""
Find current given any voltage.

Expand All @@ -192,6 +197,14 @@ def bishop88_i_from_v(voltage, photocurrent, saturation_current,
nNsVth : numeric
product of diode ideality factor (n), number of series cells (Ns), and
thermal voltage (Vth = k_b * T / q_e) in volts [V]
d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]
NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``
method : str
one of two optional search methods: either ``'brentq'``, a reliable and
bounded method or ``'newton'`` which is the default.
Expand All @@ -203,7 +216,7 @@ def bishop88_i_from_v(voltage, photocurrent, saturation_current,
"""
# collect args
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
resistance_shunt, nNsVth, d2mutau, NsVbi)

def fv(x, v, *a):
# calculate voltage residual given diode voltage "x"
Expand Down Expand Up @@ -234,8 +247,8 @@ def vd_from_brent(voc, v, iph, isat, rs, rsh, gamma):


def bishop88_v_from_i(current, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
method='newton'):
resistance_series, resistance_shunt, nNsVth, d2mutau=0,
NsVbi=np.Inf, method='newton'):
"""
Find voltage given any current.

Expand All @@ -251,6 +264,14 @@ def bishop88_v_from_i(current, photocurrent, saturation_current,
series resistance (Rs) in ohms
resistance_shunt : numeric
shunt resistance (Rsh) in ohms
d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]
NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``
nNsVth : numeric
product of diode ideality factor (n), number of series cells (Ns), and
thermal voltage (Vth = k_b * T / q_e) in volts [V]
Expand All @@ -265,7 +286,7 @@ def bishop88_v_from_i(current, photocurrent, saturation_current,
"""
# collect args
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
resistance_shunt, nNsVth, d2mutau, NsVbi)
# first bound the search using voc
voc_est = estimate_voc(photocurrent, saturation_current, nNsVth)

Expand Down Expand Up @@ -295,7 +316,8 @@ def vd_from_brent(voc, i, iph, isat, rs, rsh, gamma):


def bishop88_mpp(photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method='newton'):
resistance_shunt, nNsVth, d2mutau=0, NsVbi=np.Inf,
method='newton'):
"""
Find max power point.

Expand All @@ -312,6 +334,14 @@ def bishop88_mpp(photocurrent, saturation_current, resistance_series,
nNsVth : numeric
product of diode ideality factor (n), number of series cells (Ns), and
thermal voltage (Vth = k_b * T / q_e) in volts [V]
d2mutau : numeric
PVSyst thin-film recombination parameter that is the ratio of thickness
of the intrinsic layer squared :math:`d^2` and the diffusion length of
charge carriers :math:`\\mu \\tau`, in volts [V], defaults to 0[V]
NsVbi : numeric
PVSyst thin-film recombination parameter that is the product of the PV
module number of series cells ``Ns`` and the builtin voltage ``Vbi`` of
the intrinsic layer, in volts [V], defaults to ``np.inf``
method : str
one of two optional search methods: either ``'brentq'``, a reliable and
bounded method or ``'newton'`` which is the default.
Expand All @@ -324,7 +354,7 @@ def bishop88_mpp(photocurrent, saturation_current, resistance_series,
"""
# collect args
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
resistance_shunt, nNsVth, d2mutau, NsVbi)
# first bound the search using voc
voc_est = estimate_voc(photocurrent, saturation_current, nNsVth)

Expand Down
18 changes: 9 additions & 9 deletions pvlib/test/test_irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,13 +466,13 @@ def test_dirint_value():
pressure = 93193.
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure)
assert_almost_equal(dirint_data.values,
np.array([ 888. , 683.7]), 1)
np.array([868.8, 699.7]), 1)


def test_dirint_nans():
times = pd.DatetimeIndex(start='2014-06-24T12-0700', periods=5, freq='6H')
ghi = pd.Series([np.nan, 1038.62, 1038.62, 1038.62, 1038.62], index=times)
zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567,], index=times)
zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567], index=times)
pressure = pd.Series([93193., 93193., np.nan, 93193., 93193.], index=times)
temp_dew = pd.Series([10, 10, 10, np.nan, 10], index=times)
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
Expand All @@ -489,7 +489,7 @@ def test_dirint_tdew():
dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
temp_dew=10)
assert_almost_equal(dirint_data.values,
np.array([892.9, 636.5]), 1)
np.array([882.1, 672.6]), 1)


def test_dirint_no_delta_kt():
Expand Down Expand Up @@ -559,7 +559,7 @@ def test_gti_dirint():
expected = pd.DataFrame(array(
[[ 21.05796198, 0. , 21.05796198],
[ 288.22574368, 60.59964218, 245.37532576],
[ 930.85454521, 695.8504884 , 276.96897609]]),
[ 931.04078010, 695.94965324, 277.06172442]]),
columns=expected_col_order, index=times)

assert_frame_equal(output, expected)
Expand All @@ -583,7 +583,7 @@ def test_gti_dirint():
expected = pd.DataFrame(array(
[[ 21.05796198, 0. , 21.05796198],
[ 289.81109139, 60.52460392, 247.01373353],
[ 932.22047435, 647.68716072, 323.59362885]]),
[ 932.46756378, 647.05001357, 323.49974813]]),
columns=expected_col_order, index=times)

assert_frame_equal(output, expected)
Expand All @@ -595,9 +595,9 @@ def test_gti_dirint():
albedo=albedo)

expected = pd.DataFrame(array(
[[ 21.3592591 , 0. , 21.3592591 ],
[ 292.5162373 , 64.42628826, 246.95997198],
[ 941.47847463, 727.07261187, 258.25370648]]),
[[ 21.3592591, 0. , 21.3592591 ],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

E203 whitespace before ','
E202 whitespace before ']'

[ 292.5162373, 64.42628826, 246.95997198],
[ 941.6753031, 727.16311901, 258.36548605]]),
columns=expected_col_order, index=times)

assert_frame_equal(output, expected)
Expand All @@ -611,7 +611,7 @@ def test_gti_dirint():
expected = pd.DataFrame(array(
[[ 21.05796198, 0. , 21.05796198],
[ 292.40468994, 36.79559287, 266.3862767 ],
[ 930.72198876, 712.36063132, 261.32196017]]),
[ 931.79627208, 689.81549269, 283.5817439]]),
columns=expected_col_order, index=times)

assert_frame_equal(output, expected)
Expand Down