Skip to content

MAINT: DOC: rename singlediode module, and clean up docstring for singlediode function #525

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 5 commits into from
Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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: 5 additions & 5 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,11 @@ Low-level functions for solving the single diode equation.
.. autosummary::
:toctree: generated/

singlediode_methods.estimate_voc
singlediode_methods.bishop88
singlediode_methods.bishop88_i_from_v
singlediode_methods.bishop88_v_from_i
singlediode_methods.bishop88_mpp
singlediode.estimate_voc
singlediode.bishop88
singlediode.bishop88_i_from_v
singlediode.bishop88_v_from_i
singlediode.bishop88_mpp

SAPM model
----------
Expand Down
1 change: 1 addition & 0 deletions docs/sphinx/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Contents
api
comparison_pvlib_matlab
variables_style_rules
singlediode


Indices and tables
Expand Down
104 changes: 104 additions & 0 deletions docs/sphinx/source/singlediode.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
.. _singlediode:
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding this! Perhaps it deserves its own note in the whatsnew document.

Didn't you make something else (a wiki?) with more information that might belong here?

Copy link
Member

Choose a reason for hiding this comment

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

Are you set up to get readthedocs to render this version? It's pretty easy to do if you're not. Always nice to see that it works when making bigger documentation changes. If you've rendered locally and say it looks good then ok with me.

Copy link
Member Author

@mikofski mikofski Aug 9, 2018

Choose a reason for hiding this comment

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

Yes, there is a wiki on cell model solutions, but in order to close #518, I just need to move the section on bishop88() out of singlediode(), so I would like to open a separate documentation issue/pr to address moving the material appropriate from the wiki to the documents, and perhaps augmenting that with more detail as needed. Is this okay?

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ added note under documentation in what's new:

Added section on single diode equation with some detail on solutions used in
pvlib-python (:issue:518)

Copy link
Member

Choose a reason for hiding this comment

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

yes, that's ok with me.


Single Diode Model
==================

This section reviews the solutions to the single diode model used in
Copy link
Member

Choose a reason for hiding this comment

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

solutions to the single diode equation here and elsewhere. Let's use "Single diode equation" when we are referring to the equation that describes a single IV curve, and "single diode model" when we are referring to the set of equations (one of which is the single diode equation) that describe IV curves at any irradiance and temperature condtion (e.g., PVsyst is a single diode model).

These are my preferred terms, and the meaning of 'model' can be debated at length without adding value. I'm pushing here for consistency and hopefully, clarity.

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ agreed, I changed all references for now to single diode equations, since I don't discuss any single diode models here yet eg: PVSyst or DeSoto

pvlib-python to generate an IV curve of a PV module.

pvlib-python supports two ways to solve the single diode model, by passing the
a ``method`` keyword to the :func:`pvlib.pvsystem.singlediode` function:
Copy link
Member

Choose a reason for hiding this comment

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

I suggest something like...

pvlib-python supports two ways to solve the single diode model:

The :func:pvlib.pvsystem.singlediode function allows the user to choose the method using the method keyword.

Copy link
Member

Choose a reason for hiding this comment

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

Agree with @wholmgren here

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ nice change thx!


1. Lambert W-Function
2. Bishop's Algorithm

Lambert W-Function
------------------
When ``method='lambertw'``, the Lambert W-function is used as previously shown
by Jain and Kapoor [1, 2]. The following algorithm can be found on
`Wikipedia: Theory of Solar Cells
<https://en.wikipedia.org/wiki/Theory_of_solar_cells>`_, given the basic single
diode model equation.

.. math::

I = I_L - I_0 \left(\exp \left(\frac{\left(V + I R_s \right)}{n Ns V_{th}} \right) - 1 \right)
- \frac{\left(V + I R_s \right)}{R_{sh}}

Lambert W-function is the inverse of the function
:math:`f \left( w \right) = w \exp \left( w \right)` or
:math:`w = f^{-1} \left( w \exp \left( w \right) \right)` also given as
:math:`w = W \left( w \exp \left( w \right) \right)`. Rearranging the single
diode equation above with a Lambert W-function yields the following.
Copy link
Member

Choose a reason for hiding this comment

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

I'd replace the phrase "Rearranging the single diode equation above with a Lambert W-function yields the following. " with "Defining"

Because I could not find a derivation of the Lambert W solution in literature, I wrote it out in a Sandia report. We could add a reference if you want.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ OK, I think I've reworded it using "Defining ..." is this better:

