pvlib 0.11.2__py3-none-any.whl → 0.12.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. pvlib/__init__.py +1 -0
  2. pvlib/atmosphere.py +0 -9
  3. pvlib/bifacial/infinite_sheds.py +4 -3
  4. pvlib/bifacial/utils.py +2 -1
  5. pvlib/iotools/psm3.py +1 -1
  6. pvlib/iotools/pvgis.py +10 -2
  7. pvlib/iotools/tmy.py +3 -69
  8. pvlib/irradiance.py +14 -0
  9. pvlib/location.py +73 -33
  10. pvlib/modelchain.py +18 -35
  11. pvlib/pvsystem.py +7 -10
  12. pvlib/snow.py +64 -28
  13. pvlib/spectrum/__init__.py +0 -1
  14. pvlib/spectrum/irradiance.py +0 -63
  15. pvlib/spectrum/mismatch.py +3 -3
  16. pvlib/tools.py +6 -5
  17. {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/METADATA +5 -3
  18. pvlib-0.12.0.dist-info/RECORD +75 -0
  19. {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
  20. pvlib/data/BIRD_08_16_2012.csv +0 -8761
  21. pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
  22. pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
  23. pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
  24. pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
  25. pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
  26. pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
  27. pvlib/data/CRN_with_problems.txt +0 -3
  28. pvlib/data/ET-M772BH550GL.PAN +0 -75
  29. pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
  30. pvlib/data/PVsyst_demo.csv +0 -10757
  31. pvlib/data/PVsyst_demo_model.csv +0 -3588
  32. pvlib/data/SRML-day-EUPO1801.txt +0 -1441
  33. pvlib/data/abq19056.dat +0 -6
  34. pvlib/data/bishop88_numerical_precision.csv +0 -101
  35. pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
  36. pvlib/data/bsrn-pay0616.dat.gz +0 -0
  37. pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
  38. pvlib/data/cams_mcclear_monthly.csv +0 -42
  39. pvlib/data/cams_radiation_1min_verbose.csv +0 -72
  40. pvlib/data/cams_radiation_monthly.csv +0 -47
  41. pvlib/data/detect_clearsky_data.csv +0 -35
  42. pvlib/data/detect_clearsky_threshold_data.csv +0 -126
  43. pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
  44. pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
  45. pvlib/data/inverter_fit_snl_meas.csv +0 -127
  46. pvlib/data/inverter_fit_snl_sim.csv +0 -19
  47. pvlib/data/ivtools_numdiff.csv +0 -52
  48. pvlib/data/midc_20181014.txt +0 -1441
  49. pvlib/data/midc_raw_20181018.txt +0 -1441
  50. pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
  51. pvlib/data/msn19056.dat +0 -6
  52. pvlib/data/precise_iv_curves1.json +0 -10251
  53. pvlib/data/precise_iv_curves2.json +0 -10251
  54. pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
  55. pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
  56. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
  57. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
  58. pvlib/data/pvgis_tmy_meta.json +0 -32
  59. pvlib/data/pvgis_tmy_test.csv +0 -8761
  60. pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
  61. pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
  62. pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
  63. pvlib/data/spectrl2_example_spectra.csv +0 -123
  64. pvlib/data/surfrad-slv16001.dat +0 -1442
  65. pvlib/data/test_psm3_2017.csv +0 -17521
  66. pvlib/data/test_psm3_2019_5min.csv +0 -289
  67. pvlib/data/test_psm3_tmy-2017.csv +0 -8761
  68. pvlib/data/test_read_psm3.csv +0 -17523
  69. pvlib/data/test_read_pvgis_horizon.csv +0 -49
  70. pvlib/data/tmy_45.000_8.000_2005_2023.csv +0 -8789
  71. pvlib/data/tmy_45.000_8.000_2005_2023.epw +0 -8768
  72. pvlib/data/tmy_45.000_8.000_2005_2023.json +0 -1
  73. pvlib/data/tmy_45.000_8.000_2005_2023.txt +0 -8761
  74. pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
  75. pvlib/spa_c_files/README.md +0 -81
  76. pvlib/spa_c_files/cspa_py.pxd +0 -43
  77. pvlib/spa_c_files/spa_py.pyx +0 -30
  78. pvlib/tests/__init__.py +0 -0
  79. pvlib/tests/bifacial/__init__.py +0 -0
  80. pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
  81. pvlib/tests/bifacial/test_losses_models.py +0 -54
  82. pvlib/tests/bifacial/test_pvfactors.py +0 -82
  83. pvlib/tests/bifacial/test_utils.py +0 -192
  84. pvlib/tests/conftest.py +0 -476
  85. pvlib/tests/iotools/__init__.py +0 -0
  86. pvlib/tests/iotools/test_acis.py +0 -213
  87. pvlib/tests/iotools/test_bsrn.py +0 -131
  88. pvlib/tests/iotools/test_crn.py +0 -95
  89. pvlib/tests/iotools/test_epw.py +0 -23
  90. pvlib/tests/iotools/test_midc.py +0 -89
  91. pvlib/tests/iotools/test_panond.py +0 -32
  92. pvlib/tests/iotools/test_psm3.py +0 -198
  93. pvlib/tests/iotools/test_pvgis.py +0 -644
  94. pvlib/tests/iotools/test_sodapro.py +0 -298
  95. pvlib/tests/iotools/test_solaranywhere.py +0 -287
  96. pvlib/tests/iotools/test_solargis.py +0 -68
  97. pvlib/tests/iotools/test_solcast.py +0 -324
  98. pvlib/tests/iotools/test_solrad.py +0 -152
  99. pvlib/tests/iotools/test_srml.py +0 -124
  100. pvlib/tests/iotools/test_surfrad.py +0 -75
  101. pvlib/tests/iotools/test_tmy.py +0 -133
  102. pvlib/tests/ivtools/__init__.py +0 -0
  103. pvlib/tests/ivtools/test_sde.py +0 -230
  104. pvlib/tests/ivtools/test_sdm.py +0 -429
  105. pvlib/tests/ivtools/test_utils.py +0 -173
  106. pvlib/tests/spectrum/__init__.py +0 -0
  107. pvlib/tests/spectrum/conftest.py +0 -40
  108. pvlib/tests/spectrum/test_irradiance.py +0 -138
  109. pvlib/tests/spectrum/test_mismatch.py +0 -304
  110. pvlib/tests/spectrum/test_response.py +0 -124
  111. pvlib/tests/spectrum/test_spectrl2.py +0 -72
  112. pvlib/tests/test__deprecation.py +0 -97
  113. pvlib/tests/test_albedo.py +0 -84
  114. pvlib/tests/test_atmosphere.py +0 -351
  115. pvlib/tests/test_clearsky.py +0 -884
  116. pvlib/tests/test_conftest.py +0 -37
  117. pvlib/tests/test_iam.py +0 -555
  118. pvlib/tests/test_inverter.py +0 -213
  119. pvlib/tests/test_irradiance.py +0 -1487
  120. pvlib/tests/test_location.py +0 -356
  121. pvlib/tests/test_modelchain.py +0 -2020
  122. pvlib/tests/test_numerical_precision.py +0 -124
  123. pvlib/tests/test_pvarray.py +0 -71
  124. pvlib/tests/test_pvsystem.py +0 -2511
  125. pvlib/tests/test_scaling.py +0 -207
  126. pvlib/tests/test_shading.py +0 -391
  127. pvlib/tests/test_singlediode.py +0 -608
  128. pvlib/tests/test_snow.py +0 -212
  129. pvlib/tests/test_soiling.py +0 -230
  130. pvlib/tests/test_solarposition.py +0 -966
  131. pvlib/tests/test_spa.py +0 -454
  132. pvlib/tests/test_temperature.py +0 -470
  133. pvlib/tests/test_tools.py +0 -146
  134. pvlib/tests/test_tracking.py +0 -474
  135. pvlib/tests/test_transformer.py +0 -60
  136. pvlib-0.11.2.dist-info/RECORD +0 -191
  137. {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
  138. {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
  139. {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
@@ -1,429 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
- from scipy import optimize
4
-
5
- import pytest
6
- from numpy.testing import assert_allclose
7
-
8
- from pvlib.ivtools import sdm
9
- from pvlib import pvsystem
10
-
11
- from pvlib.tests.conftest import requires_pysam, requires_statsmodels
12
-
13
- from ..conftest import DATA_DIR
14
-
15
-
16
- @pytest.fixture
17
- def get_test_iv_params():
18
- return {'IL': 8.0, 'I0': 5e-10, 'Rsh': 1000, 'Rs': 0.2, 'nNsVth': 1.61864}
19
-
20
-
21
- @pytest.fixture
22
- def cec_params_cansol_cs5p_220p():
23
- return {'ivcurve': {'V_mp_ref': 46.6, 'I_mp_ref': 4.73, 'V_oc_ref': 58.3,
24
- 'I_sc_ref': 5.05},
25
- 'specs': {'alpha_sc': 0.0025, 'beta_voc': -0.19659,
26
- 'gamma_pmp': -0.43, 'cells_in_series': 96},
27
- 'params': {'I_L_ref': 5.056, 'I_o_ref': 1.01e-10,
28
- 'R_sh_ref': 837.51, 'R_s': 1.004, 'a_ref': 2.3674,
29
- 'Adjust': 2.3}}
30
-
31
-
32
- @requires_pysam
33
- def test_fit_cec_sam(cec_params_cansol_cs5p_220p):
34
- input_data = cec_params_cansol_cs5p_220p['ivcurve']
35
- specs = cec_params_cansol_cs5p_220p['specs']
36
- I_L_ref, I_o_ref, R_s, R_sh_ref, a_ref, Adjust = \
37
- sdm.fit_cec_sam(
38
- celltype='polySi', v_mp=input_data['V_mp_ref'],
39
- i_mp=input_data['I_mp_ref'], v_oc=input_data['V_oc_ref'],
40
- i_sc=input_data['I_sc_ref'], alpha_sc=specs['alpha_sc'],
41
- beta_voc=specs['beta_voc'],
42
- gamma_pmp=specs['gamma_pmp'],
43
- cells_in_series=specs['cells_in_series'])
44
- expected = pd.Series(cec_params_cansol_cs5p_220p['params'])
45
- modeled = pd.Series(index=expected.index, data=np.nan)
46
- modeled['a_ref'] = a_ref
47
- modeled['I_L_ref'] = I_L_ref
48
- modeled['I_o_ref'] = I_o_ref
49
- modeled['R_s'] = R_s
50
- modeled['R_sh_ref'] = R_sh_ref
51
- modeled['Adjust'] = Adjust
52
- assert np.allclose(modeled.values, expected.values, rtol=5e-2)
53
-
54
-
55
- @requires_pysam
56
- def test_fit_cec_sam_estimation_failure(cec_params_cansol_cs5p_220p):
57
- # Failing to estimate the parameters for the CEC SDM model should raise an
58
- # exception.
59
- with pytest.raises(RuntimeError):
60
- sdm.fit_cec_sam(celltype='polySi', v_mp=0.45, i_mp=5.25, v_oc=0.55,
61
- i_sc=5.5, alpha_sc=0.00275, beta_voc=0.00275,
62
- gamma_pmp=0.0055, cells_in_series=1, temp_ref=25)
63
-
64
-
65
- def test_fit_desoto():
66
- result, _ = sdm.fit_desoto(v_mp=31.0, i_mp=8.71, v_oc=38.3, i_sc=9.43,
67
- alpha_sc=0.005658, beta_voc=-0.13788,
68
- cells_in_series=60)
69
- result_expected = {'I_L_ref': 9.45232,
70
- 'I_o_ref': 3.22460e-10,
71
- 'R_s': 0.297814,
72
- 'R_sh_ref': 125.798,
73
- 'a_ref': 1.59128,
74
- 'alpha_sc': 0.005658,
75
- 'EgRef': 1.121,
76
- 'dEgdT': -0.0002677,
77
- 'irrad_ref': 1000,
78
- 'temp_ref': 25}
79
- assert np.allclose(pd.Series(result), pd.Series(result_expected),
80
- rtol=1e-4)
81
-
82
-
83
- def test_fit_desoto_init_guess(mocker):
84
- init_guess_array = np.array([9.4, 3.0e-10, 0.3, 125., 1.6])
85
- init_guess = {k: v for k, v in zip(
86
- ['IL_0', 'Io_0', 'Rs_0', 'Rsh_0', 'a_0'], init_guess_array)}
87
- spy = mocker.spy(optimize, 'root')
88
- result, _ = sdm.fit_desoto(v_mp=31.0, i_mp=8.71, v_oc=38.3, i_sc=9.43,
89
- alpha_sc=0.005658, beta_voc=-0.13788,
90
- cells_in_series=60, init_guess=init_guess)
91
- np.testing.assert_array_equal(init_guess_array, spy.call_args[1]['x0'])
92
-
93
-
94
- def test_fit_desoto_init_bad_key():
95
- init_guess = {'IL_0': 6., 'bad_key': 0}
96
- with pytest.raises(ValueError, match='is not a valid name;'):
97
- result, _ = sdm.fit_desoto(v_mp=31.0, i_mp=8.71, v_oc=38.3, i_sc=9.43,
98
- alpha_sc=0.005658, beta_voc=-0.13788,
99
- cells_in_series=60, init_guess=init_guess)
100
-
101
-
102
- def test_fit_desoto_failure():
103
- with pytest.raises(RuntimeError) as exc:
104
- sdm.fit_desoto(v_mp=31.0, i_mp=8.71, v_oc=38.3, i_sc=9.43,
105
- alpha_sc=0.005658, beta_voc=-0.13788,
106
- cells_in_series=10)
107
- assert ('Parameter estimation failed') in str(exc.value)
108
-
109
-
110
- @requires_statsmodels
111
- def test_fit_desoto_sandia(cec_params_cansol_cs5p_220p):
112
- # this test computes a set of IV curves for the input fixture, fits
113
- # the De Soto model to the calculated IV curves, and compares the fitted
114
- # parameters to the starting values
115
- params = cec_params_cansol_cs5p_220p['params']
116
- params.pop('Adjust')
117
- specs = cec_params_cansol_cs5p_220p['specs']
118
- effective_irradiance = np.array([400., 500., 600., 700., 800., 900.,
119
- 1000.])
120
- temp_cell = np.array([15., 25., 35., 45.])
121
- ee = np.tile(effective_irradiance, len(temp_cell))
122
- tc = np.repeat(temp_cell, len(effective_irradiance))
123
- IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
124
- ee, tc, alpha_sc=specs['alpha_sc'], **params)
125
- ivcurve_params = dict(photocurrent=IL, saturation_current=I0,
126
- resistance_series=Rs, resistance_shunt=Rsh,
127
- nNsVth=nNsVth)
128
- sim_ivcurves = pvsystem.singlediode(**ivcurve_params).to_dict('series')
129
- v = np.linspace(0., sim_ivcurves['v_oc'], 300)
130
- i = pvsystem.i_from_v(voltage=v, **ivcurve_params)
131
- sim_ivcurves.update(v=v.T, i=i.T, ee=ee, tc=tc)
132
-
133
- result = sdm.fit_desoto_sandia(sim_ivcurves, specs)
134
- modeled = pd.Series(index=params.keys(), data=np.nan)
135
- modeled['a_ref'] = result['a_ref']
136
- modeled['I_L_ref'] = result['I_L_ref']
137
- modeled['I_o_ref'] = result['I_o_ref']
138
- modeled['R_s'] = result['R_s']
139
- modeled['R_sh_ref'] = result['R_sh_ref']
140
- expected = pd.Series(params)
141
- assert np.allclose(modeled[params.keys()].values,
142
- expected[params.keys()].values, rtol=5e-2)
143
- assert_allclose(result['dEgdT'], -0.0002677)
144
- assert_allclose(result['EgRef'], 1.3112547292120638)
145
- assert_allclose(result['cells_in_series'], specs['cells_in_series'])
146
-
147
-
148
- def _read_iv_curves_for_test(datafile, npts):
149
- """ read constants and npts IV curves from datafile """
150
- iv_specs = dict.fromkeys(['cells_in_series', 'alpha_sc', 'beta_voc',
151
- 'descr'])
152
- ivcurves = dict.fromkeys(['i_sc', 'i_mp', 'v_mp', 'v_oc', 'poa', 'tc',
153
- 'ee'])
154
-
155
- infilen = DATA_DIR / datafile
156
- with infilen.open(mode='r') as f:
157
-
158
- Ns, aIsc, bVoc, descr = f.readline().split(',')
159
-
160
- iv_specs.update(
161
- cells_in_series=int(Ns), alpha_sc=float(aIsc),
162
- beta_voc=float(bVoc), descr=descr)
163
-
164
- strN, strM = f.readline().split(',')
165
- N = int(strN)
166
- M = int(strM)
167
-
168
- isc = np.empty(N)
169
- imp = np.empty(N)
170
- vmp = np.empty(N)
171
- voc = np.empty(N)
172
- ee = np.empty(N)
173
- poa = np.empty(N)
174
- tc = np.empty(N)
175
- v = np.empty((N, M))
176
- i = np.empty((N, M))
177
- v[:] = np.nan # fill with nan
178
- i[:] = np.nan
179
-
180
- for k in range(N):
181
- tmp = (float(x) for x in f.readline().split(','))
182
- isc[k], imp[k], vmp[k], voc[k], poa[k], tc[k], ee[k] = tmp
183
- # read voltage and current
184
- tmp = [float(x) for x in f.readline().split(',')]
185
- while len(tmp) < M:
186
- tmp.append(np.nan)
187
- v[k, :] = tmp
188
- tmp = [float(x) for x in f.readline().split(',')]
189
- while len(tmp) < M:
190
- tmp.append(np.nan)
191
- i[k, :] = tmp
192
-
193
- ivcurves['i_sc'] = isc[:npts]
194
- ivcurves['i_mp'] = imp[:npts]
195
- ivcurves['v_oc'] = voc[:npts]
196
- ivcurves['v_mp'] = vmp[:npts]
197
- ivcurves['ee'] = ee[:npts]
198
- ivcurves['tc'] = tc[:npts]
199
- ivcurves['v'] = v[:npts]
200
- ivcurves['i'] = i[:npts]
201
- ivcurves['p_mp'] = ivcurves['v_mp'] * ivcurves['i_mp'] # power
202
-
203
- return iv_specs, ivcurves
204
-
205
-
206
- def _read_pvsyst_expected(datafile):
207
- """ Read Pvsyst model parameters and diode equation values for each
208
- IV curve
209
- """
210
- pvsyst_specs = dict.fromkeys(['cells_in_series', 'alpha_sc', 'beta_voc',
211
- 'descr'])
212
- # order required to match file being read
213
- paramlist = [
214
- 'I_L_ref', 'I_o_ref', 'EgRef', 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s',
215
- 'gamma_ref', 'mu_gamma']
216
- varlist = ['iph', 'io', 'rs', 'rsh', 'u']
217
- pvsyst = dict.fromkeys(paramlist + varlist)
218
-
219
- infilen = DATA_DIR / datafile
220
- with infilen.open(mode='r') as f:
221
-
222
- Ns, aIsc, bVoc, descr = f.readline().split(',')
223
-
224
- pvsyst_specs.update(
225
- cells_in_series=int(Ns), alpha_sc=float(aIsc),
226
- beta_voc=float(bVoc), descr=descr)
227
-
228
- tmp = [float(x) for x in f.readline().split(',')]
229
- # I_L_ref, I_o_ref, EgRef, R_s, R_sh_ref, R_sh_0, R_sh_exp, gamma_ref,
230
- # mu_gamma
231
- pvsyst.update(zip(paramlist, tmp))
232
-
233
- strN = f.readline()
234
- N = int(strN)
235
-
236
- Iph = np.empty(N)
237
- Io = np.empty(N)
238
- Rsh = np.empty(N)
239
- Rs = np.empty(N)
240
- u = np.empty(N)
241
-
242
- for k in range(N):
243
- tmp = [float(x) for x in f.readline().split(',')]
244
- Iph[k], Io[k], Rsh[k], Rs[k], u[k] = tmp
245
-
246
- pvsyst.update(zip(varlist, [Iph, Io, Rs, Rsh, u]))
247
-
248
- return pvsyst_specs, pvsyst
249
-
250
-
251
- @requires_statsmodels
252
- def test_fit_pvsyst_sandia(npts=3000):
253
-
254
- # get IV curve data
255
- iv_specs, ivcurves = _read_iv_curves_for_test('PVsyst_demo.csv', npts)
256
-
257
- # get known Pvsyst model parameters and five parameters from each fitted
258
- # IV curve
259
- pvsyst_specs, pvsyst = _read_pvsyst_expected('PVsyst_demo_model.csv')
260
-
261
- modeled = sdm.fit_pvsyst_sandia(ivcurves, iv_specs)
262
-
263
- # calculate IV curves using the fitted model, for comparison with input
264
- # IV curves
265
- param_res = pvsystem.calcparams_pvsyst(
266
- effective_irradiance=ivcurves['ee'], temp_cell=ivcurves['tc'],
267
- alpha_sc=iv_specs['alpha_sc'], gamma_ref=modeled['gamma_ref'],
268
- mu_gamma=modeled['mu_gamma'], I_L_ref=modeled['I_L_ref'],
269
- I_o_ref=modeled['I_o_ref'], R_sh_ref=modeled['R_sh_ref'],
270
- R_sh_0=modeled['R_sh_0'], R_s=modeled['R_s'],
271
- cells_in_series=iv_specs['cells_in_series'], EgRef=modeled['EgRef'])
272
- iv_res = pvsystem.singlediode(*param_res)
273
-
274
- # assertions
275
- assert np.allclose(
276
- ivcurves['p_mp'], iv_res['p_mp'], equal_nan=True, rtol=0.038)
277
- assert np.allclose(
278
- ivcurves['v_mp'], iv_res['v_mp'], equal_nan=True, rtol=0.029)
279
- assert np.allclose(
280
- ivcurves['i_mp'], iv_res['i_mp'], equal_nan=True, rtol=0.021)
281
- assert np.allclose(
282
- ivcurves['i_sc'], iv_res['i_sc'], equal_nan=True, rtol=0.003)
283
- assert np.allclose(
284
- ivcurves['v_oc'], iv_res['v_oc'], equal_nan=True, rtol=0.019)
285
- # cells_in_series, alpha_sc, beta_voc, descr
286
- assert all((iv_specs[k] == pvsyst_specs[k]) for k in iv_specs.keys())
287
- # I_L_ref, I_o_ref, EgRef, R_sh_ref, R_sh_0, R_sh_exp, R_s, gamma_ref,
288
- # mu_gamma
289
- assert np.isclose(modeled['I_L_ref'], pvsyst['I_L_ref'], rtol=6.5e-5)
290
- assert np.isclose(modeled['I_o_ref'], pvsyst['I_o_ref'], rtol=0.15)
291
- assert np.isclose(modeled['R_s'], pvsyst['R_s'], rtol=0.0035)
292
- assert np.isclose(modeled['R_sh_ref'], pvsyst['R_sh_ref'], rtol=0.091)
293
- assert np.isclose(modeled['R_sh_0'], pvsyst['R_sh_0'], rtol=0.013)
294
- assert np.isclose(modeled['EgRef'], pvsyst['EgRef'], rtol=0.037)
295
- assert np.isclose(modeled['gamma_ref'], pvsyst['gamma_ref'], rtol=0.0045)
296
- assert np.isclose(modeled['mu_gamma'], pvsyst['mu_gamma'], rtol=0.064)
297
-
298
- # Iph, Io, Rsh, Rs, u
299
- mask = np.ones(modeled['u'].shape, dtype=bool)
300
- # exclude one curve with different convergence
301
- umask = mask.copy()
302
- umask[2540] = False
303
- assert all(modeled['u'][umask] == pvsyst['u'][:npts][umask])
304
- assert np.allclose(
305
- modeled['iph'][modeled['u']], pvsyst['iph'][:npts][modeled['u']],
306
- equal_nan=True, rtol=0.0009)
307
- assert np.allclose(
308
- modeled['io'][modeled['u']], pvsyst['io'][:npts][modeled['u']],
309
- equal_nan=True, rtol=0.096)
310
- assert np.allclose(
311
- modeled['rs'][modeled['u']], pvsyst['rs'][:npts][modeled['u']],
312
- equal_nan=True, rtol=0.035)
313
- # exclude one curve with Rsh outside 63% tolerance
314
- rshmask = modeled['u'].copy()
315
- rshmask[2545] = False
316
- assert np.allclose(
317
- modeled['rsh'][rshmask], pvsyst['rsh'][:npts][rshmask],
318
- equal_nan=True, rtol=0.63)
319
-
320
-
321
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth, expected', [
322
- (2., 2., 2., 2., 2., 2., 2., np.nan),
323
- (2., 2., 0., 2., 2., 2., 2., np.nan),
324
- (2., 2., 2., 0., 2., 2., 2., np.nan),
325
- (2., 2., 2., 2., 0., 2., 2., np.nan),
326
- (2., 2., 2., 2., 2., 0., 2., np.nan),
327
- (2., 2., 2., 2., 2., 2., 0., np.nan)])
328
- def test__update_rsh_fixed_pt_nans(vmp, imp, iph, io, rs, rsh, nnsvth,
329
- expected):
330
- outrsh = sdm._update_rsh_fixed_pt(vmp, imp, iph, io, rs, rsh, nnsvth)
331
- assert np.all(np.isnan(outrsh))
332
-
333
-
334
- def test__update_rsh_fixed_pt_vmp0():
335
- outrsh = sdm._update_rsh_fixed_pt(vmp=0., imp=2., iph=2., io=2., rs=2.,
336
- rsh=2., nnsvth=2.)
337
- assert_allclose(outrsh, np.array([502.]), atol=.0001)
338
-
339
-
340
- def test__update_rsh_fixed_pt_vector():
341
- outrsh = sdm._update_rsh_fixed_pt(rsh=np.array([-1., 3, .5, 2.]),
342
- rs=np.array([1., -.5, 2., 2.]),
343
- io=np.array([.2, .3, -.4, 2.]),
344
- iph=np.array([-.1, 1, 3., 2.]),
345
- nnsvth=np.array([4., -.2, .1, 2.]),
346
- imp=np.array([.2, .2, -1., 2.]),
347
- vmp=np.array([0., -1, 0., 0.]))
348
- assert np.all(np.isnan(outrsh[0:3]))
349
- assert_allclose(outrsh[3], np.array([502.]), atol=.0001)
350
-
351
-
352
- @pytest.mark.parametrize('voc, iph, io, rs, rsh, nnsvth, expected', [
353
- (2., 2., 2., 2., 2., 2., 0.5911),
354
- (2., 2., 2., 0., 2., 2., 0.5911),
355
- (2., 2., 0., 2., 2., 2., 0.),
356
- (2., 0., 2., 2., 2., 2., 1.0161e-4),
357
- (0., 2., 2., 2., 2., 2., 17.9436)])
358
- def test__update_io(voc, iph, io, rs, rsh, nnsvth, expected):
359
- outio = sdm._update_io(voc, iph, io, rs, rsh, nnsvth)
360
- assert_allclose(outio, expected, atol=.0001)
361
-
362
-
363
- @pytest.mark.parametrize('voc, iph, io, rs, rsh, nnsvth', [
364
- (2., 2., 2., 2., 2., 0.),
365
- (-1., -1., -1., -1., -1., -1.)])
366
- def test__update_io_nan(voc, iph, io, rs, rsh, nnsvth):
367
- outio = sdm._update_io(voc, iph, io, rs, rsh, nnsvth)
368
- assert np.isnan(outio)
369
-
370
-
371
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth, expected', [
372
- (2., 2., 2., 2., 2., 2., 2., (1.8726, 2.)),
373
- (2., 0., 2., 2., 2., 2., 2., (1.8726, 3.4537)),
374
- (2., 2., 0., 2., 2., 2., 2., (1.2650, 0.8526)),
375
- (0., 2., 2., 2., 2., 2., 2., (1.5571, 2.))])
376
- def test__calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth, expected):
377
- theta, phi = sdm._calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth)
378
- assert_allclose(theta, expected[0], atol=.0001)
379
- assert_allclose(phi, expected[1], atol=.0001)
380
-
381
-
382
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth', [
383
- (2., 2., 2., 0., 2., 2., 2.),
384
- (2., 2., 2., 2., 2., 2., 0.),
385
- (2., 0., 2., 2., 2., 0., 2.)])
386
- def test__calc_theta_phi_exact_both_nan(vmp, imp, iph, io, rs, rsh, nnsvth):
387
- theta, phi = sdm._calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth)
388
- assert np.isnan(theta)
389
- assert np.isnan(phi)
390
-
391
-
392
- def test__calc_theta_phi_exact_one_nan():
393
- theta, phi = sdm._calc_theta_phi_exact(imp=2., iph=2., vmp=2., io=2.,
394
- nnsvth=2., rs=0., rsh=2.)
395
- assert np.isnan(theta)
396
- assert_allclose(phi, 2., atol=.0001)
397
-
398
-
399
- def test__calc_theta_phi_exact_vector():
400
- theta, phi = sdm._calc_theta_phi_exact(imp=np.array([1., -1.]),
401
- iph=np.array([-1., 1.]),
402
- vmp=np.array([1., -1.]),
403
- io=np.array([-1., 1.]),
404
- nnsvth=np.array([1., -1.]),
405
- rs=np.array([-1., 1.]),
406
- rsh=np.array([1., -1.]))
407
- assert np.isnan(theta[0])
408
- assert np.isnan(theta[1])
409
- assert np.isnan(phi[0])
410
- assert_allclose(phi[1], 2.2079, atol=.0001)
411
-
412
-
413
- def test_pvsyst_temperature_coeff():
414
- # test for consistency with dP/dT estimated with secant rule
415
- params = {'alpha_sc': 0., 'gamma_ref': 1.1, 'mu_gamma': 0.,
416
- 'I_L_ref': 6., 'I_o_ref': 5.e-9, 'R_sh_ref': 200.,
417
- 'R_sh_0': 2000., 'R_s': 0.5, 'cells_in_series': 60}
418
- expected = -0.004886706494879083
419
- # params defines a Pvsyst model for a notional module.
420
- # expected value is created by calculating power at 1000 W/m2, and cell
421
- # temperature of 24 and 26C, using pvsystem.calcparams_pvsyst and
422
- # pvsystem.singlediode. The derivative (value for expected) is estimated
423
- # as the slope (p_mp at 26C - p_mp at 24C) / 2
424
- # using the secant rule for derivatives.
425
- gamma_pdc = sdm.pvsyst_temperature_coeff(
426
- params['alpha_sc'], params['gamma_ref'], params['mu_gamma'],
427
- params['I_L_ref'], params['I_o_ref'], params['R_sh_ref'],
428
- params['R_sh_0'], params['R_s'], params['cells_in_series'])
429
- assert_allclose(gamma_pdc, expected, rtol=0.0005)
@@ -1,173 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
- import pytest
4
- from pvlib.ivtools.utils import _numdiff, rectify_iv_curve, astm_e1036
5
- from pvlib.ivtools.utils import _schumaker_qspline
6
-
7
- from ..conftest import DATA_DIR
8
-
9
-
10
- @pytest.fixture
11
- def ivcurve():
12
- voltage = np.array([0., 1., 5., 10., 25., 25.00001, 30., 28., 45., 47.,
13
- 49., 51., np.nan])
14
- current = np.array([7., 6., 6., 5., 4., 3., 2.7, 2.5, np.nan, 0.5, -1., 0.,
15
- np.nan])
16
- return voltage, current
17
-
18
-
19
- def test__numdiff():
20
- iv = pd.read_csv(DATA_DIR / 'ivtools_numdiff.csv',
21
- names=['I', 'V', 'dIdV', 'd2IdV2'], dtype=float)
22
- df, d2f = _numdiff(iv.V, iv.I)
23
- assert np.allclose(iv.dIdV, df, equal_nan=True)
24
- assert np.allclose(iv.d2IdV2, d2f, equal_nan=True)
25
-
26
-
27
- def test_rectify_iv_curve(ivcurve):
28
- voltage, current = ivcurve
29
-
30
- vexp_no_dec = np.array([0., 1., 5., 10., 25., 25.00001, 28., 30., 47.,
31
- 51.])
32
- iexp_no_dec = np.array([7., 6., 6., 5., 4., 3., 2.5, 2.7, 0.5, 0.])
33
- v, i = rectify_iv_curve(voltage, current)
34
- np.testing.assert_allclose(v, vexp_no_dec, atol=.0001)
35
- np.testing.assert_allclose(i, iexp_no_dec, atol=.0001)
36
-
37
- vexp = np.array([0., 1., 5., 10., 25., 28., 30., 47., 51.])
38
- iexp = np.array([7., 6., 6., 5., 3.5, 2.5, 2.7, 0.5, 0.])
39
- v, i = rectify_iv_curve(voltage, current, decimals=4)
40
- np.testing.assert_allclose(v, vexp, atol=.0001)
41
- np.testing.assert_allclose(i, iexp, atol=.0001)
42
-
43
-
44
- @pytest.mark.parametrize('x,y,expected', [
45
- (np.array([0., 1., 2., 3., 4., 1., 2., 3., 4., 5.]),
46
- np.array([2., 1., 0., 1., 2., 3., 2., 1., 2., 3.]),
47
- (np.array([[0., -1., 2.], [-0.5, -1., 1.], [-0.75, -0.5, 3.],
48
- [0.75, -1.5, 0.375], [0.125, -1.25, 2.5625], [1.5, 0., 0.],
49
- [-0.5, -1., 2.], [-0.25, 1.5, 0.375], [0.75, -1.5, 1.375],
50
- [0.5, 1., 1.], [1.5, 0., 1.], [0.0278, -0.3333, 2.1667],
51
- [-0.75, 1.5, 1.625], [-0.25, 1.5, 1.375], [0.1667, 0., 2.],
52
- [0., 1., 2.]]),
53
- np.array([0., 1., 1., 1.5, 1.5, 2., 2., 2.5, 2.5, 3., 3., 3., 3.5, 3.5,
54
- 4., 4., 5.]),
55
- np.array([2., 1., 3., 0.375, 2.5625, 0., 2., 0.375, 1.375, 1., 1.,
56
- 2.1667, 1.625, 1.375, 2., 2., 3.]),
57
- np.array([0., 0., 0., 1., 1., 0., 0., 1., 1., 0., 0., 1., 1., 1., 0., 0.,
58
- 0.]))),
59
- (np.array([1., 2., 3., 4., 5.]),
60
- np.array([-2., -1., 0., 1., 2.]),
61
- (np.array([[0., 1., -2.], [0., 1., -1.], [0., 1., 0.], [0., 1., 1.]]),
62
- np.array([1., 2., 3., 4., 5.]),
63
- np.array([-2., -1., 0., 1., 2.]),
64
- np.array([0., 0., 0., 0., 0.]))),
65
- (np.array([-.5, -.1, 0., .2, .3]),
66
- np.array([-5., -1., .2, .5, 2.]),
67
- (np.array([[2.2727, 9.0909, -5.], [63.0303, 10.9091, -1.],
68
- [-72.7273, 17.2121, -.297], [-11.8182, 2.6667, .2],
69
- [6.0606, .303, .3485], [122.7273, 2.7273, .5]]),
70
- np.array([-.5, -.1, -.05, 0., .1, .2, .3]),
71
- np.array([-5., -1., -.297, .2, .3485, .5, 2.]),
72
- np.array([0., 0., 1., 0., 1., 0., 0.])))])
73
- def test__schmumaker_qspline(x, y, expected):
74
- [t, c, yhat, kflag] = _schumaker_qspline(x, y)
75
- np.testing.assert_allclose(c, expected[0], atol=0.0001)
76
- np.testing.assert_allclose(t, expected[1], atol=0.0001)
77
- np.testing.assert_allclose(yhat, expected[2], atol=0.0001)
78
- np.testing.assert_allclose(kflag, expected[3], atol=0.0001)
79
-
80
-
81
- @pytest.fixture
82
- def i_array():
83
- i = np.array([8.09403993, 8.09382549, 8.09361103, 8.09339656, 8.09318205,
84
- 8.09296748, 8.09275275, 8.09253771, 8.09232204, 8.09210506,
85
- 8.09188538, 8.09166014, 8.09142342, 8.09116305, 8.09085392,
86
- 8.09044425, 8.08982734, 8.08878333, 8.08685945, 8.08312463,
87
- 8.07566926, 8.06059856, 8.03005836, 7.96856869, 7.8469714,
88
- 7.61489584, 7.19789314, 6.51138396, 5.49373476, 4.13267172,
89
- 2.46021487, 0.52838624, -1.61055289])
90
- return i
91
-
92
-
93
- @pytest.fixture
94
- def v_array():
95
- v = np.array([-0.005, 0.015, 0.035, 0.055, 0.075, 0.095, 0.115, 0.135,
96
- 0.155, 0.175, 0.195, 0.215, 0.235, 0.255, 0.275, 0.295,
97
- 0.315, 0.335, 0.355, 0.375, 0.395, 0.415, 0.435, 0.455,
98
- 0.475, 0.495, 0.515, 0.535, 0.555, 0.575, 0.595, 0.615,
99
- 0.635])
100
- return v
101
-
102
-
103
- # astm_e1036 tests
104
- def test_astm_e1036(v_array, i_array):
105
- result = astm_e1036(v_array, i_array)
106
- expected = {'voc': 0.6195097477985162,
107
- 'isc': 8.093986320386227,
108
- 'vmp': 0.494283417170082,
109
- 'imp': 7.626088301548568,
110
- 'pmp': 3.7694489853302127,
111
- 'ff': 0.7517393078504361}
112
- fit = result.pop('mp_fit')
113
- expected_fit = np.array(
114
- [3.6260726, 0.49124176, -0.24644747, -0.26442383, -0.1223237])
115
- assert fit.coef == pytest.approx(expected_fit)
116
- assert result == pytest.approx(expected)
117
-
118
-
119
- def test_astm_e1036_fit_order(v_array, i_array):
120
- result = astm_e1036(v_array, i_array, mp_fit_order=3)
121
- fit = result.pop('mp_fit')
122
- expected_fit = np.array(
123
- [3.64081697, 0.49124176, -0.3720477, -0.26442383])
124
- assert fit.coef == pytest.approx(expected_fit)
125
-
126
-
127
- def test_astm_e1036_est_isc_voc(v_array, i_array):
128
- '''
129
- Test the case in which Isc and Voc estimates are
130
- valid without a linear fit
131
- '''
132
- v = v_array
133
- i = i_array
134
- v = np.append(v, [0.001, 0.6201])
135
- i = np.append(i, [8.09397560e+00, 7.10653445e-04])
136
- result = astm_e1036(v, i)
137
- expected = {'voc': 0.6201,
138
- 'isc': 8.093975598317805,
139
- 'vmp': 0.494283417170082,
140
- 'imp': 7.626088301548568,
141
- 'pmp': 3.7694489853302127,
142
- 'ff': 0.751024747526615}
143
- result.pop('mp_fit')
144
- assert result == pytest.approx(expected)
145
-
146
-
147
- def test_astm_e1036_mpfit_limits(v_array, i_array):
148
- result = astm_e1036(v_array,
149
- i_array,
150
- imax_limits=(0.85, 1.1),
151
- vmax_limits=(0.85, 1.1))
152
- expected = {'voc': 0.6195097477985162,
153
- 'isc': 8.093986320386227,
154
- 'vmp': 0.49464214190725303,
155
- 'imp': 7.620032530519718,
156
- 'pmp': 3.769189212299219,
157
- 'ff': 0.7516875014460312}
158
- result.pop('mp_fit')
159
- assert result == pytest.approx(expected)
160
-
161
-
162
- def test_astm_e1036_fit_points(v_array, i_array):
163
- i = i_array
164
- i[3] = 8.1 # ensure an interesting change happens
165
- result = astm_e1036(v_array, i, voc_points=4, isc_points=4)
166
- expected = {'voc': 0.619337073271274,
167
- 'isc': 8.093160893325297,
168
- 'vmp': 0.494283417170082,
169
- 'imp': 7.626088301548568,
170
- 'pmp': 3.7694489853302127,
171
- 'ff': 0.7520255886236707}
172
- result.pop('mp_fit')
173
- assert result == pytest.approx(expected)
File without changes
@@ -1,40 +0,0 @@
1
- import numpy as np
2
- import pytest
3
- import pandas as pd
4
-
5
- from ..conftest import DATA_DIR
6
-
7
- SPECTRL2_TEST_DATA = DATA_DIR / 'spectrl2_example_spectra.csv'
8
-
9
-
10
- @pytest.fixture
11
- def spectrl2_data():
12
- # reference spectra generated with solar_utils==0.3
13
- """
14
- expected = solar_utils.spectrl2(
15
- units=1,
16
- location=[40, -80, -5],
17
- datetime=[2020, 3, 15, 10, 45, 59],
18
- weather=[1013, 15],
19
- orientation=[0, 180],
20
- atmospheric_conditions=[1.14, 0.65, 0.344, 0.1, 1.42],
21
- albedo=[0.3, 0.7, 0.8, 1.3, 2.5, 4.0] + [0.2]*6,
22
- )
23
- """
24
- kwargs = {
25
- 'surface_tilt': 0,
26
- 'relative_airmass': 1.4899535986910446,
27
- 'apparent_zenith': 47.912086486816406,
28
- 'aoi': 47.91208648681641,
29
- 'ground_albedo': 0.2,
30
- 'surface_pressure': 101300,
31
- 'ozone': 0.344,
32
- 'precipitable_water': 1.42,
33
- 'aerosol_turbidity_500nm': 0.1,
34
- 'dayofyear': 75
35
- }
36
- df = pd.read_csv(SPECTRL2_TEST_DATA, index_col=0)
37
- # convert um to nm
38
- df['wavelength'] = np.round(df['wavelength'] * 1000, 1)
39
- df[['specdif', 'specdir', 'specetr', 'specglo']] /= 1000
40
- return kwargs, df