Skip to content

Commit 4a1dfab

Browse files
committed
deprecating pvsystem.singlediode ivcurve_pnts parameter
1 parent 30c62e3 commit 4a1dfab

File tree

3 files changed

+68
-61
lines changed

3 files changed

+68
-61
lines changed

docs/examples/iv-modeling/plot_singlediode.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# :py:meth:`pvlib.pvsystem.singlediode` is then used to generate the IV curves.
3333

3434
from pvlib import pvsystem
35+
import numpy as np
3536
import pandas as pd
3637
import matplotlib.pyplot as plt
3738

@@ -88,26 +89,27 @@
8889
)
8990

9091
# plug the parameters into the SDE and solve for IV curves:
91-
curve_info = pvsystem.singlediode(
92-
photocurrent=IL,
93-
saturation_current=I0,
94-
resistance_series=Rs,
95-
resistance_shunt=Rsh,
96-
nNsVth=nNsVth,
97-
ivcurve_pnts=100,
98-
method='lambertw'
99-
)
92+
SDE_params = {
93+
'photocurrent': IL,
94+
'saturation_current': I0,
95+
'resistance_series': Rs,
96+
'resistance_shunt': Rsh,
97+
'nNsVth': nNsVth
98+
}
99+
curve_info = pvsystem.singlediode(method='lambertw', **SDE_params)
100+
v = pd.DataFrame(np.linspace(0., curve_info['v_oc'], 100))
101+
i = pd.DataFrame(pvsystem.i_from_v(voltage=v, method='lambertw', **SDE_params))
100102

101103
# plot the calculated curves:
102104
plt.figure()
103-
for i, case in conditions.iterrows():
105+
for idx, case in conditions.iterrows():
104106
label = (
105107
"$G_{eff}$ " + f"{case['Geff']} $W/m^2$\n"
106108
"$T_{cell}$ " + f"{case['Tcell']} $\\degree C$"
107109
)
108-
plt.plot(curve_info['v'][i], curve_info['i'][i], label=label)
109-
v_mp = curve_info['v_mp'][i]
110-
i_mp = curve_info['i_mp'][i]
110+
plt.plot(v[idx], i[idx], label=label)
111+
v_mp = curve_info['v_mp'][idx]
112+
i_mp = curve_info['i_mp'][idx]
111113
# mark the MPP
112114
plt.plot([v_mp], [i_mp], ls='', marker='o', c='k')
113115

pvlib/pvsystem.py

+50-48
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from abc import ABC, abstractmethod
1717
from typing import Optional
1818

19-
from pvlib._deprecation import deprecated
19+
from pvlib._deprecation import deprecated, warn_deprecated
2020

2121
from pvlib import (atmosphere, iam, inverter, irradiance,
2222
singlediode as _singlediode, temperature)
@@ -2711,7 +2711,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
27112711
resistance_shunt, nNsVth, ivcurve_pnts=None,
27122712
method='lambertw'):
27132713
r"""
2714-
Solve the single-diode equation to obtain a photovoltaic IV curve.
2714+
Solve the single diode equation to obtain a photovoltaic IV curve.
27152715
27162716
Solves the single diode equation [1]_
27172717
@@ -2724,11 +2724,10 @@ def singlediode(photocurrent, saturation_current, resistance_series,
27242724
\frac{V + I R_s}{R_{sh}}
27252725
27262726
for :math:`I` and :math:`V` when given :math:`I_L, I_0, R_s, R_{sh},` and
2727-
:math:`n N_s V_{th}` which are described later. Returns a DataFrame
2728-
which contains the 5 points on the I-V curve specified in
2729-
[3]_. If all :math:`I_L, I_0, R_s, R_{sh},` and
2730-
:math:`n N_s V_{th}` are scalar, a single curve is returned, if any
2731-
are Series (of the same length), multiple IV curves are calculated.
2727+
:math:`n N_s V_{th}` which are described later. The five points on the I-V
2728+
curve specified in [3]_ are returned. If :math:`I_L, I_0, R_s, R_{sh},` and
2729+
:math:`n N_s V_{th}` are all scalars, a single curve is returned. If any
2730+
are array-like (of the same length), multiple IV curves are calculated.
27322731
27332732
The input parameters can be calculated from meteorological data using a
27342733
function for a single diode model, e.g.,
@@ -2766,35 +2765,33 @@ def singlediode(photocurrent, saturation_current, resistance_series,
27662765
Number of points in the desired IV curve. If None or 0, no points on
27672766
the IV curves will be produced.
27682767
2768+
.. deprecated:: 0.10.0
2769+
Use :py:func:`pvlib.pvsystem.v_from_i` and
2770+
:py:func:`pvlib.pvsystem.i_from_v` instead.
2771+
27692772
method : str, default 'lambertw'
27702773
Determines the method used to calculate points on the IV curve. The
27712774
options are ``'lambertw'``, ``'newton'``, or ``'brentq'``.
27722775
27732776
Returns
27742777
-------
2775-
OrderedDict or DataFrame
2776-
2777-
The returned dict-like object always contains the keys/columns:
2778-
2779-
* i_sc - short circuit current in amperes.
2780-
* v_oc - open circuit voltage in volts.
2781-
* i_mp - current at maximum power point in amperes.
2782-
* v_mp - voltage at maximum power point in volts.
2783-
* p_mp - power at maximum power point in watts.
2784-
* i_x - current, in amperes, at ``v = 0.5*v_oc``.
2785-
* i_xx - current, in amperes, at ``V = 0.5*(v_oc+v_mp)``.
2778+
dict or pandas.DataFrame
2779+
The returned dict-like object always contains the keys/columns:
27862780
2787-
If ivcurve_pnts is greater than 0, the output dictionary will also
2788-
include the keys:
2781+
* i_sc - short circuit current in amperes.
2782+
* v_oc - open circuit voltage in volts.
2783+
* i_mp - current at maximum power point in amperes.
2784+
* v_mp - voltage at maximum power point in volts.
2785+
* p_mp - power at maximum power point in watts.
2786+
* i_x - current, in amperes, at ``v = 0.5*v_oc``.
2787+
* i_xx - current, in amperes, at ``V = 0.5*(v_oc+v_mp)``.
27892788
2790-
* i - IV curve current in amperes.
2791-
* v - IV curve voltage in volts.
2789+
A dict is returned when the input parameters are scalars or
2790+
``ivcurve_pnts > 0``. If ``ivcurve_pnts > 0``, the output dictionary
2791+
will also include the keys:
27922792
2793-
The output will be an OrderedDict if photocurrent is a scalar,
2794-
array, or ivcurve_pnts is not None.
2795-
2796-
The output will be a DataFrame if photocurrent is a Series and
2797-
ivcurve_pnts is None.
2793+
* i - IV curve current in amperes.
2794+
* v - IV curve voltage in volts.
27982795
27992796
See also
28002797
--------
@@ -2841,22 +2838,25 @@ def singlediode(photocurrent, saturation_current, resistance_series,
28412838
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
28422839
https://doi.org/10.1016/0379-6787(88)90059-2
28432840
"""
2841+
if ivcurve_pnts:
2842+
warn_deprecated('0.10.0', name='pvlib.pvsystem.singlediode',
2843+
alternative=('pvlib.pvsystem.v_from_i and '
2844+
'pvlib.pvsystem.i_from_v'),
2845+
obj_type='parameter ivcurve_pnts',
2846+
removal='0.11.0')
2847+
args = (photocurrent, saturation_current, resistance_series,
2848+
resistance_shunt, nNsVth) # collect args
28442849
# Calculate points on the IV curve using the LambertW solution to the
28452850
# single diode equation
28462851
if method.lower() == 'lambertw':
2847-
out = _singlediode._lambertw(
2848-
photocurrent, saturation_current, resistance_series,
2849-
resistance_shunt, nNsVth, ivcurve_pnts
2850-
)
2851-
i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx = out[:7]
2852+
out = _singlediode._lambertw(*args, ivcurve_pnts)
2853+
points = out[:7]
28522854
if ivcurve_pnts:
28532855
ivcurve_i, ivcurve_v = out[7:]
28542856
else:
28552857
# Calculate points on the IV curve using either 'newton' or 'brentq'
28562858
# methods. Voltages are determined by first solving the single diode
28572859
# equation for the diode voltage V_d then backing out voltage
2858-
args = (photocurrent, saturation_current, resistance_series,
2859-
resistance_shunt, nNsVth) # collect args
28602860
v_oc = _singlediode.bishop88_v_from_i(
28612861
0.0, *args, method=method.lower()
28622862
)
@@ -2872,6 +2872,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
28722872
i_xx = _singlediode.bishop88_i_from_v(
28732873
(v_oc + v_mp) / 2.0, *args, method=method.lower()
28742874
)
2875+
points = i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx
28752876