Defining the following parameter, :math:z, is necessary to transform the single diode equation into a form that can be expressed as a Lambert W-function.


.. math::

z = \frac{R_s I_0}{n Ns V_{th} \left(1 + \frac{R_s}{R_{sh}} \right)} \exp \left(
\frac{R_s \left( I_L + I_0 \right) + V}{n Ns V_{th} \left(1 + \frac{R_s}{R_{sh}}\right)}
\right)

The the module current can be solved using the Lambert W-function.
Copy link
Member

Choose a reason for hiding this comment

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

Then the

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ thanks


.. math::

I = \frac{I_L + I_0 - \frac{V}{R_{sh}}}{1 + \frac{R_s}{R_{sh}}}
- \frac{n Ns V_{th}}{R_s} W(z)


Bishop's Algorithm
------------------
The function :func:`pvlib.singlediode.bishop88` uses an explicit solution [3]
that finds points on the IV curve by first solving for pairs :math:`(V_d, I)`
where :math:`V_d` is the diode voltage :math:`V_d = V + I*Rs`. Then the voltage
is backed out from :math:`V_d`. Points with specific voltage, such as open
circuit, are located using the bisection search method, ``brentq``, bounded
by a zero diode voltage and an estimate of open circuit voltage given by

.. math::

V_{oc, est} = n Ns V_{th} \log \left( \frac{I_L}{I_0} + 1 \right)

We know that :math:`V_d = 0` corresponds to a voltage less than zero, and
we can also show that when :math:`V_d = V_{oc, est}`, the resulting
current is also negative, meaning that the corresponding voltage must be
in the 4th quadrant and therefore greater than the open circuit voltage
(see proof below). Therefore the entire forward-bias 1st quadrant IV-curve
is bounded, and a bisection search within these points will always find
Copy link
Member

Choose a reason for hiding this comment

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

please clarify "these points" I believe you mean "a bisection search for V_oc between V_d = 0 and V_{oc, est}"

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ I tried to make this wording better. I added between Vd and Voc,est, but the point is not just to find Voc, but to be able to find any 1st quadrant point including Voc.

desired condition.

.. math::

I = I_L - I_0 \left(\exp \left(\frac{V_{oc, est}}{n Ns V_{th}} \right) - 1 \right)
- \frac{V_{oc, est}}{R_{sh}} \newline

I = I_L - I_0 \left(\exp \left(\frac{n Ns V_{th} \log \left(\frac{I_L}{I_0} + 1 \right)}{n Ns V_{th}} \right) - 1 \right)
- \frac{n Ns V_{th} \log \left(\frac{I_L}{I_0} + 1 \right)}{R_{sh}} \newline

I = I_L - I_0 \left(\exp \left(\log \left(\frac{I_L}{I_0} + 1 \right) \right) - 1 \right)
- \frac{n Ns V_{th} \log \left(\frac{I_L}{I_0} + 1 \right)}{R_{sh}} \newline

I = I_L - I_0 \left(\frac{I_L}{I_0} + 1 - 1 \right)
- \frac{n Ns V_{th} \log \left(\frac{I_L}{I_0} + 1 \right)}{R_{sh}} \newline

I = I_L - I_0 \left(\frac{I_L}{I_0} \right)
- \frac{n Ns V_{th} \log \left(\frac{I_L}{I_0} + 1 \right)}{R_{sh}} \newline

I = I_L - I_L - \frac{n Ns V_{th} \log \left( \frac{I_L}{I_0} + 1 \right)}{R_{sh}} \newline

I = - \frac{n Ns V_{th} \log \left( \frac{I_L}{I_0} + 1 \right)}{R_{sh}}

References
----------
[1] "Exact analytical solutions of the parameters of real solar cells using
Lambert W-function," A. Jain, A. Kapoor, Solar Energy Materials and Solar Cells,
81, (2004) pp 269-277.
:doi:`10.1016/j.solmat.2003.11.018`

[2] "A new method to determine the diode ideality factor of real solar cell
using Lambert W-function," A. Jain, A. Kapoor, Solar Energy Materials and Solar
Cells, 85, (2005) 391-396.
:doi:`10.1016/j.solmat.2004.05.022`

