|
20 | 20 | from pvlib.tools import _build_kwargs
|
21 | 21 | from pvlib.location import Location
|
22 | 22 | from pvlib import irradiance, atmosphere
|
| 23 | +from pvlib import way_faster |
23 | 24 |
|
24 | 25 |
|
25 | 26 | # not sure if this belongs in the pvsystem module.
|
@@ -1571,7 +1572,7 @@ def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
|
1571 | 1572 |
|
1572 | 1573 |
|
1573 | 1574 | def singlediode(photocurrent, saturation_current, resistance_series,
|
1574 |
| - resistance_shunt, nNsVth, ivcurve_pnts=None): |
| 1575 | + resistance_shunt, nNsVth, ivcurve_pnts=None, method=''): |
1575 | 1576 | r'''
|
1576 | 1577 | Solve the single-diode model to obtain a photovoltaic IV curve.
|
1577 | 1578 |
|
@@ -1627,6 +1628,12 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
1627 | 1628 | Number of points in the desired IV curve. If None or 0, no
|
1628 | 1629 | IV curves will be produced.
|
1629 | 1630 |
|
| 1631 | + method : str, default 'slow' |
| 1632 | + Either 'slow', 'fast', or 'lambertw'. Determines the method used to |
| 1633 | + calculate IV curve and points. If 'slow' then ``brentq`` is used, if |
| 1634 | + 'fast' then ``newton`` is used, and if 'lambertw' then `lambertw` is |
| 1635 | + used. |
| 1636 | +
|
1630 | 1637 | Returns
|
1631 | 1638 | -------
|
1632 | 1639 | OrderedDict or DataFrame
|
@@ -1677,53 +1684,75 @@ def singlediode(photocurrent, saturation_current, resistance_series,
|
1677 | 1684 | calcparams_desoto
|
1678 | 1685 | '''
|
1679 | 1686 |
|
1680 |
| - # Compute short circuit current |
1681 |
| - i_sc = i_from_v(resistance_shunt, resistance_series, nNsVth, 0., |
1682 |
| - saturation_current, photocurrent) |
| 1687 | + if method.lower() == 'lambertw': |
| 1688 | + # Compute short circuit current |
| 1689 | + i_sc = i_from_v(resistance_shunt, resistance_series, nNsVth, 0., |
| 1690 | + saturation_current, photocurrent) |
| 1691 | + |
| 1692 | + # Compute open circuit voltage |
| 1693 | + v_oc = v_from_i(resistance_shunt, resistance_series, nNsVth, 0., |
| 1694 | + saturation_current, photocurrent) |
1683 | 1695 |
|
1684 |
| - # Compute open circuit voltage |
1685 |
| - v_oc = v_from_i(resistance_shunt, resistance_series, nNsVth, 0., |
1686 |
| - saturation_current, photocurrent) |
| 1696 | + params = {'r_sh': resistance_shunt, |
| 1697 | + 'r_s': resistance_series, |
| 1698 | + 'nNsVth': nNsVth, |
| 1699 | + 'i_0': saturation_current, |
| 1700 | + 'i_l': photocurrent} |
1687 | 1701 |
|
1688 |
| - params = {'r_sh': resistance_shunt, |
1689 |
| - 'r_s': resistance_series, |
1690 |
| - 'nNsVth': nNsVth, |
1691 |
| - 'i_0': saturation_current, |
1692 |
| - 'i_l': photocurrent} |
| 1702 | + p_mp, v_mp = _golden_sect_DataFrame(params, 0., v_oc * 1.14, _pwr_optfcn) |
1693 | 1703 |
|
1694 |
| - p_mp, v_mp = _golden_sect_DataFrame(params, 0., v_oc * 1.14, _pwr_optfcn) |
| 1704 | + # Invert the Power-Current curve. Find the current where the inverted power |
| 1705 | + # is minimized. This is i_mp. Start the optimization at v_oc/2 |
| 1706 | + i_mp = i_from_v(resistance_shunt, resistance_series, nNsVth, v_mp, |
| 1707 | + saturation_current, photocurrent) |
1695 | 1708 |
|
1696 |
| - # Invert the Power-Current curve. Find the current where the inverted power |
1697 |
| - # is minimized. This is i_mp. Start the optimization at v_oc/2 |
1698 |
| - i_mp = i_from_v(resistance_shunt, resistance_series, nNsVth, v_mp, |
1699 |
| - saturation_current, photocurrent) |
| 1709 | + # Find Ix and Ixx using Lambert W |
| 1710 | + i_x = i_from_v(resistance_shunt, resistance_series, nNsVth, 0.5 * v_oc, |
| 1711 | + saturation_current, photocurrent) |
1700 | 1712 |
|
1701 |
| - # Find Ix and Ixx using Lambert W |
1702 |
| - i_x = i_from_v(resistance_shunt, resistance_series, nNsVth, 0.5 * v_oc, |
1703 |
| - saturation_current, photocurrent) |
| 1713 | + i_xx = i_from_v(resistance_shunt, resistance_series, nNsVth, |
| 1714 | + 0.5 * (v_oc + v_mp), saturation_current, photocurrent) |
1704 | 1715 |
|
1705 |
| - i_xx = i_from_v(resistance_shunt, resistance_series, nNsVth, |
1706 |
| - 0.5 * (v_oc + v_mp), saturation_current, photocurrent) |
| 1716 | + out = OrderedDict() |
| 1717 | + out['i_sc'] = i_sc |
| 1718 | + out['v_oc'] = v_oc |
| 1719 | + out['i_mp'] = i_mp |
| 1720 | + out['v_mp'] = v_mp |
| 1721 | + out['p_mp'] = p_mp |
| 1722 | + out['i_x'] = i_x |
| 1723 | + out['i_xx'] = i_xx |
1707 | 1724 |
|
1708 |
| - out = OrderedDict() |
1709 |
| - out['i_sc'] = i_sc |
1710 |
| - out['v_oc'] = v_oc |
1711 |
| - out['i_mp'] = i_mp |
1712 |
| - out['v_mp'] = v_mp |
1713 |
| - out['p_mp'] = p_mp |
1714 |
| - out['i_x'] = i_x |
1715 |
| - out['i_xx'] = i_xx |
1716 |
| - |
1717 |
| - # create ivcurve |
1718 |
| - if ivcurve_pnts: |
1719 |
| - ivcurve_v = (np.asarray(v_oc)[..., np.newaxis] * |
1720 |
| - np.linspace(0, 1, ivcurve_pnts)) |
1721 |
| - |
1722 |
| - ivcurve_i = i_from_v(resistance_shunt, resistance_series, nNsVth, |
1723 |
| - ivcurve_v.T, saturation_current, photocurrent).T |
1724 |
| - |
1725 |
| - out['v'] = ivcurve_v |
1726 |
| - out['i'] = ivcurve_i |
| 1725 | + # create ivcurve |
| 1726 | + if ivcurve_pnts: |
| 1727 | + ivcurve_v = (np.asarray(v_oc)[..., np.newaxis] * |
| 1728 | + np.linspace(0, 1, ivcurve_pnts)) |
| 1729 | + |
| 1730 | + ivcurve_i = i_from_v(resistance_shunt, resistance_series, nNsVth, |
| 1731 | + ivcurve_v.T, saturation_current, photocurrent).T |
| 1732 | + |
| 1733 | + out['v'] = ivcurve_v |
| 1734 | + out['i'] = ivcurve_i |
| 1735 | + |
| 1736 | + else: |
| 1737 | + size = 0 |
| 1738 | + try: |
| 1739 | + size = len(photocurrent) |
| 1740 | + except TypeError: |
| 1741 | + my_func = way_faster.faster_way |
| 1742 | + else: |
| 1743 | + my_func = np.vectorize(way_faster.slower_way) |
| 1744 | + out = my_func(photocurrent, saturation_current, resistance_series, |
| 1745 | + resistance_shunt, nNsVth, ivcurve_pnts) |
| 1746 | + if size: |
| 1747 | + out_array = pd.DataFrame(out.tolist()) |
| 1748 | + out = OrderedDict() |
| 1749 | + out['i_sc'] = out_array.i_sc |
| 1750 | + out['v_oc'] = out_array.v_oc |
| 1751 | + out['i_mp'] = out_array.i_mp |
| 1752 | + out['v_mp'] = out_array.v_mp |
| 1753 | + out['p_mp'] = out_array.p_mp |
| 1754 | + out['i_x'] = out_array.i_x |
| 1755 | + out['i_xx'] = out_array.i_xx |
1727 | 1756 |
|
1728 | 1757 | if isinstance(photocurrent, pd.Series) and not ivcurve_pnts:
|
1729 | 1758 | out = pd.DataFrame(out, index=photocurrent.index)
|
|
0 commit comments