Skip to content

Commit 5953f82

Browse files
cwhansekandersolar
andauthored
Use chandrupatla to find MPP in lambertw method (#2571)
* restart from PR2567 * left interval to neg., calculate i_mp * relax tolerance for i_mp * docstring work * indent * Apply suggestions from code review Co-authored-by: Kevin Anderson <[email protected]> * better inspection of values * shorten string in test system * Update docs/sphinx/source/whatsnew/v0.13.2.rst Co-authored-by: Kevin Anderson <[email protected]> --------- Co-authored-by: Kevin Anderson <[email protected]>
1 parent 258f78f commit 5953f82

File tree

5 files changed

+77
-31
lines changed

5 files changed

+77
-31
lines changed

docs/sphinx/source/whatsnew/v0.13.2.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ Enhancements
3030
:py:func:`~pvlib.singlediode.bishop88_mpp`,
3131
:py:func:`~pvlib.singlediode.bishop88_v_from_i`, and
3232
:py:func:`~pvlib.singlediode.bishop88_i_from_v`. (:issue:`2497`, :pull:`2498`)
33-
33+
* Accelerate :py:func:`~pvlib.pvsystem.singlediode` when scipy>=1.15 is
34+
installed. (:issue:`2497`, :pull:`2571`)
3435

3536

3637
Documentation
@@ -56,4 +57,4 @@ Maintenance
5657

5758
Contributors
5859
~~~~~~~~~~~~
59-
60+
* Cliff Hansen (:ghuser:`cwhanse`)

pvlib/pvsystem.py

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2534,28 +2534,35 @@ def singlediode(photocurrent, saturation_current, resistance_series,
25342534
explicit function of :math:`V=f(I)` and :math:`I=f(V)` as shown in [2]_.
25352535
25362536
If the method is ``'newton'`` then the root-finding Newton-Raphson method
2537-
is used. It should be safe for well behaved IV-curves, but the ``'brentq'``
2538-
method is recommended for reliability.
2537+
is used. It should be safe for well-behaved IV curves, otherwise the
2538+
``'chandrupatla``` or ``'brentq'`` methods are recommended for reliability.
25392539
25402540
If the method is ``'brentq'`` then Brent's bisection search method is used
25412541
that guarantees convergence by bounding the voltage between zero and
2542-
open-circuit.
2542+
open-circuit. ``'brentq'`` is generally slower than the other options.
2543+
2544+
If the method is ``'chandrupatla'`` then Chandrupatla's method is used
2545+
that guarantees convergence.
25432546
25442547
References
25452548
----------
2546-
.. [1] S.R. Wenham, M.A. Green, M.E. Watt, "Applied Photovoltaics" ISBN
2547-
0 86758 909 4
2549+
.. [1] S. R. Wenham, M. A. Green, M. E. Watt, "Applied Photovoltaics",
2550+
Centre for Photovoltaic Devices and Systems, 1995. ISBN
2551+
0867589094
25482552
25492553
.. [2] A. Jain, A. Kapoor, "Exact analytical solutions of the
25502554
parameters of real solar cells using Lambert W-function", Solar
2551-
Energy Materials and Solar Cells, 81 (2004) 269-277.
2555+
Energy Materials and Solar Cells, vol. 81 no. 2, pp. 269-277, Feb. 2004.
2556+
:doi:`10.1016/j.solmat.2003.11.018`.
25522557
2553-
.. [3] D. King et al, "Sandia Photovoltaic Array Performance Model",
2554-
SAND2004-3535, Sandia National Laboratories, Albuquerque, NM
2558+
.. [3] D. L. King, E. E. Boyson and J. A. Kratochvil "Photovoltaic Array
2559+
Performance Model", Sandia National Laboratories, Albuquerque, NM, USA.
2560+
Report SAND2004-3535, 2004.
25552561
2556-
.. [4] "Computer simulation of the effects of electrical mismatches in
2557-
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
2558-
https://doi.org/10.1016/0379-6787(88)90059-2
2562+
.. [4] J.W. Bishop, "Computer simulation of the effects of electrical
2563+
mismatches in photovoltaic cell interconnection circuits" Solar Cells,
2564+
vol. 25 no. 1, pp. 73-89, Oct. 1988.
2565+
:doi:`doi.org/10.1016/0379-6787(88)90059-2`
25592566
"""
25602567
args = (photocurrent, saturation_current, resistance_series,
25612568
resistance_shunt, nNsVth) # collect args
@@ -2565,8 +2572,9 @@ def singlediode(photocurrent, saturation_current, resistance_series,
25652572
out = _singlediode._lambertw(*args)
25662573
points = out[:7]
25672574
else:
2568-
# Calculate points on the IV curve using either 'newton' or 'brentq'
2569-
# methods. Voltages are determined by first solving the single diode
2575+
# Calculate points on the IV curve using Bishop's algorithm and solving
2576+
# with 'newton', 'brentq' or 'chandrupatla' method.
2577+
# Voltages are determined by first solving the single diode
25702578
# equation for the diode voltage V_d then backing out voltage
25712579
v_oc = _singlediode.bishop88_v_from_i(
25722580
0.0, *args, method=method.lower()

pvlib/singlediode.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,20 @@ def bishop88(diode_voltage, photocurrent, saturation_current,
141141
142142
References
143143
----------
144-
.. [1] "Computer simulation of the effects of electrical mismatches in
145-
photovoltaic cell interconnection circuits" JW Bishop, Solar Cell (1988)
146-
:doi:`10.1016/0379-6787(88)90059-2`
147-
148-
.. [2] "Improved equivalent circuit and Analytical Model for Amorphous
149-
Silicon Solar Cells and Modules." J. Mertens, et al., IEEE Transactions
150-
on Electron Devices, Vol 45, No 2, Feb 1998.
144+
.. [1] J.W. Bishop, "Computer simulation of the effects of electrical
145+
mismatches in photovoltaic cell interconnection circuits" Solar Cells,
146+
vol. 25 no. 1, pp. 73-89, Oct. 1988.
147+
:doi:`doi.org/10.1016/0379-6787(88)90059-2`
148+
149+
.. [2] J. Merten, J. M. Asensi, C. Voz, A. V. Shah, R. Platz and J. Andreu,
150+
"Improved equivalent circuit and Analytical Model for Amorphous
151+
Silicon Solar Cells and Modules." , IEEE Transactions
152+
on Electron Devices, vol. 45, no. 2, pp. 423-429, Feb 1998.
151153
:doi:`10.1109/16.658676`
152154
153-
.. [3] "Performance assessment of a simulation model for PV modules of any
154-
available technology", André Mermoud and Thibault Lejeune, 25th EUPVSEC,
155-
2010
155+
.. [3] A. Mermoud and T. Lejeune, "Performance assessment of a simulation
156+
model for PV modules of any available technology", In Proc. of the 25th
157+
European PVSEC, Valencia, ES, 2010.
156158
:doi:`10.4229/25thEUPVSEC2010-4BV.1.114`
157159
"""
158160
# calculate recombination loss current where d2mutau > 0
@@ -913,10 +915,25 @@ def _lambertw(photocurrent, saturation_current, resistance_series,
913915
v_oc = 0.
914916

915917
# Find the voltage, v_mp, where the power is maximized.
916-
# Start the golden section search at v_oc * 1.14
917-
p_mp, v_mp = _golden_sect_DataFrame(params, 0., v_oc * 1.14, _pwr_optfcn)
918+
# use scipy.elementwise if available
919+
# remove try/except when scipy>=1.15, and golden mean is retired
920+
try:
921+
from scipy.optimize.elementwise import find_minimum
922+
# left negative to insure strict inequality
923+
init = (-1., 0.8*v_oc, v_oc)
924+
res = find_minimum(_vmp_opt, init,
925+
args=(params['photocurrent'],
926+
params['saturation_current'],
927+
params['resistance_series'],
928+
params['resistance_shunt'],
929+
params['nNsVth'],))
930+
v_mp = res.x
931+
p_mp = -1.*res.f_x
932+
except ModuleNotFoundError:
933+
# switch to old golden section method
934+
p_mp, v_mp = _golden_sect_DataFrame(params, 0., v_oc * 1.14,
935+
_pwr_optfcn)
918936

919-
# Find Imp using Lambert W
920937
i_mp = _lambertw_i_from_v(v_mp, **params)
921938

922939
# Find Ix and Ixx using Lambert W
@@ -938,6 +955,15 @@ def _lambertw(photocurrent, saturation_current, resistance_series,
938955
return out
939956

940957

958+
def _vmp_opt(v, iph, io, rs, rsh, nNsVth):
959+
'''
960+
Function to find negative of power from ``i_from_v``.
961+
'''
962+
current = _lambertw_i_from_v(v, iph, io, rs, rsh, nNsVth)
963+
964+
return -v * current
965+
966+
941967
def _pwr_optfcn(df, loc):
942968
'''
943969
Function to find power from ``i_from_v``.

tests/test_modelchain.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def cec_dc_adr_ac_system(sam_data, cec_module_cs5p_220m,
140140
module_parameters=module_parameters,
141141
temperature_model_parameters=temp_model_params,
142142
inverter_parameters=inverter,
143-
modules_per_string=14)
143+
modules_per_string=13)
144144
return system
145145

146146

@@ -1383,6 +1383,12 @@ def test_ac_models(sapm_dc_snl_ac_system, cec_dc_adr_ac_system,
13831383
'adr': 'adr',
13841384
'pvwatts': 'pvwatts',
13851385
'pvwatts_multi': 'pvwatts'}
1386+
inverter_to_ac_model_param = {
1387+
'sandia': 'Paco',
1388+
'sandia_multi': 'Paco',
1389+
'adr': 'Pnom',
1390+
'pvwatts': 'pdc0',
1391+
'pvwatts_multi': 'pdc0'}
13861392
ac_model = inverter_to_ac_model[inverter_model]
13871393
system = ac_systems[inverter_model]
13881394

@@ -1399,7 +1405,12 @@ def test_ac_models(sapm_dc_snl_ac_system, cec_dc_adr_ac_system,
13991405
assert m.call_count == 1
14001406
assert isinstance(mc.results.ac, pd.Series)
14011407
assert not mc.results.ac.empty
1402-
assert mc.results.ac.iloc[1] < 1
1408+
# irradiance 800 W/m2 at 1st timestamp
1409+
inv_param = mc.system.inverter_parameters[
1410+
inverter_to_ac_model_param[inverter_model]]
1411+
assert (mc.results.ac.iloc[0] > inv_param / 2.)
1412+
# irradiance 0 W/m2 at the 2nd timestamp
1413+
assert (np.isnan(mc.results.ac.iloc[1]) or (mc.results.ac.iloc[1] < 1))
14031414

14041415

14051416
def test_ac_model_user_func(pvwatts_dc_pvwatts_ac_system, location, weather,

tests/test_singlediode.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def test_singlediode_precision(method, precise_iv_curves):
159159

160160
assert np.allclose(pc['i_sc'], outs['i_sc'], atol=1e-10, rtol=0)
161161
assert np.allclose(pc['v_oc'], outs['v_oc'], atol=1e-10, rtol=0)
162-
assert np.allclose(pc['i_mp'], outs['i_mp'], atol=7e-8, rtol=0)
162+
assert np.allclose(pc['i_mp'], outs['i_mp'], atol=1e-7, rtol=0)
163163
assert np.allclose(pc['v_mp'], outs['v_mp'], atol=1e-6, rtol=0)
164164
assert np.allclose(pc['p_mp'], outs['p_mp'], atol=1e-10, rtol=0)
165165
assert np.allclose(pc['i_x'], outs['i_x'], atol=1e-10, rtol=0)

0 commit comments

Comments
 (0)