-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathtest_pvcell.py
More file actions
150 lines (125 loc) · 4.46 KB
/
test_pvcell.py
File metadata and controls
150 lines (125 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
"""
Test pvcells.
"""
from nose.tools import ok_
from pvmismatch.pvmismatch_lib.pvcell import PVcell
from pvmismatch.pvmismatch_lib.pvconstants import PVconstants
import numpy as np
import os
BASE_DIR = os.path.dirname(__file__)
def test_pvcell_basic():
"""
test that pvcell returns a :class:`~pvmismatch.pvmismatch_lib.pvcell.PVcell`
object.
"""
pvc = PVcell()
ok_(isinstance(pvc, PVcell))
def test_pvcell_setattr_recalc():
pvc = PVcell()
i183 = pvc.Icell[183]
pvc.Tcell = 323
pvc.Ee = 0.65
ok_(pvc.Icell[183] != i183)
def test_pvcell_calc_icell():
pvc = PVcell()
ok_(np.isclose(pvc.Icell[123], pvc.calcIcell(pvc.Vcell[123])))
ok_(np.isclose(pvc.Icell[153], pvc.calcIcell(pvc.Vcell[153])))
ok_(np.isclose(pvc.Icell[183], pvc.calcIcell(pvc.Vcell[183])))
def test_pvcell_calc_vcell():
pvc = PVcell()
ok_(np.isclose(pvc.Vcell[123], pvc.calcVcell(pvc.Icell[123]), 1e-4))
ok_(np.isclose(pvc.Vcell[153], pvc.calcVcell(pvc.Icell[153]), 1e-4))
ok_(np.isclose(pvc.Vcell[183], pvc.calcVcell(pvc.Icell[183])))
def test_calc_series():
pvconst = PVconstants()
pvcells = [
PVcell(pvconst=pvconst, Tcell=323),
PVcell(pvconst=pvconst, Ee=0.75, Tcell=313),
PVcell(pvconst=pvconst, Ee=0.55, Tcell=303)
]
i_at_vrbd = np.asarray([np.interp(pvc.VRBD, pvc.Vcell.flat, pvc.Icell.flat)
for pvc in pvcells])
icells = np.asarray([pvc.Icell.flatten() for pvc in pvcells])
vcells = np.asarray([pvc.Vcell.flatten() for pvc in pvcells])
isc = np.asarray([pvc.Isc for pvc in pvcells])
i, v = pvconst.calcSeries(icells, vcells, isc.mean(), i_at_vrbd.max())
iv_old = np.loadtxt(os.path.join(BASE_DIR, 'calc_series_test_iv_old.dat'))
iv_expected = np.loadtxt(
os.path.join(BASE_DIR, 'calc_series_test_iv.dat'))
# noinspection PyTypeChecker
iv_calc = np.concatenate([[i], [v]], axis=0).T
# noinspection PyTypeChecker
ok_(np.allclose(iv_calc, iv_expected))
assert np.allclose(iv_old[0,:], np.interp(iv_old[1,:], v, i), 0.01, 0.01)
assert np.allclose(
iv_old[1,:],
np.interp(iv_old[0,:], np.flipud(i), np.flipud(v)), 0.1, 0.1)
return i, v
def test_pvcell_calc_rbd():
pvc1 = PVcell(bRBD=0.)
ok_(isinstance(pvc1, PVcell))
pvc2 = PVcell(bRBD=-0.056)
ok_(isinstance(pvc2, PVcell))
def test_pvcell_calc_now_flag():
"""
Test ``_calc_now`` turns off recalc in ``__setattr__``.
"""
pvc = PVcell()
itest, vtest, ptest = pvc.Icell, pvc.Vcell, pvc.Pcell
pvc._calc_now = False
pvc.Rs = 0.001
assert np.allclose(itest, pvc.Icell)
assert np.allclose(vtest, pvc.Vcell)
assert np.allclose(ptest, pvc.Pcell)
icell, vcell, pcell = pvc.calcCell()
pvc._calc_now = True
assert np.allclose(icell, pvc.Icell)
assert np.allclose(vcell, pvc.Vcell)
assert np.allclose(pcell, pvc.Pcell)
def test_update():
pvc = PVcell()
Rs = pvc.Rs
itest = pvc.Icell[170]
pvc.update(Rs=0.001)
assert np.isclose(pvc.Icell[170], 5.79691674)
pvc._calc_now = False
pvc.Rs = Rs
pvc.update() # resets _calc_now to True
assert np.isclose(pvc.Icell[170], itest)
assert pvc._calc_now
def test_cache(mocker):
"""
Test that the cache mechanism actually works and doesn't calculate the same
thing more than once.
"""
pvc = PVcell()
attrs = ['Vt', 'Isc', 'Aph', 'Isat1', 'Isat2', 'Isc0', 'Voc', 'Igen']
# it's a little tricky to get ahold of the underlying function for the
# properties -- by accessing the property through the class rather than
# the instance, we get access to the `fget` object, which is the wrapper
# function. And the @cached decorator stores the underlying function
# in the __wrapped__ attribute on the wrapper.
spies = [
mocker.spy(getattr(PVcell, attr).fget, "__wrapped__")
for attr in attrs
]
pvc.Ee = 0.5
for spy in spies:
spy.assert_called_once()
def test_clone():
"""
Test that the clone method returns an independent object.
"""
# test independence
pvc1 = PVcell()
pvc2 = pvc1.clone()
pvc1.Ee = 0.5
assert pvc2.Ee == 1.0
# test returns identical
pvc3 = pvc1.clone()
assert np.allclose(pvc1.calcCell(), pvc3.calcCell())
assert pvc1.pvconst is pvc3.pvconst
if __name__ == "__main__":
i, v = test_calc_series()
iv_calc = np.concatenate([[i], [v]], axis=0).T
np.savetxt(os.path.join(BASE_DIR, 'calc_series_test_iv.dat'), iv_calc)