pvlib 0.11.1__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 (149) hide show
  1. pvlib/__init__.py +1 -0
  2. pvlib/_deprecation.py +73 -0
  3. pvlib/atmosphere.py +77 -7
  4. pvlib/bifacial/infinite_sheds.py +4 -3
  5. pvlib/bifacial/utils.py +2 -1
  6. pvlib/clearsky.py +35 -22
  7. pvlib/iam.py +4 -4
  8. pvlib/iotools/midc.py +1 -1
  9. pvlib/iotools/psm3.py +1 -1
  10. pvlib/iotools/pvgis.py +10 -12
  11. pvlib/iotools/tmy.py +3 -69
  12. pvlib/irradiance.py +112 -55
  13. pvlib/ivtools/sdm.py +75 -52
  14. pvlib/location.py +73 -33
  15. pvlib/modelchain.py +18 -35
  16. pvlib/pvsystem.py +139 -94
  17. pvlib/snow.py +64 -28
  18. pvlib/solarposition.py +46 -30
  19. pvlib/spa.py +4 -2
  20. pvlib/spectrum/__init__.py +0 -1
  21. pvlib/spectrum/irradiance.py +2 -64
  22. pvlib/spectrum/mismatch.py +3 -3
  23. pvlib/spectrum/spectrl2.py +2 -1
  24. pvlib/temperature.py +49 -3
  25. pvlib/tools.py +6 -5
  26. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/METADATA +14 -11
  27. pvlib-0.12.0.dist-info/RECORD +75 -0
  28. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
  29. pvlib/data/BIRD_08_16_2012.csv +0 -8761
  30. pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
  31. pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
  32. pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
  33. pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
  34. pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
  35. pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
  36. pvlib/data/CRN_with_problems.txt +0 -3
  37. pvlib/data/ET-M772BH550GL.PAN +0 -75
  38. pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
  39. pvlib/data/PVsyst_demo.csv +0 -10757
  40. pvlib/data/PVsyst_demo_model.csv +0 -3588
  41. pvlib/data/SRML-day-EUPO1801.txt +0 -1441
  42. pvlib/data/abq19056.dat +0 -6
  43. pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
  44. pvlib/data/bishop88_numerical_precision.csv +0 -101
  45. pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
  46. pvlib/data/bsrn-pay0616.dat.gz +0 -0
  47. pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
  48. pvlib/data/cams_mcclear_monthly.csv +0 -42
  49. pvlib/data/cams_radiation_1min_verbose.csv +0 -72
  50. pvlib/data/cams_radiation_monthly.csv +0 -47
  51. pvlib/data/detect_clearsky_data.csv +0 -35
  52. pvlib/data/detect_clearsky_threshold_data.csv +0 -126
  53. pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
  54. pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
  55. pvlib/data/inverter_fit_snl_meas.csv +0 -127
  56. pvlib/data/inverter_fit_snl_sim.csv +0 -19
  57. pvlib/data/ivtools_numdiff.csv +0 -52
  58. pvlib/data/midc_20181014.txt +0 -1441
  59. pvlib/data/midc_raw_20181018.txt +0 -1441
  60. pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
  61. pvlib/data/msn19056.dat +0 -6
  62. pvlib/data/precise_iv_curves1.json +0 -10251
  63. pvlib/data/precise_iv_curves2.json +0 -10251
  64. pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
  65. pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
  66. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
  67. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
  68. pvlib/data/pvgis_tmy_meta.json +0 -32
  69. pvlib/data/pvgis_tmy_test.dat +0 -8761
  70. pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
  71. pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
  72. pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
  73. pvlib/data/spectrl2_example_spectra.csv +0 -123
  74. pvlib/data/surfrad-slv16001.dat +0 -1442
  75. pvlib/data/test_psm3_2017.csv +0 -17521
  76. pvlib/data/test_psm3_2019_5min.csv +0 -289
  77. pvlib/data/test_psm3_tmy-2017.csv +0 -8761
  78. pvlib/data/test_read_psm3.csv +0 -17523
  79. pvlib/data/test_read_pvgis_horizon.csv +0 -49
  80. pvlib/data/tmy_45.000_8.000_2005_2020.csv +0 -8789
  81. pvlib/data/tmy_45.000_8.000_2005_2020.epw +0 -8768
  82. pvlib/data/tmy_45.000_8.000_2005_2020.json +0 -1
  83. pvlib/data/tmy_45.000_8.000_2005_2020.txt +0 -8761
  84. pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
  85. pvlib/data/variables_style_rules.csv +0 -56
  86. pvlib/spa_c_files/README.md +0 -81
  87. pvlib/spa_c_files/cspa_py.pxd +0 -43
  88. pvlib/spa_c_files/spa_py.pyx +0 -30
  89. pvlib/tests/__init__.py +0 -0
  90. pvlib/tests/bifacial/__init__.py +0 -0
  91. pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
  92. pvlib/tests/bifacial/test_losses_models.py +0 -54
  93. pvlib/tests/bifacial/test_pvfactors.py +0 -82
  94. pvlib/tests/bifacial/test_utils.py +0 -192
  95. pvlib/tests/conftest.py +0 -476
  96. pvlib/tests/iotools/__init__.py +0 -0
  97. pvlib/tests/iotools/test_acis.py +0 -213
  98. pvlib/tests/iotools/test_bsrn.py +0 -131
  99. pvlib/tests/iotools/test_crn.py +0 -95
  100. pvlib/tests/iotools/test_epw.py +0 -23
  101. pvlib/tests/iotools/test_midc.py +0 -89
  102. pvlib/tests/iotools/test_panond.py +0 -32
  103. pvlib/tests/iotools/test_psm3.py +0 -198
  104. pvlib/tests/iotools/test_pvgis.py +0 -644
  105. pvlib/tests/iotools/test_sodapro.py +0 -298
  106. pvlib/tests/iotools/test_solaranywhere.py +0 -287
  107. pvlib/tests/iotools/test_solargis.py +0 -68
  108. pvlib/tests/iotools/test_solcast.py +0 -324
  109. pvlib/tests/iotools/test_solrad.py +0 -152
  110. pvlib/tests/iotools/test_srml.py +0 -124
  111. pvlib/tests/iotools/test_surfrad.py +0 -75
  112. pvlib/tests/iotools/test_tmy.py +0 -133
  113. pvlib/tests/ivtools/__init__.py +0 -0
  114. pvlib/tests/ivtools/test_sde.py +0 -230
  115. pvlib/tests/ivtools/test_sdm.py +0 -407
  116. pvlib/tests/ivtools/test_utils.py +0 -173
  117. pvlib/tests/spectrum/__init__.py +0 -0
  118. pvlib/tests/spectrum/conftest.py +0 -40
  119. pvlib/tests/spectrum/test_irradiance.py +0 -138
  120. pvlib/tests/spectrum/test_mismatch.py +0 -304
  121. pvlib/tests/spectrum/test_response.py +0 -124
  122. pvlib/tests/spectrum/test_spectrl2.py +0 -72
  123. pvlib/tests/test_albedo.py +0 -84
  124. pvlib/tests/test_atmosphere.py +0 -204
  125. pvlib/tests/test_clearsky.py +0 -878
  126. pvlib/tests/test_conftest.py +0 -81
  127. pvlib/tests/test_iam.py +0 -555
  128. pvlib/tests/test_inverter.py +0 -213
  129. pvlib/tests/test_irradiance.py +0 -1441
  130. pvlib/tests/test_location.py +0 -356
  131. pvlib/tests/test_modelchain.py +0 -2020
  132. pvlib/tests/test_numerical_precision.py +0 -124
  133. pvlib/tests/test_pvarray.py +0 -71
  134. pvlib/tests/test_pvsystem.py +0 -2495
  135. pvlib/tests/test_scaling.py +0 -207
  136. pvlib/tests/test_shading.py +0 -391
  137. pvlib/tests/test_singlediode.py +0 -608
  138. pvlib/tests/test_snow.py +0 -212
  139. pvlib/tests/test_soiling.py +0 -230
  140. pvlib/tests/test_solarposition.py +0 -933
  141. pvlib/tests/test_spa.py +0 -425
  142. pvlib/tests/test_temperature.py +0 -470
  143. pvlib/tests/test_tools.py +0 -146
  144. pvlib/tests/test_tracking.py +0 -474
  145. pvlib/tests/test_transformer.py +0 -60
  146. pvlib-0.11.1.dist-info/RECORD +0 -192
  147. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
  148. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
  149. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
