Skip to content

Commit 394cc58

Browse files
committed
try out skipping chandrupatla on py3.9
1 parent 3aa8acd commit 394cc58

3 files changed

Lines changed: 55 additions & 43 deletions

File tree

tests/conftest.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pandas as pd
66
import os
7+
import sys
78
from packaging.version import Version
89
import pytest
910
from functools import wraps
@@ -194,6 +195,17 @@ def has_spa_c():
194195
reason="requires pandas>=2.0.0")
195196

196197

198+
# single-diode equation functions have method=='chandrupatla', which relies
199+
# on scipy.optimize.elementwise.find_root, which is only available in
200+
# scipy>=1.15. That is only available for python 3.10 and above, so
201+
# we need to skip those tests on python 3.9.
202+
# TODO remove this when we drop support for python 3.9.
203+
chandrupatla_available = sys.version_info >= (3, 10)
204+
chandrupatla = pytest.param(
205+
"chandrupatla", marks=pytest.mark.skipif(not chandrupatla_available)
206+
)
207+
208+
197209
@pytest.fixture()
198210
def golden():
199211
return Location(39.742476, -105.1786, 'America/Denver', 1830.14)

tests/test_pvsystem.py

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
from tests.test_singlediode import get_pvsyst_fs_495
2424

25+
from .conftest import chandrupatla, chandrupatla_available
26+
2527

