From 611f409082655f3d1312ce26320691dae73ea7a1 Mon Sep 17 00:00:00 2001 From: Mark Mikofski Date: Wed, 8 Aug 2018 14:16:56 -0700 Subject: [PATCH 1/5] MAINT: rename singlediode_methods.py to just singlediode.py * closes #515 * import pvlib in pvsystem and use pvlib.singlediode to differentiate from existing pvsystem.singldiode() method already there! * rename test_singlediode_methods.py to test_singlediode.py * update documentation and comments --- docs/sphinx/source/api.rst | 10 +++--- docs/sphinx/source/whatsnew/v0.6.0.rst | 18 +++++----- pvlib/__init__.py | 2 +- pvlib/pvsystem.py | 34 +++++++++---------- ...{singlediode_methods.py => singlediode.py} | 0 pvlib/test/test_numerical_precision.py | 6 ++-- ...lediode_methods.py => test_singlediode.py} | 2 +- pvlib/tools.py | 4 +-- 8 files changed, 38 insertions(+), 38 deletions(-) rename pvlib/{singlediode_methods.py => singlediode.py} (100%) rename pvlib/test/{test_singlediode_methods.py => test_singlediode.py} (99%) diff --git a/docs/sphinx/source/api.rst b/docs/sphinx/source/api.rst index 31cfabdb02..735b89ff10 100644 --- a/docs/sphinx/source/api.rst +++ b/docs/sphinx/source/api.rst @@ -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 ---------- diff --git a/docs/sphinx/source/whatsnew/v0.6.0.rst b/docs/sphinx/source/whatsnew/v0.6.0.rst index b60a683c5f..492aca4961 100644 --- a/docs/sphinx/source/whatsnew/v0.6.0.rst +++ b/docs/sphinx/source/whatsnew/v0.6.0.rst @@ -32,7 +32,7 @@ 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 @@ -40,24 +40,24 @@ Enhancements 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`) diff --git a/pvlib/__init__.py b/pvlib/__init__.py index 3a231da728..0606737ee5 100644 --- a/pvlib/__init__.py +++ b/pvlib/__init__.py @@ -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 diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index e44617f36a..19343aadb8 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -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 # not sure if this belongs in the pvsystem module. @@ -1963,7 +1963,7 @@ 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` 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 @@ -2029,12 +2029,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 ) @@ -2047,19 +2047,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() ) @@ -2069,7 +2069,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 @@ -2125,7 +2125,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() ) @@ -2205,7 +2205,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 ) @@ -2215,9 +2215,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) @@ -2293,7 +2293,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 ) @@ -2303,9 +2303,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) diff --git a/pvlib/singlediode_methods.py b/pvlib/singlediode.py similarity index 100% rename from pvlib/singlediode_methods.py rename to pvlib/singlediode.py diff --git a/pvlib/test/test_numerical_precision.py b/pvlib/test/test_numerical_precision.py index 8d4ebd3d7d..50b86c6e3a 100644 --- a/pvlib/test/test_numerical_precision.py +++ b/pvlib/test/test_numerical_precision.py @@ -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. """ @@ -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__) diff --git a/pvlib/test/test_singlediode_methods.py b/pvlib/test/test_singlediode.py similarity index 99% rename from pvlib/test/test_singlediode_methods.py rename to pvlib/test/test_singlediode.py index 27deaf4276..3d659eb450 100644 --- a/pvlib/test/test_singlediode_methods.py +++ b/pvlib/test/test_singlediode.py @@ -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 diff --git a/pvlib/tools.py b/pvlib/tools.py index 16596af885..72835e8803 100644 --- a/pvlib/tools.py +++ b/pvlib/tools.py @@ -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 From 1a42153d82bd1a4d4b7f988916dff1c91cced759 Mon Sep 17 00:00:00 2001 From: Mark Mikofski Date: Wed, 8 Aug 2018 16:07:11 -0700 Subject: [PATCH 2/5] DOC: move proof that estimated Voc is in q4 * closes #518 * add singlediode.rst and add to index --- docs/sphinx/source/index.rst | 1 + docs/sphinx/source/singlediode.rst | 98 ++++++++++++++++++++++++++++++ pvlib/pvsystem.py | 42 +------------ 3 files changed, 100 insertions(+), 41 deletions(-) create mode 100644 docs/sphinx/source/singlediode.rst diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst index a5ad0d3e4e..f1106b151a 100644 --- a/docs/sphinx/source/index.rst +++ b/docs/sphinx/source/index.rst @@ -81,6 +81,7 @@ Contents api comparison_pvlib_matlab variables_style_rules + singlediode Indices and tables diff --git a/docs/sphinx/source/singlediode.rst b/docs/sphinx/source/singlediode.rst new file mode 100644 index 0000000000..54c16c4c6f --- /dev/null +++ b/docs/sphinx/source/singlediode.rst @@ -0,0 +1,98 @@ +.. _singlediode: + +Single Diode Model +================== + +This section reviews the solutions to the single diode model used in +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: + +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]. The following algorithm can be found on +`Wikipedia: 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. + +.. 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. + +.. 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 [2] +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] A. Jain, A. Kapoor, "Exact analytical solutions of the +parameters of real solar cells using Lambert W-function", Solar +Energy Materials and Solar Cells, 81 (2004) 269-277. + +[2] "Computer simulation of the effects of electrical mismatches in +photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988) +https://doi.org/10.1016/0379-6787(88)90059-2 \ No newline at end of file diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 19343aadb8..7309dcb98d 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -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.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 From a49e959cf69eecdb58b4009cc39ed8bfedfea12d Mon Sep 17 00:00:00 2001 From: Mark Mikofski Date: Wed, 8 Aug 2018 16:28:44 -0700 Subject: [PATCH 3/5] DOC: add DOI to Jain and Kapoor * proofed the docs and they are ok --- docs/sphinx/source/singlediode.rst | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/sphinx/source/singlediode.rst b/docs/sphinx/source/singlediode.rst index 54c16c4c6f..d21b922265 100644 --- a/docs/sphinx/source/singlediode.rst +++ b/docs/sphinx/source/singlediode.rst @@ -14,10 +14,10 @@ a ``method`` keyword to the :func:`pvlib.pvsystem.singlediode` function: Lambert W-Function ------------------ -When ``method='lambertw'``, the Lambert W-Function is used as previously shown -by Jain and Kapoor [1]. The following algorithm can be found on +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 -`_ given the basic single +`_, given the basic single diode model equation. .. math:: @@ -47,7 +47,7 @@ The the module current can be solved using the Lambert W-function. Bishop's Algorithm ------------------ -The function :func:`pvlib.singlediode.bishop88` uses an explicit solution [2] +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 @@ -89,10 +89,16 @@ desired condition. References ---------- -[1] A. Jain, A. Kapoor, "Exact analytical solutions of the -parameters of real solar cells using Lambert W-function", Solar -Energy Materials and Solar Cells, 81 (2004) 269-277. +[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] "Computer simulation of the effects of electrical mismatches in +[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) -https://doi.org/10.1016/0379-6787(88)90059-2 \ No newline at end of file +:doi:`10.1016/0379-6787(88)90059-2` \ No newline at end of file From 1b024e1b67d9a1c683dc19109904101839b97569 Mon Sep 17 00:00:00 2001 From: Mark Mikofski Date: Thu, 9 Aug 2018 17:16:53 -0700 Subject: [PATCH 4/5] DOC: MAINT: improve wording in singlediode.rst * add to what's new documentation section that there is now some detail on pvlib-python solutions to single diode equation * change single diode _model_ to single diode _equation_ everywhere to distinguish between the equation I = IL - I0*(exp(Vd/nNsVt)-1) - Vd/Rsh and implementation like PVSyst and DeSoto that derive coefficients * add reference to Cliff's Sandia Report on Lambert W-function solution of single diode equation * remove fixme in pvsystem --- docs/sphinx/source/singlediode.rst | 38 ++++++++++++++++---------- docs/sphinx/source/whatsnew/v0.6.0.rst | 2 ++ pvlib/pvsystem.py | 2 +- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/sphinx/source/singlediode.rst b/docs/sphinx/source/singlediode.rst index d21b922265..e8695bbb09 100644 --- a/docs/sphinx/source/singlediode.rst +++ b/docs/sphinx/source/singlediode.rst @@ -1,21 +1,23 @@ .. _singlediode: -Single Diode Model -================== +Single Diode Equation +===================== -This section reviews the solutions to the single diode model used in +This section reviews the solutions to the single diode equation used in 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: +pvlib-python supports two ways to solve the single diode equation: 1. Lambert W-Function 2. Bishop's Algorithm +The :func:`pvlib.pvsystem.singlediode` function allows the user to choose the +method using the ``method`` keyword. + 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 +by Jain and Kapoor [1-3]. The following algorithm can be found on `Wikipedia: Theory of Solar Cells `_, given the basic single diode model equation. @@ -28,8 +30,9 @@ diode model equation. 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. +:math:`w = W \left( w \exp \left( w \right) \right)`. 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:: @@ -37,17 +40,18 @@ diode equation above with a Lambert W-function yields the following. \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. +Then the module current can be solved using the Lambert W-function, +:math:`W \left(z \right)`. .. 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) + - \frac{n Ns V_{th}}{R_s} W \left(z \right) Bishop's Algorithm ------------------ -The function :func:`pvlib.singlediode.bishop88` uses an explicit solution [3] +The function :func:`pvlib.singlediode.bishop88` uses an explicit solution [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 @@ -63,8 +67,9 @@ 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. +is bounded because :math:`V_{oc} < V_{oc, est}`, and so a bisection search +between 0 and :math:`V_{oc, est}` will always find any desired condition in the +1st quadrant including :math:`V_{oc}`. .. math:: @@ -99,6 +104,11 @@ 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 +[3] "Parameter Estimation for Single Diode Models of Photovoltaic Modules," +Clifford W. Hansen, Sandia `Report SAND2015-2065 +`_, +2015 :doi:`10.13140/RG.2.1.4336.7842` + +[4] "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` \ No newline at end of file diff --git a/docs/sphinx/source/whatsnew/v0.6.0.rst b/docs/sphinx/source/whatsnew/v0.6.0.rst index 492aca4961..1db4dc91a5 100644 --- a/docs/sphinx/source/whatsnew/v0.6.0.rst +++ b/docs/sphinx/source/whatsnew/v0.6.0.rst @@ -84,6 +84,8 @@ Documentation * Updated several incorrect statements in ModelChain documentation regarding implementation status and default values. (:issue:`480`) * Expanded general contributing and pull request guidelines. +* Added section on single diode equation with some detail on solutions used in + pvlib-python (:issue:`518`) Testing diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 7309dcb98d..a89da7dd48 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -20,7 +20,7 @@ from pvlib.tools import _build_kwargs from pvlib.location import Location from pvlib import irradiance, atmosphere -import pvlib # FIXME: import singlediode module from pvlib +import pvlib # use pvlib.singlediode to avoid clash with local method # not sure if this belongs in the pvsystem module. From fa03a939c1ae5513f4154815769dffc82b2d9c40 Mon Sep 17 00:00:00 2001 From: Mark Mikofski Date: Thu, 9 Aug 2018 17:26:09 -0700 Subject: [PATCH 5/5] DOC: MAINT: fix citation for Sandia Report, remove extra parentheses --- docs/sphinx/source/singlediode.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sphinx/source/singlediode.rst b/docs/sphinx/source/singlediode.rst index e8695bbb09..2fafa7d9f5 100644 --- a/docs/sphinx/source/singlediode.rst +++ b/docs/sphinx/source/singlediode.rst @@ -17,15 +17,15 @@ method using the ``method`` keyword. Lambert W-Function ------------------ When ``method='lambertw'``, the Lambert W-function is used as previously shown -by Jain and Kapoor [1-3]. The following algorithm can be found on +by Jain, Kapoor [1, 2] and Hansen [3]. The following algorithm can be found on `Wikipedia: 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}} + I = I_L - I_0 \left(\exp \left(\frac{V + I R_s}{n Ns V_{th}} \right) - 1 \right) + - \frac{V + I R_s}{R_{sh}} Lambert W-function is the inverse of the function :math:`f \left( w \right) = w \exp \left( w \right)` or