28762877
# calculate the IV curve if requested using bishop88
28772878
if ivcurve_pnts:
@@ -2880,22 +2881,23 @@ def singlediode(photocurrent, saturation_current, resistance_series,
28802881
)
28812882
ivcurve_i, ivcurve_v, _ = _singlediode.bishop88(vd, *args)
28822883

2883-
out = OrderedDict()
2884-
out['i_sc'] = i_sc
2885-
out['v_oc'] = v_oc
2886-
out['i_mp'] = i_mp
2887-
out['v_mp'] = v_mp
2888-
out['p_mp'] = p_mp
2889-
out['i_x'] = i_x
2890-
out['i_xx'] = i_xx
2884+
columns = ('i_sc', 'v_oc', 'i_mp', 'v_mp', 'p_mp', 'i_x', 'i_xx')
28912885

2892-
if ivcurve_pnts:
2886+
if all(map(np.isscalar, args)) or ivcurve_pnts:
2887+
out = {c: p for c, p in zip(columns, points)}
2888+
2889+
if ivcurve_pnts:
2890+
out.update(i=ivcurve_i, v=ivcurve_v)
2891+
2892+
return out
2893+
2894+
points = np.atleast_1d(*points) # convert scalars to 1d-arrays
2895+
points = np.vstack(points).T # collect rows into DataFrame columns
28932896

2894-
out['v'] = ivcurve_v
2895-
out['i'] = ivcurve_i
2897+
# save the first available pd.Series index, otherwise set to None
2898+
index = next((a.index for a in args if isinstance(a, pd.Series)), None)
28962899

2897-
if isinstance(photocurrent, pd.Series) and not ivcurve_pnts:
2898-
out = pd.DataFrame(out, index=photocurrent.index)
2900+
out = pd.DataFrame(points, columns=columns, index=index)
28992901

29002902
return out
29012903

@@ -2936,7 +2938,7 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
29362938
29372939
Returns
29382940
-------
2939-
OrderedDict or pandas.Datafrane
2941+
OrderedDict or pandas.DataFrame
29402942
``(i_mp, v_mp, p_mp)``
29412943
29422944
Notes

pvlib/tools.py

+3
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ def _golden_sect_DataFrame(params, lower, upper, func, atol=1e-8):
377377
df['max'] = 0.5 * (df['V1'] + df['V2'])
378378
func_result = func(df, 'max')
379379
x = np.where(np.isnan(func_result), np.nan, df['max'])
380+
if np.isscalar(df['max']):
381+
# np.where always returns an ndarray, converting scalars to 0d-arrays
382+
x = x.item()
380383

381384
return func_result, x
382385

0 commit comments

Comments
 (0)