2628
@pytest.mark.parametrize('iam_model,model_params', [
2729
('ashrae', {'b': 0.05}),
@@ -1371,8 +1373,11 @@ def fixture_i_from_v(request):
13711373

13721374

13731375
@pytest.mark.parametrize(
1374-
'method, atol', [('lambertw', 1e-11), ('brentq', 1e-11), ('newton', 1e-11),
1375-
('chandrupatla', 1e-11)]
1376+
'method, atol', [
1377+
('lambertw', 1e-11), ('brentq', 1e-11), ('newton', 1e-11),
1378+
pytest.param("chandrupatla", 1e-11,
1379+
marks=pytest.mark.skipif(not chandrupatla_available)),
1380+
]
13761381
)
13771382
def test_i_from_v(fixture_i_from_v, method, atol):
13781383
# Solution set loaded from fixture
@@ -1401,50 +1406,42 @@ def test_PVSystem_i_from_v(mocker):
14011406
m.assert_called_once_with(*args)
14021407

14031408

1404-
def test_i_from_v_size():
1405-
with pytest.raises(ValueError):
1406-
pvsystem.i_from_v([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
1407-
with pytest.raises(ValueError):
1408-
pvsystem.i_from_v([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
1409-
method='brentq')
1410-
with pytest.raises(ValueError):
1411-
pvsystem.i_from_v([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
1412-
method='chandrupatla')
1409+
@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton',
1410+
chandrupatla])
1411+
def test_i_from_v_size(method):
1412+
if method == 'newton':
1413+
args = ([7.5] * 3, np.array([7., 7.]), 6e-7, 0.1, 20, 0.5)
1414+
else:
1415+
args = ([7.5] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
14131416
with pytest.raises(ValueError):
1414-
pvsystem.i_from_v([7.5] * 3, np.array([7., 7.]), 6e-7, 0.1, 20, 0.5,
1415-
method='newton')
1417+
pvsystem.i_from_v(*args, method=method)
14161418

14171419

1418-
def test_v_from_i_size():
1419-
with pytest.raises(ValueError):
1420-
pvsystem.v_from_i([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
1421-
with pytest.raises(ValueError):
1422-
pvsystem.v_from_i([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
1423-
method='brentq')
1424-
with pytest.raises(ValueError):
1425-
pvsystem.v_from_i([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5,
1426-
method='chandrupatla')
1420+
@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton',
1421+
chandrupatla])
1422+
def test_v_from_i_size(method):
1423+
if method == 'newton':
1424+
args = ([3.] * 3, np.array([7., 7.]), 6e-7, [0.1], 20, 0.5)
1425+
else:
1426+
args = ([3.] * 3, 7., 6e-7, [0.1] * 2, 20, 0.5)
14271427
with pytest.raises(ValueError):
1428-
pvsystem.v_from_i([3.] * 3, np.array([7., 7.]), 6e-7, [0.1], 20, 0.5,
1429-
method='newton')
1428+
pvsystem.v_from_i(*args, method=method)
14301429

14311430

1432-
def test_mpp_floats():
1431+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
1432+
def test_mpp_floats(method):
14331433
"""test max_power_point"""
14341434
IL, I0, Rs, Rsh, nNsVth = (7, 6e-7, .1, 20, .5)
1435-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='brentq')
1435+
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method=method)
14361436
expected = {'i_mp': 6.1362673597376753, # 6.1390251797935704, lambertw
14371437
'v_mp': 6.2243393757884284, # 6.221535886625464, lambertw
14381438
'p_mp': 38.194210547580511} # 38.194165464983037} lambertw
14391439
assert isinstance(out, dict)
14401440
for k, v in out.items():
14411441
assert np.isclose(v, expected[k])
1442-
out = pvsystem.max_power_point(IL, I0, Rs, Rsh, nNsVth, method='newton')
1443-
for k, v in out.items():
1444-
assert np.isclose(v, expected[k])
14451442

14461443

1447-
@pytest.mark.parametrize('method', ['brentq', 'newton', 'chandrupatla'])
1444+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
14481445
def test_mpp_recombination(method):
14491446
"""test max_power_point"""
14501447
pvsyst_fs_495 = get_pvsyst_fs_495()
@@ -1475,7 +1472,7 @@ def test_mpp_recombination(method):
14751472
assert np.isclose(v, expected[k], 0.01)
14761473

14771474

1478-
@pytest.mark.parametrize('method', ['brentq', 'newton', 'chandrupatla'])
1475+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
14791476
def test_mpp_array(method):
14801477
"""test max_power_point"""
14811478
IL, I0, Rs, Rsh, nNsVth = (np.array([7, 7]), 6e-7, .1, 20, .5)
@@ -1488,7 +1485,7 @@ def test_mpp_array(method):
14881485
assert np.allclose(v, expected[k])
14891486

14901487

1491-
@pytest.mark.parametrize('method', ['brentq', 'newton', 'chandrupatla'])
1488+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
14921489
def test_mpp_series(method):
14931490
"""test max_power_point"""
14941491
idx = ['2008-02-17T11:30:00-0800', '2008-02-17T12:30:00-0800']

tests/test_singlediode.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
from numpy.testing import assert_array_equal
1313
from .conftest import TESTS_DATA_DIR
1414

15+
from .conftest import chandrupatla, chandrupatla_available
16+
1517
POA = 888
1618
TCELL = 55
1719

1820

19-
@pytest.mark.parametrize('method', ['brentq', 'newton', 'chandrupatla'])
21+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
2022
def test_method_spr_e20_327(method, cec_module_spr_e20_327):
2123
"""test pvsystem.singlediode with different methods on SPR-E20-327"""
2224
spr_e20_327 = cec_module_spr_e20_327
@@ -38,7 +40,7 @@ def test_method_spr_e20_327(method, cec_module_spr_e20_327):
3840
assert np.isclose(pvs['i_xx'], out['i_xx'])
3941

4042

41-
@pytest.mark.parametrize('method', ['brentq', 'newton', 'chandrupatla'])
43+
@pytest.mark.parametrize('method', ['brentq', 'newton', chandrupatla])
4244
def test_newton_fs_495(method, cec_module_fs_495):
4345
"""test pvsystem.singlediode with different methods on FS495"""
4446
fs_495 = cec_module_fs_495
@@ -147,7 +149,7 @@ def precise_iv_curves(request):
147149

148150

149151
@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton',
150-
'chandrupatla'])
152+
chandrupatla])
151153
def test_singlediode_precision(method, precise_iv_curves):
152154
"""
153155
Tests the accuracy of singlediode. ivcurve_pnts is not tested.
@@ -189,7 +191,7 @@ def test_singlediode_lambert_negative_voc(mocker):
189191

190192

191193
@pytest.mark.parametrize('method', ['lambertw', 'brentq', 'newton',
192-
'chandrupatla'])
194+
chandrupatla])
193195
def test_v_from_i_i_from_v_precision(method, precise_iv_curves):
194196
"""
195197
Tests the accuracy of pvsystem.v_from_i and pvsystem.i_from_v.
@@ -258,7 +260,7 @@ def get_pvsyst_fs_495():
258260
)
259261
]
260262
)
261-
@pytest.mark.parametrize('method', ['newton', 'brentq', 'chandrupatla'])
263+
@pytest.mark.parametrize('method', ['newton', 'brentq', chandrupatla])
262264
def test_pvsyst_recombination_loss(method, poa, temp_cell, expected, tol):
263265
"""test PVSst recombination loss"""
264266
pvsyst_fs_495 = get_pvsyst_fs_495()
@@ -350,7 +352,7 @@ def test_pvsyst_recombination_loss(method, poa, temp_cell, expected, tol):
350352
)
351353
]
352354
)
353-
@pytest.mark.parametrize('method', ['newton', 'brentq', 'chandrupatla'])
355+
@pytest.mark.parametrize('method', ['newton', 'brentq', chandrupatla])
354356
def test_pvsyst_breakdown(method, brk_params, recomb_params, poa, temp_cell,
355357
expected, tol):
356358
"""test PVSyst recombination loss"""
@@ -460,6 +462,7 @@ def bishop88_arguments():
460462
'maxiter': 30,
461463
}),
462464
# can't include chandrupatla since the function is not available to patch
465+
# TODO: add this once chandrupatla becomes non-optional functionality
463466
#('chandrupatla', {
464467
# 'tolerances ': {'xtol': 1e-8, 'rtol': 1e-8},
465468
# 'maxiter': 30,
@@ -503,12 +506,12 @@ def test_bishop88_kwargs_transfer(method, method_kwargs, mocker,
503506
'maxiter': 20,
504507
'_inexistent_param': "0.01"
505508
}),
506-
('chandrupatla', {
509+
pytest.param('chandrupatla', {
507510
'xtol': 1e-4,
508511
'rtol': 1e-4,
509512
'maxiter': 20,
510513
'_inexistent_param': "0.01"
511-
}),
514+
}, marks=pytest.mark.skipif(not chandrupatla_available)),
512515
])
513516
def test_bishop88_kwargs_fails(method, method_kwargs, bishop88_arguments):
514517
"""test invalid method_kwargs passed onto the optimizer fail"""
@@ -526,7 +529,7 @@ def test_bishop88_kwargs_fails(method, method_kwargs, bishop88_arguments):
526529
method_kwargs=method_kwargs)
527530

