Skip to content

pvlib.pvsystem.singlediode: remove deprecated ivcurve_pnts parameter #2101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 21, 2024
Merged
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
3 changes: 3 additions & 0 deletions docs/sphinx/source/whatsnew/v0.11.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Breaking changes
* :py:func:`~pvlib.iotools.get_psm3`, :py:func:`~pvlib.iotools.read_psm3`, and
:py:func:`~pvlib.iotools.parse_psm3` all now have ``map_variables=True`` by
default. (:issue:`1425`, :pull:`2094`)
* The deprecated ``ivcurve_pnts`` parameter of :py:func:`pvlib.pvsystem.singlediode`
is removed. Use :py:func:`pvlib.pvsystem.v_from_i` and
:py:func:`pvlib.pvsystem.i_from_v` instead. (:pull:`2101`)


Deprecations
Expand Down
54 changes: 6 additions & 48 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,15 +722,13 @@ def _spectral_correction(array, pw):
)

def singlediode(self, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
ivcurve_pnts=None):
resistance_series, resistance_shunt, nNsVth):
"""Wrapper around the :py:func:`pvlib.pvsystem.singlediode` function.

See :py:func:`pvsystem.singlediode` for details
"""
return singlediode(photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth,
ivcurve_pnts=ivcurve_pnts)
resistance_series, resistance_shunt, nNsVth)

def i_from_v(self, voltage, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth):
Expand Down Expand Up @@ -2352,8 +2350,7 @@ 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, method='lambertw'):
r"""
Solve the single diode equation to obtain a photovoltaic IV curve.

Expand Down Expand Up @@ -2405,14 +2402,6 @@ def singlediode(photocurrent, saturation_current, resistance_series,
junction in Kelvin, and :math:`q` is the charge of an electron
(coulombs). ``0 < nNsVth``. [V]

ivcurve_pnts : int, optional
Number of points in the desired IV curve. If not specified or 0, no
points on the IV curves will be produced.

.. deprecated:: 0.10.0
Use :py:func:`pvlib.pvsystem.v_from_i` and
:py:func:`pvlib.pvsystem.i_from_v` instead.

method : str, default 'lambertw'
Determines the method used to calculate points on the IV curve. The
options are ``'lambertw'``, ``'newton'``, or ``'brentq'``.
Expand All @@ -2430,12 +2419,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
* i_x - current, in amperes, at ``v = 0.5*v_oc``.
* i_xx - current, in amperes, at ``v = 0.5*(v_oc+v_mp)``.

A dict is returned when the input parameters are scalars or
``ivcurve_pnts > 0``. If ``ivcurve_pnts > 0``, the output dictionary
will also include the keys:

* i - IV curve current in amperes.
* v - IV curve voltage in volts.
A dict is returned when the input parameters are scalars.

See also
--------
Expand All @@ -2459,13 +2443,6 @@ def singlediode(photocurrent, saturation_current, resistance_series,
that guarantees convergence by bounding the voltage between zero and
open-circuit.

If the method is either ``'newton'`` or ``'brentq'`` and ``ivcurve_pnts``
are indicated, then :func:`pvlib.singlediode.bishop88` [4]_ is used to
calculate the points on the IV curve points at diode voltages from zero to
open-circuit voltage with a log spacing that gets closer as voltage
increases. If the method is ``'lambertw'`` then the calculated points on
the IV curve are linearly spaced.

References
----------
.. [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN
Expand All @@ -2482,21 +2459,13 @@ def singlediode(photocurrent, saturation_current, resistance_series,
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
https://doi.org/10.1016/0379-6787(88)90059-2
"""
if ivcurve_pnts:
warn_deprecated('0.10.0', name='pvlib.pvsystem.singlediode',
alternative=('pvlib.pvsystem.v_from_i and '
'pvlib.pvsystem.i_from_v'),
obj_type='parameter ivcurve_pnts',
removal='0.11.0')
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) # collect args
# Calculate points on the IV curve using the LambertW solution to the
# single diode equation
if method.lower() == 'lambertw':
out = _singlediode._lambertw(*args, ivcurve_pnts)
out = _singlediode._lambertw(*args)
points = out[:7]
if ivcurve_pnts:
ivcurve_i, ivcurve_v = out[7:]
else:
# Calculate points on the IV curve using either 'newton' or 'brentq'
# methods. Voltages are determined by first solving the single diode
Expand All @@ -2518,21 +2487,10 @@ def singlediode(photocurrent, saturation_current, resistance_series,
)
points = i_sc, v_oc, i_mp, v_mp, p_mp, i_x, i_xx

# calculate the IV curve if requested using bishop88
if ivcurve_pnts:
vd = v_oc * (
(11.0 - np.logspace(np.log10(11.0), 0.0, ivcurve_pnts)) / 10.0
)
ivcurve_i, ivcurve_v, _ = _singlediode.bishop88(vd, *args)

columns = ('i_sc', 'v_oc', 'i_mp', 'v_mp', 'p_mp', 'i_x', 'i_xx')

if all(map(np.isscalar, args)) or ivcurve_pnts:
if all(map(np.isscalar, args)):
out = {c: p for c, p in zip(columns, points)}

if ivcurve_pnts:
out.update(i=ivcurve_i, v=ivcurve_v)

return out

points = np.atleast_1d(*points) # convert scalars to 1d-arrays
Expand Down
44 changes: 8 additions & 36 deletions pvlib/tests/test_pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import pandas as pd

import pytest
from .conftest import (
assert_series_equal, assert_frame_equal, fail_on_pvlib_version)
from .conftest import assert_series_equal, assert_frame_equal
from numpy.testing import assert_allclose
import unittest.mock as mock