[3] "Computer simulation of the effects of electrical mismatches in
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
:doi:`10.1016/0379-6787(88)90059-2`
18 changes: 9 additions & 9 deletions docs/sphinx/source/whatsnew/v0.6.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,32 @@ Enhancements
``method`` in ``('lambertw', 'newton', 'brentq')``, default is ``'lambertw'``,
to select a method to solve the single diode equation for points on the IV
curve. Selecting either ``'brentq'`` or ``'newton'`` as the method uses
:func:`~pvlib.singlediode_methods.bishop88` with the corresponding method.
:func:`~pvlib.singlediode.bishop88` with the corresponding method.
(:issue:`410`)
* Implement new methods ``'brentq'`` and ``'newton'`` for solving the single
diode equation for points on the IV curve. ``'brentq'`` uses a bisection
method (Brent, 1973) that may be slow but guarantees a solution. ``'newton'``
uses the Newton-Raphson method and may be faster but is not guaranteed to
converge. However, ``'newton'`` should be safe for well-behaved IV curves.
(:issue:`408`)
* Implement :func:`~pvlib.singlediode_methods.bishop88` for explicit calculation
* Implement :func:`~pvlib.singlediode.bishop88` for explicit calculation
of arbitrary IV curve points using diode voltage instead of cell voltage. If
``method`` is either ``'newton'`` or ``'brentq'`` and ``ivcurve_pnts`` in
:func:`~pvlib.pvsystem.singlediode` is provided, the IV curve points will be
log spaced instead of linear.
* Implement :func:`~pvlib.singlediode_methods.estimate_voc` to estimate open
* Implement :func:`~pvlib.singlediode.estimate_voc` to estimate open
circuit voltage by assuming :math:`R_{sh} \to \infty` and :math:`R_s=0` as an
upper bound in bisection method for :func:`~pvlib.pvsystem.singlediode` when
method is either ``'newton'`` or ``'brentq'``.
* Add :func:`~pvlib.pvsystem.max_power_point` method to compute the max power
point using the new ``'brentq'`` method.
* Add new module ``pvlib.singlediode_methods`` with low-level functions for
* Add new module ``pvlib.singlediode`` with low-level functions for
solving the single diode equation such as:
:func:`~pvlib.singlediode_methods.bishop88`,
:func:`~pvlib.singlediode_methods.estimate_voc`,
:func:`~pvlib.singlediode_methods.bishop88_i_from_v`,
:func:`~pvlib.singlediode_methods.bishop88_v_from_i`, and
:func:`~pvlib.singlediode_methods.bishop88_mpp`.
:func:`~pvlib.singlediode.bishop88`,
:func:`~pvlib.singlediode.estimate_voc`,
:func:`~pvlib.singlediode.bishop88_i_from_v`,
:func:`~pvlib.singlediode.bishop88_v_from_i`, and
:func:`~pvlib.singlediode.bishop88_mpp`.
* Add PVSyst thin-film recombination losses for CdTe and a:Si (:issue:`163`)
* Python 3.7 officially supported. (:issue:`496`)

Expand Down
2 changes: 1 addition & 1 deletion pvlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
from pvlib import pvsystem
from pvlib import spa
from pvlib import modelchain
from pvlib import singlediode_methods
from pvlib import singlediode
74 changes: 17 additions & 57 deletions pvlib/pvsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from pvlib.tools import _build_kwargs
from pvlib.location import Location
from pvlib import irradiance, atmosphere
from pvlib import singlediode_methods
import pvlib # FIXME: import singlediode module from pvlib
Copy link
Member

Choose a reason for hiding this comment

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

why FIXME? seems ok to me.

Something like from pvlib import singlediode as _singlediode would work too.

Copy link
Member Author

Choose a reason for hiding this comment

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

✅ removed fixme, replace with comment use pvlib.singlediode to avoid clash with local method