528531

529-
@pytest.mark.parametrize('method', ['newton', 'brentq', 'chandrupatla'])
532+
@pytest.mark.parametrize('method', ['newton', 'brentq', chandrupatla])
530533
def test_bishop88_full_output_kwarg(method, bishop88_arguments):
531534
"""test call to bishop88_.* with full_output=True return values are ok"""
532535
method_kwargs = {'full_output': True}
@@ -560,7 +563,7 @@ def test_bishop88_full_output_kwarg(method, bishop88_arguments):
560563
assert len(ret_val[1]) >= 2
561564

562565

563-
@pytest.mark.parametrize('method', ['newton', 'brentq', 'chandrupatla'])
566+
@pytest.mark.parametrize('method', ['newton', 'brentq', chandrupatla])
564567
def test_bishop88_pdSeries_len_one(method, bishop88_arguments):
565568
for k, v in bishop88_arguments.items():
566569
bishop88_arguments[k] = pd.Series([v])
@@ -576,7 +579,7 @@ def _sde_check_solution(i, v, il, io, rs, rsh, a, d2mutau=0., NsVbi=np.inf):
576579
return il - io*np.expm1(vd/a) - vd/rsh - il*d2mutau/(NsVbi - vd) - i
577580

578581

579-
@pytest.mark.parametrize('method', ['newton', 'brentq', 'chandrupatla'])
582+
@pytest.mark.parametrize('method', ['newton', 'brentq', chandrupatla])
580583
def test_bishop88_init_cond(method):
581584
# GH 2013
582585
p = {'alpha_sc': 0.0012256,

0 commit comments

Comments
 (0)