Expand Down Expand Up @@ -1568,27 +1567,21 @@ def test_singlediode_floats():
assert_allclose(v, expected[k], atol=1e-6)


def test_singlediode_floats_ivcurve():
with pytest.warns(pvlibDeprecationWarning, match='ivcurve_pnts'):
out = pvsystem.singlediode(7., 6e-7, .1, 20., .5, ivcurve_pnts=3,
method='lambertw')
def test_singlediode_floats_expected():
out = pvsystem.singlediode(7., 6e-7, .1, 20., .5, method='lambertw')
expected = {'i_xx': 4.264060478,
'i_mp': 6.136267360,
'v_oc': 8.106300147,
'p_mp': 38.19421055,
'i_x': 6.7558815684,
'i_sc': 6.965172322,
'v_mp': 6.224339375,
'i': np.array([
6.965172322, 6.755881568, 2.664535259e-14]),
'v': np.array([
0., 4.053150073, 8.106300147])}
'v_mp': 6.224339375}
assert isinstance(out, dict)
for k, v in out.items():
assert_allclose(v, expected[k], atol=1e-6)


def test_singlediode_series_ivcurve(cec_module_params):
def test_singlediode_series_expected(cec_module_params):
times = pd.date_range(start='2015-06-01', periods=3, freq='6h')
effective_irradiance = pd.Series([0.0, 400.0, 800.0], index=times)
IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
Expand All @@ -1603,51 +1596,30 @@ def test_singlediode_series_ivcurve(cec_module_params):
EgRef=1.121,
dEgdT=-0.0002677)

with pytest.warns(pvlibDeprecationWarning, match='ivcurve_pnts'):
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, ivcurve_pnts=3,
method='lambertw')
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, method='lambertw')

expected = OrderedDict([('i_sc', array([0., 3.01079860, 6.00726296])),
('v_oc', array([0., 9.96959733, 10.29603253])),
('i_mp', array([0., 2.656285960, 5.290525645])),
('v_mp', array([0., 8.321092255, 8.409413795])),
('p_mp', array([0., 22.10320053, 44.49021934])),
('i_x', array([0., 2.884132006, 5.746202281])),
('i_xx', array([0., 2.052691562, 3.909673879])),
('v', array([[0., 0., 0.],
[0., 4.984798663, 9.969597327],
[0., 5.148016266, 10.29603253]])),
('i', array([[0., 0., 0.],
[3.0107985972, 2.8841320056, 0.],
[6.0072629615, 5.7462022810, 0.]]))])
('i_xx', array([0., 2.052691562, 3.909673879]))])

for k, v in out.items():
assert_allclose(v, expected[k], atol=1e-2)

with pytest.warns(pvlibDeprecationWarning, match='ivcurve_pnts'):
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth, ivcurve_pnts=3)
out = pvsystem.singlediode(IL, I0, Rs, Rsh, nNsVth)

expected['i_mp'] = pvsystem.i_from_v(out['v_mp'], IL, I0, Rs, Rsh, nNsVth,
method='lambertw')
expected['v_mp'] = pvsystem.v_from_i(out['i_mp'], IL, I0, Rs, Rsh, nNsVth,
method='lambertw')
expected['i'] = pvsystem.i_from_v(out['v'].T, IL, I0, Rs, Rsh, nNsVth,
method='lambertw').T
expected['v'] = pvsystem.v_from_i(out['i'].T, IL, I0, Rs, Rsh, nNsVth,
method='lambertw').T

for k, v in out.items():
assert_allclose(v, expected[k], atol=1e-6)


@fail_on_pvlib_version('0.11')
@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton'])
def test_singlediode_ivcurvepnts_deprecation_warning(method):
with pytest.warns(pvlibDeprecationWarning, match='ivcurve_pnts'):
pvsystem.singlediode(7., 6e-7, .1, 20., .5, ivcurve_pnts=3,
method=method)


def test_scale_voltage_current_power():
data = pd.DataFrame(
np.array([[2, 1.5, 10, 8, 12, 0.5, 1.5]]),
Expand Down
19 changes: 0 additions & 19 deletions pvlib/tests/test_singlediode.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from pvlib import pvsystem
from pvlib.singlediode import (bishop88_mpp, estimate_voc, VOLTAGE_BUILTIN,
bishop88, bishop88_i_from_v, bishop88_v_from_i)
from pvlib._deprecation import pvlibDeprecationWarning
import pytest
from numpy.testing import assert_array_equal
from .conftest import DATA_DIR
Expand Down Expand Up @@ -188,24 +187,6 @@ def test_singlediode_lambert_negative_voc(mocker):
assert_array_equal(outs["v_oc"], [0, 0])


@pytest.mark.parametrize('method', ['lambertw'])
def test_ivcurve_pnts_precision(method, precise_iv_curves):
"""
Tests the accuracy of the IV curve points calcuated by singlediode. Only
methods of singlediode that linearly spaced points are tested.
"""
x, pc = precise_iv_curves
pc_i, pc_v = np.stack(pc['Currents']), np.stack(pc['Voltages'])
ivcurve_pnts = len(pc['Currents'][0])

with pytest.warns(pvlibDeprecationWarning, match='ivcurve_pnts'):
outs = pvsystem.singlediode(method=method, ivcurve_pnts=ivcurve_pnts,
**x)

assert np.allclose(pc_i, outs['i'], atol=1e-10, rtol=0)
assert np.allclose(pc_v, outs['v'], atol=1e-10, rtol=0)


@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton'])
def test_v_from_i_i_from_v_precision(method, precise_iv_curves):
"""
Expand Down
Loading