# not sure if this belongs in the pvsystem module.
Expand Down Expand Up @@ -1963,52 +1963,12 @@ def singlediode(photocurrent, saturation_current, resistance_series,
open-circuit.

If the method is either ``'newton'`` or ``'brentq'`` and ``ivcurve_pnts``
are indicated, then :func:`pvlib.singlediode_methods.bishop88` is used to
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.

The ``bishop88`` method uses an explicit solution from [4] that finds
points on the IV curve by first solving for pairs :math:`(V_d, I)` where
:math:`V_d` is the diode voltage :math:`V_d = V + I*Rs`. Then the voltage
is backed out from :math:`V_d`. Points with specific voltage, such as open
circuit, are located using the bisection search method, ``brentq``, bounded
by a zero diode voltage and an estimate of open circuit voltage given by

.. math::

V_{oc, est} = n Ns V_{th} \\log \\left( \\frac{I_L}{I_0} + 1 \\right)

We know that :math:`V_d = 0` corresponds to a voltage less than zero, and
we can also show that when :math:`V_d = V_{oc, est}`, the resulting
current is also negative, meaning that the corresponding voltage must be
in the 4th quadrant and therefore greater than the open circuit voltage
(see proof below). Therefore the entire forward-bias 1st quadrant IV-curve
is bounded, and a bisection search within these points will always find
desired condition.

.. math::

I = I_L - I_0 \\left(\\exp \\left(\\frac{V_{oc, est}}{n Ns V_{th}} \\right) - 1 \\right)
- \\frac{V_{oc, est}}{R_{sh}} \\newline

I = I_L - I_0 \\left(\\exp \\left(\\frac{n Ns V_{th} \\log \\left(\\frac{I_L}{I_0} + 1 \\right)}{n Ns V_{th}} \\right) - 1 \\right)
- \\frac{n Ns V_{th} \\log \\left(\\frac{I_L}{I_0} + 1 \\right)}{R_{sh}} \\newline

I = I_L - I_0 \\left(\\exp \\left(\\log \\left(\\frac{I_L}{I_0} + 1 \\right) \\right) - 1 \\right)
- \\frac{n Ns V_{th} \\log \\left(\\frac{I_L}{I_0} + 1 \\right)}{R_{sh}} \\newline

I = I_L - I_0 \\left(\\frac{I_L}{I_0} + 1 - 1 \\right)
- \\frac{n Ns V_{th} \\log \\left(\\frac{I_L}{I_0} + 1 \\right)}{R_{sh}} \\newline

I = I_L - I_0 \\left(\\frac{I_L}{I_0} \\right)
- \\frac{n Ns V_{th} \\log \\left(\\frac{I_L}{I_0} + 1 \\right)}{R_{sh}} \\newline

I = I_L - I_L - \\frac{n Ns V_{th} \log \\left( \\frac{I_L}{I_0} + 1 \\right)}{R_{sh}} \\newline

I = - \\frac{n Ns V_{th} \\log \\left( \\frac{I_L}{I_0} + 1 \\right)}{R_{sh}}

References
-----------
[1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN
Expand All @@ -2029,12 +1989,12 @@ def singlediode(photocurrent, saturation_current, resistance_series,
--------
sapm
calcparams_desoto
pvlib.singlediode_methods.bishop88
pvlib.singlediode.bishop88
"""
# Calculate points on the IV curve using the LambertW solution to the
# single diode equation
if method.lower() == 'lambertw':
out = singlediode_methods._lambertw(
out = pvlib.singlediode._lambertw(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, ivcurve_pnts
)
Expand All @@ -2047,19 +2007,19 @@ def singlediode(photocurrent, saturation_current, resistance_series,
# equation for the diode voltage V_d then backing out voltage
args = (photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth) # collect args
v_oc = singlediode_methods.bishop88_v_from_i(
v_oc = pvlib.singlediode.bishop88_v_from_i(
0.0, *args, method=method.lower()
)
i_mp, v_mp, p_mp = singlediode_methods.bishop88_mpp(
i_mp, v_mp, p_mp = pvlib.singlediode.bishop88_mpp(
*args, method=method.lower()
)
i_sc = singlediode_methods.bishop88_i_from_v(
i_sc = pvlib.singlediode.bishop88_i_from_v(
0.0, *args, method=method.lower()
)
i_x = singlediode_methods.bishop88_i_from_v(
i_x = pvlib.singlediode.bishop88_i_from_v(
v_oc / 2.0, *args, method=method.lower()
)
i_xx = singlediode_methods.bishop88_i_from_v(
i_xx = pvlib.singlediode.bishop88_i_from_v(
(v_oc + v_mp) / 2.0, *args, method=method.lower()
)

Expand All @@ -2069,7 +2029,7 @@ def singlediode(photocurrent, saturation_current, resistance_series,
(11.0 - np.logspace(np.log10(11.0), 0.0,
ivcurve_pnts)) / 10.0
)
ivcurve_i, ivcurve_v, _ = singlediode_methods.bishop88(vd, *args)
ivcurve_i, ivcurve_v, _ = pvlib.singlediode.bishop88(vd, *args)

out = OrderedDict()
out['i_sc'] = i_sc
Expand Down Expand Up @@ -2125,7 +2085,7 @@ def max_power_point(photocurrent, saturation_current, resistance_series,
curve. This function uses Brent's method by default because it is
guaranteed to converge.
"""
i_mp, v_mp, p_mp = singlediode_methods.bishop88_mpp(
i_mp, v_mp, p_mp = pvlib.singlediode.bishop88_mpp(
photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth, method=method.lower()
)
Expand Down Expand Up @@ -2205,7 +2165,7 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
Energy Materials and Solar Cells, 81 (2004) 269-277.
'''
if method.lower() == 'lambertw':
return singlediode_methods._lambertw_v_from_i(
return pvlib.singlediode._lambertw_v_from_i(
resistance_shunt, resistance_series, nNsVth, current,
saturation_current, photocurrent
)
Expand All @@ -2215,9 +2175,9 @@ def v_from_i(resistance_shunt, resistance_series, nNsVth, current,
# equation for the diode voltage V_d then backing out voltage
args = (current, photocurrent, saturation_current,
resistance_series, resistance_shunt, nNsVth)
V = singlediode_methods.bishop88_v_from_i(*args, method=method.lower())
V = pvlib.singlediode.bishop88_v_from_i(*args, method=method.lower())
# find the right size and shape for returns
size, shape = singlediode_methods._get_size_and_shape(args)
size, shape = pvlib.singlediode._get_size_and_shape(args)
if size <= 1:
if shape is not None:
V = np.tile(V, shape)
Expand Down Expand Up @@ -2293,7 +2253,7 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
Energy Materials and Solar Cells, 81 (2004) 269-277.
'''
if method.lower() == 'lambertw':
return singlediode_methods._lambertw_i_from_v(
return pvlib.singlediode._lambertw_i_from_v(
resistance_shunt, resistance_series, nNsVth, voltage,
saturation_current, photocurrent
)
Expand All @@ -2303,9 +2263,9 @@ def i_from_v(resistance_shunt, resistance_series, nNsVth, voltage,
# equation for the diode voltage V_d then backing out voltage
args = (voltage, photocurrent, saturation_current, resistance_series,
resistance_shunt, nNsVth)
I = singlediode_methods.bishop88_i_from_v(*args, method=method.lower())
I = pvlib.singlediode.bishop88_i_from_v(*args, method=method.lower())
# find the right size and shape for returns
size, shape = singlediode_methods._get_size_and_shape(args)
size, shape = pvlib.singlediode._get_size_and_shape(args)
if size <= 1:
if shape is not None:
I = np.tile(I, shape)
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions pvlib/test/test_numerical_precision.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

This module can be executed from the command line to generate a high precision
dataset of I-V curve points to test the explicit single diode calculations
:func:`pvlib.singlediode_methods.bishop88`::
:func:`pvlib.singlediode.bishop88`::

$ python test_numeric_precision.py

This generates a file in the pvlib data folder, which is specified by the
constant ``DATA_PATH``. When the test is run using ``pytest`` it will compare
the values calculated by :func:`pvlib.singlediode_methods.bishop88` with the
the values calculated by :func:`pvlib.singlediode.bishop88` with the
high-precision values generated with SymPy.
"""

Expand All @@ -21,7 +21,7 @@
import numpy as np
import pandas as pd
from pvlib import pvsystem
from pvlib.singlediode_methods import bishop88, estimate_voc
from pvlib.singlediode import bishop88, estimate_voc

logging.basicConfig()
LOGGER = logging.getLogger(__name__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import numpy as np
from pvlib import pvsystem
from pvlib.singlediode_methods import bishop88, estimate_voc, VOLTAGE_BUILTIN
from pvlib.singlediode import bishop88, estimate_voc, VOLTAGE_BUILTIN
import pytest
from conftest import requires_scipy

Expand Down
4 changes: 2 additions & 2 deletions pvlib/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ def _build_kwargs(keys, input_dict):


# FIXME: remove _array_newton when SciPy-1.2.0 is released
# pvlib.singlediode_methods.bishop88_i_from_v(..., method='newton') and other
# functions in singlediode_methods call scipy.optimize.newton with a vector
# pvlib.singlediode.bishop88_i_from_v(..., method='newton') and other
# functions in singlediode call scipy.optimize.newton with a vector
# unfortunately wrapping the functions with np.vectorize() was too slow
# a vectorized newton method was merged into SciPy but isn't released yet, so
# in the meantime, we just copied the relevant code: "_array_newton" for more
Expand Down