@@ -1,407 +0,0 @@
1
- import numpy as np
2
- import pandas as pd
3
-
4
- import pytest
5
- from numpy.testing import assert_allclose
6
-
7
- from pvlib.ivtools import sdm
8
- from pvlib import pvsystem
9
- from pvlib._deprecation import pvlibDeprecationWarning
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_failure():
84
- with pytest.raises(RuntimeError) as exc:
85
- sdm.fit_desoto(v_mp=31.0, i_mp=8.71, v_oc=38.3, i_sc=9.43,
86
- alpha_sc=0.005658, beta_voc=-0.13788,
87
- cells_in_series=10)
88
- assert ('Parameter estimation failed') in str(exc.value)
89
-
90
-
91
- @requires_statsmodels
92
- def test_fit_desoto_sandia(cec_params_cansol_cs5p_220p):
93
- # this test computes a set of IV curves for the input fixture, fits
94
- # the De Soto model to the calculated IV curves, and compares the fitted
95
- # parameters to the starting values
96
- params = cec_params_cansol_cs5p_220p['params']
97
- params.pop('Adjust')
98
- specs = cec_params_cansol_cs5p_220p['specs']
99
- effective_irradiance = np.array([400., 500., 600., 700., 800., 900.,
100
- 1000.])
101
- temp_cell = np.array([15., 25., 35., 45.])
102
- ee = np.tile(effective_irradiance, len(temp_cell))
103
- tc = np.repeat(temp_cell, len(effective_irradiance))
104
- IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
105
- ee, tc, alpha_sc=specs['alpha_sc'], **params)
106
- ivcurve_params = dict(photocurrent=IL, saturation_current=I0,
107
- resistance_series=Rs, resistance_shunt=Rsh,
108
- nNsVth=nNsVth)
109
- sim_ivcurves = pvsystem.singlediode(**ivcurve_params).to_dict('series')
110
- v = np.linspace(0., sim_ivcurves['v_oc'], 300)
111
- i = pvsystem.i_from_v(voltage=v, **ivcurve_params)
112
- sim_ivcurves.update(v=v.T, i=i.T, ee=ee, tc=tc)
113
-
114
- result = sdm.fit_desoto_sandia(sim_ivcurves, specs)
115
- modeled = pd.Series(index=params.keys(), data=np.nan)
116
- modeled['a_ref'] = result['a_ref']
117
- modeled['I_L_ref'] = result['I_L_ref']
118
- modeled['I_o_ref'] = result['I_o_ref']
119
- modeled['R_s'] = result['R_s']
120
- modeled['R_sh_ref'] = result['R_sh_ref']
121
- expected = pd.Series(params)
122
- assert np.allclose(modeled[params.keys()].values,
123
- expected[params.keys()].values, rtol=5e-2)
124
-
125
-
126
- def _read_iv_curves_for_test(datafile, npts):
127
- """ read constants and npts IV curves from datafile """
128
- iv_specs = dict.fromkeys(['cells_in_series', 'alpha_sc', 'beta_voc',
129
- 'descr'])
130
- ivcurves = dict.fromkeys(['i_sc', 'i_mp', 'v_mp', 'v_oc', 'poa', 'tc',
131
- 'ee'])
132
-
133
- infilen = DATA_DIR / datafile
134
- with infilen.open(mode='r') as f:
135
-
136
- Ns, aIsc, bVoc, descr = f.readline().split(',')
137
-
138
- iv_specs.update(
139
- cells_in_series=int(Ns), alpha_sc=float(aIsc),
140
- beta_voc=float(bVoc), descr=descr)
141
-
142
- strN, strM = f.readline().split(',')
143
- N = int(strN)
144
- M = int(strM)
145
-
146
- isc = np.empty(N)
147
- imp = np.empty(N)
148
- vmp = np.empty(N)
149
- voc = np.empty(N)
150
- ee = np.empty(N)
151
- poa = np.empty(N)
152
- tc = np.empty(N)
153
- v = np.empty((N, M))
154
- i = np.empty((N, M))
155
- v[:] = np.nan # fill with nan
156
- i[:] = np.nan
157
-
158
- for k in range(N):
159
- tmp = (float(x) for x in f.readline().split(','))
160
- isc[k], imp[k], vmp[k], voc[k], poa[k], tc[k], ee[k] = tmp
161
- # read voltage and current
162
- tmp = [float(x) for x in f.readline().split(',')]
163
- while len(tmp) < M:
164
- tmp.append(np.nan)
165
- v[k, :] = tmp
166
- tmp = [float(x) for x in f.readline().split(',')]
167
- while len(tmp) < M:
168
- tmp.append(np.nan)
169
- i[k, :] = tmp
170
-
171
- ivcurves['i_sc'] = isc[:npts]
172
- ivcurves['i_mp'] = imp[:npts]
173
- ivcurves['v_oc'] = voc[:npts]
174
- ivcurves['v_mp'] = vmp[:npts]
175
- ivcurves['ee'] = ee[:npts]
176
- ivcurves['tc'] = tc[:npts]
177
- ivcurves['v'] = v[:npts]
178
- ivcurves['i'] = i[:npts]
179
- ivcurves['p_mp'] = ivcurves['v_mp'] * ivcurves['i_mp'] # power
180
-
181
- return iv_specs, ivcurves
182
-
183
-
184
- def _read_pvsyst_expected(datafile):
185
- """ Read Pvsyst model parameters and diode equation values for each
186
- IV curve
187
- """
188
- pvsyst_specs = dict.fromkeys(['cells_in_series', 'alpha_sc', 'beta_voc',
189
- 'descr'])
190
- # order required to match file being read
191
- paramlist = [
192
- 'I_L_ref', 'I_o_ref', 'EgRef', 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s',
193
- 'gamma_ref', 'mu_gamma']
194
- varlist = ['iph', 'io', 'rs', 'rsh', 'u']
195
- pvsyst = dict.fromkeys(paramlist + varlist)
196
-
197
- infilen = DATA_DIR / datafile
198
- with infilen.open(mode='r') as f:
199
-
200
- Ns, aIsc, bVoc, descr = f.readline().split(',')
201
-
202
- pvsyst_specs.update(
203
- cells_in_series=int(Ns), alpha_sc=float(aIsc),
204
- beta_voc=float(bVoc), descr=descr)
205
-
206
- tmp = [float(x) for x in f.readline().split(',')]
207
- # I_L_ref, I_o_ref, EgRef, R_s, R_sh_ref, R_sh_0, R_sh_exp, gamma_ref,
208
- # mu_gamma
209
- pvsyst.update(zip(paramlist, tmp))
210
-
211
- strN = f.readline()
212
- N = int(strN)
213
-
214
- Iph = np.empty(N)
215
- Io = np.empty(N)
216
- Rsh = np.empty(N)
217
- Rs = np.empty(N)
218
- u = np.empty(N)
219
-
220
- for k in range(N):
221
- tmp = [float(x) for x in f.readline().split(',')]
222
- Iph[k], Io[k], Rsh[k], Rs[k], u[k] = tmp
223
-
224
- pvsyst.update(zip(varlist, [Iph, Io, Rs, Rsh, u]))
225
-
226
- return pvsyst_specs, pvsyst
227
-
228
-
229
- @requires_statsmodels
230
- def test_fit_pvsyst_sandia(npts=3000):
231
-
232
- # get IV curve data
233
- iv_specs, ivcurves = _read_iv_curves_for_test('PVsyst_demo.csv', npts)
234
-
235
- # get known Pvsyst model parameters and five parameters from each fitted
236
- # IV curve
237
- pvsyst_specs, pvsyst = _read_pvsyst_expected('PVsyst_demo_model.csv')
238
-
239
- modeled = sdm.fit_pvsyst_sandia(ivcurves, iv_specs)
240
-
241
- # calculate IV curves using the fitted model, for comparison with input
242
- # IV curves
243
- param_res = pvsystem.calcparams_pvsyst(
244
- effective_irradiance=ivcurves['ee'], temp_cell=ivcurves['tc'],
245
- alpha_sc=iv_specs['alpha_sc'], gamma_ref=modeled['gamma_ref'],
246
- mu_gamma=modeled['mu_gamma'], I_L_ref=modeled['I_L_ref'],
247
- I_o_ref=modeled['I_o_ref'], R_sh_ref=modeled['R_sh_ref'],
248
- R_sh_0=modeled['R_sh_0'], R_s=modeled['R_s'],
249
- cells_in_series=iv_specs['cells_in_series'], EgRef=modeled['EgRef'])
250
- iv_res = pvsystem.singlediode(*param_res)
251
-
252
- # assertions
253
- assert np.allclose(
254
- ivcurves['p_mp'], iv_res['p_mp'], equal_nan=True, rtol=0.038)
255
- assert np.allclose(
256
- ivcurves['v_mp'], iv_res['v_mp'], equal_nan=True, rtol=0.029)
257
- assert np.allclose(
258
- ivcurves['i_mp'], iv_res['i_mp'], equal_nan=True, rtol=0.021)
259
- assert np.allclose(
260
- ivcurves['i_sc'], iv_res['i_sc'], equal_nan=True, rtol=0.003)
261
- assert np.allclose(
262
- ivcurves['v_oc'], iv_res['v_oc'], equal_nan=True, rtol=0.019)
263
- # cells_in_series, alpha_sc, beta_voc, descr
264
- assert all((iv_specs[k] == pvsyst_specs[k]) for k in iv_specs.keys())
265
- # I_L_ref, I_o_ref, EgRef, R_sh_ref, R_sh_0, R_sh_exp, R_s, gamma_ref,
266
- # mu_gamma
267
- assert np.isclose(modeled['I_L_ref'], pvsyst['I_L_ref'], rtol=6.5e-5)
268
- assert np.isclose(modeled['I_o_ref'], pvsyst['I_o_ref'], rtol=0.15)
269
- assert np.isclose(modeled['R_s'], pvsyst['R_s'], rtol=0.0035)
270
- assert np.isclose(modeled['R_sh_ref'], pvsyst['R_sh_ref'], rtol=0.091)
271
- assert np.isclose(modeled['R_sh_0'], pvsyst['R_sh_0'], rtol=0.013)
272
- assert np.isclose(modeled['EgRef'], pvsyst['EgRef'], rtol=0.037)
273
- assert np.isclose(modeled['gamma_ref'], pvsyst['gamma_ref'], rtol=0.0045)
274
- assert np.isclose(modeled['mu_gamma'], pvsyst['mu_gamma'], rtol=0.064)
275
-
276
- # Iph, Io, Rsh, Rs, u
277
- mask = np.ones(modeled['u'].shape, dtype=bool)
278
- # exclude one curve with different convergence
279
- umask = mask.copy()
280
- umask[2540] = False
281
- assert all(modeled['u'][umask] == pvsyst['u'][:npts][umask])
282
- assert np.allclose(
283
- modeled['iph'][modeled['u']], pvsyst['iph'][:npts][modeled['u']],
284
- equal_nan=True, rtol=0.0009)
285
- assert np.allclose(
286
- modeled['io'][modeled['u']], pvsyst['io'][:npts][modeled['u']],
287
- equal_nan=True, rtol=0.096)
288
- assert np.allclose(
289
- modeled['rs'][modeled['u']], pvsyst['rs'][:npts][modeled['u']],
290
- equal_nan=True, rtol=0.035)
291
- # exclude one curve with Rsh outside 63% tolerance
292
- rshmask = modeled['u'].copy()
293
- rshmask[2545] = False
294
- assert np.allclose(
295
- modeled['rsh'][rshmask], pvsyst['rsh'][:npts][rshmask],
296
- equal_nan=True, rtol=0.63)
297
-
298
-
299
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth, expected', [
300
- (2., 2., 2., 2., 2., 2., 2., np.nan),
301
- (2., 2., 0., 2., 2., 2., 2., np.nan),
302
- (2., 2., 2., 0., 2., 2., 2., np.nan),
303
- (2., 2., 2., 2., 0., 2., 2., np.nan),
304
- (2., 2., 2., 2., 2., 0., 2., np.nan),
305
- (2., 2., 2., 2., 2., 2., 0., np.nan)])
306
- def test__update_rsh_fixed_pt_nans(vmp, imp, iph, io, rs, rsh, nnsvth,
307
- expected):
308
- outrsh = sdm._update_rsh_fixed_pt(vmp, imp, iph, io, rs, rsh, nnsvth)
309
- assert np.all(np.isnan(outrsh))
310
-
311
-
312
- def test__update_rsh_fixed_pt_vmp0():
313
- outrsh = sdm._update_rsh_fixed_pt(vmp=0., imp=2., iph=2., io=2., rs=2.,
314
- rsh=2., nnsvth=2.)
315
- assert_allclose(outrsh, np.array([502.]), atol=.0001)
316
-
317
-
318
- def test__update_rsh_fixed_pt_vector():
319
- outrsh = sdm._update_rsh_fixed_pt(rsh=np.array([-1., 3, .5, 2.]),
320
- rs=np.array([1., -.5, 2., 2.]),
321
- io=np.array([.2, .3, -.4, 2.]),
322
- iph=np.array([-.1, 1, 3., 2.]),
323
- nnsvth=np.array([4., -.2, .1, 2.]),
324
- imp=np.array([.2, .2, -1., 2.]),
325
- vmp=np.array([0., -1, 0., 0.]))
326
- assert np.all(np.isnan(outrsh[0:3]))
327
- assert_allclose(outrsh[3], np.array([502.]), atol=.0001)
328
-
329
-
330
- @pytest.mark.parametrize('voc, iph, io, rs, rsh, nnsvth, expected', [
331
- (2., 2., 2., 2., 2., 2., 0.5911),
332
- (2., 2., 2., 0., 2., 2., 0.5911),
333
- (2., 2., 0., 2., 2., 2., 0.),
334
- (2., 0., 2., 2., 2., 2., 1.0161e-4),
335
- (0., 2., 2., 2., 2., 2., 17.9436)])
336
- def test__update_io(voc, iph, io, rs, rsh, nnsvth, expected):
337
- outio = sdm._update_io(voc, iph, io, rs, rsh, nnsvth)
338
- assert_allclose(outio, expected, atol=.0001)
339
-
340
-
341
- @pytest.mark.parametrize('voc, iph, io, rs, rsh, nnsvth', [
342
- (2., 2., 2., 2., 2., 0.),
343
- (-1., -1., -1., -1., -1., -1.)])
344
- def test__update_io_nan(voc, iph, io, rs, rsh, nnsvth):
345
- outio = sdm._update_io(voc, iph, io, rs, rsh, nnsvth)
346
- assert np.isnan(outio)
347
-
348
-
349
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth, expected', [
350
- (2., 2., 2., 2., 2., 2., 2., (1.8726, 2.)),
351
- (2., 0., 2., 2., 2., 2., 2., (1.8726, 3.4537)),
352
- (2., 2., 0., 2., 2., 2., 2., (1.2650, 0.8526)),
353
- (0., 2., 2., 2., 2., 2., 2., (1.5571, 2.))])
354
- def test__calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth, expected):
355
- theta, phi = sdm._calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth)
356
- assert_allclose(theta, expected[0], atol=.0001)
357
- assert_allclose(phi, expected[1], atol=.0001)
358
-
359
-
360
- @pytest.mark.parametrize('vmp, imp, iph, io, rs, rsh, nnsvth', [
361
- (2., 2., 2., 0., 2., 2., 2.),
362
- (2., 2., 2., 2., 2., 2., 0.),
363
- (2., 0., 2., 2., 2., 0., 2.)])
364
- def test__calc_theta_phi_exact_both_nan(vmp, imp, iph, io, rs, rsh, nnsvth):
365
- theta, phi = sdm._calc_theta_phi_exact(vmp, imp, iph, io, rs, rsh, nnsvth)
366
- assert np.isnan(theta)
367
- assert np.isnan(phi)
368
-
369
-
370
- def test__calc_theta_phi_exact_one_nan():
371
- theta, phi = sdm._calc_theta_phi_exact(imp=2., iph=2., vmp=2., io=2.,
372
- nnsvth=2., rs=0., rsh=2.)
373
- assert np.isnan(theta)
374
- assert_allclose(phi, 2., atol=.0001)
375
-
376
-
377
- def test__calc_theta_phi_exact_vector():
378
- theta, phi = sdm._calc_theta_phi_exact(imp=np.array([1., -1.]),
379
- iph=np.array([-1., 1.]),
380
- vmp=np.array([1., -1.]),
381
- io=np.array([-1., 1.]),
382
- nnsvth=np.array([1., -1.]),
383
- rs=np.array([-1., 1.]),
384
- rsh=np.array([1., -1.]))
385
- assert np.isnan(theta[0])
386
- assert np.isnan(theta[1])
387
- assert np.isnan(phi[0])
388
- assert_allclose(phi[1], 2.2079, atol=.0001)
389
-
390
-
391
- def test_pvsyst_temperature_coeff():
392
- # test for consistency with dP/dT estimated with secant rule
393
- params = {'alpha_sc': 0., 'gamma_ref': 1.1, 'mu_gamma': 0.,
394
- 'I_L_ref': 6., 'I_o_ref': 5.e-9, 'R_sh_ref': 200.,
395
- 'R_sh_0': 2000., 'R_s': 0.5, 'cells_in_series': 60}
396
- expected = -0.004886706494879083
397
- # params defines a Pvsyst model for a notional module.
398
- # expected value is created by calculating power at 1000 W/m2, and cell
399
- # temperature of 24 and 26C, using pvsystem.calcparams_pvsyst and
400
- # pvsystem.singlediode. The derivative (value for expected) is estimated
401
- # as the slope (p_mp at 26C - p_mp at 24C) / 2
402
- # using the secant rule for derivatives.
403
- gamma_pdc = sdm.pvsyst_temperature_coeff(
404
- params['alpha_sc'], params['gamma_ref'], params['mu_gamma'],
405
- params['I_L_ref'], params['I_o_ref'], params['R_sh_ref'],
406
- params['R_sh_0'], params['R_s'], params['cells_in_series'])
407
- 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