pvlib 0.11.0__py3-none-any.whl → 0.11.1__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 (51) hide show
  1. pvlib/atmosphere.py +157 -1
  2. pvlib/bifacial/__init__.py +4 -4
  3. pvlib/bifacial/loss_models.py +163 -0
  4. pvlib/clearsky.py +18 -29
  5. pvlib/data/pvgis_tmy_meta.json +32 -93
  6. pvlib/data/pvgis_tmy_test.dat +8761 -8761
  7. pvlib/data/tmy_45.000_8.000_2005_2020.csv +8789 -0
  8. pvlib/data/tmy_45.000_8.000_2005_2020.epw +8768 -0
  9. pvlib/data/tmy_45.000_8.000_2005_2020.json +1 -0
  10. pvlib/data/tmy_45.000_8.000_2005_2020.txt +8761 -0
  11. pvlib/data/tmy_45.000_8.000_userhorizon.json +1 -1
  12. pvlib/data/variables_style_rules.csv +2 -1
  13. pvlib/iotools/pvgis.py +39 -3
  14. pvlib/irradiance.py +141 -120
  15. pvlib/location.py +5 -5
  16. pvlib/modelchain.py +1 -1
  17. pvlib/pvsystem.py +2 -2
  18. pvlib/shading.py +8 -8
  19. pvlib/singlediode.py +1 -1
  20. pvlib/solarposition.py +55 -50
  21. pvlib/spa.py +24 -22
  22. pvlib/spectrum/__init__.py +9 -4
  23. pvlib/spectrum/irradiance.py +272 -0
  24. pvlib/spectrum/mismatch.py +118 -508
  25. pvlib/spectrum/response.py +280 -0
  26. pvlib/spectrum/spectrl2.py +16 -16
  27. pvlib/tests/bifacial/test_losses_models.py +54 -0
  28. pvlib/tests/iotools/test_pvgis.py +57 -11
  29. pvlib/tests/spectrum/__init__.py +0 -0
  30. pvlib/tests/spectrum/conftest.py +40 -0
  31. pvlib/tests/spectrum/test_irradiance.py +138 -0
  32. pvlib/tests/{test_spectrum.py → spectrum/test_mismatch.py} +32 -306
  33. pvlib/tests/spectrum/test_response.py +124 -0
  34. pvlib/tests/spectrum/test_spectrl2.py +72 -0
  35. pvlib/tests/test_atmosphere.py +71 -0
  36. pvlib/tests/test_clearsky.py +37 -25
  37. pvlib/tests/test_irradiance.py +6 -6
  38. pvlib/tests/test_solarposition.py +84 -36
  39. pvlib/tests/test_spa.py +1 -1
  40. pvlib/tools.py +26 -2
  41. pvlib/tracking.py +53 -47
  42. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/METADATA +31 -29
  43. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/RECORD +47 -38
  44. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/WHEEL +1 -1
  45. pvlib/data/tmy_45.000_8.000_2005_2016.csv +0 -8789
  46. pvlib/data/tmy_45.000_8.000_2005_2016.epw +0 -8768
  47. pvlib/data/tmy_45.000_8.000_2005_2016.json +0 -1
  48. pvlib/data/tmy_45.000_8.000_2005_2016.txt +0 -8761
  49. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/AUTHORS.md +0 -0
  50. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/LICENSE +0 -0
  51. {pvlib-0.11.0.dist-info → pvlib-0.11.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,272 @@
1
+ """
2
+ The ``irradiance`` module in the ``spectrum`` package provides functions for
3
+ calculations related to spectral irradiance data.
4
+ """
5
+
6
+ import pvlib
7
+ from pvlib._deprecation import deprecated
8
+ import numpy as np
9
+ import pandas as pd
10
+ from pathlib import Path
11
+ from functools import partial
12
+ from scipy import constants
13
+ from scipy.integrate import trapezoid
14
+
15
+
16
+ @deprecated(
17
+ since="0.11",
18
+ removal="0.12",
19
+ name="pvlib.spectrum.get_am15g",
20
+ alternative="pvlib.spectrum.get_reference_spectra",
21
+ addendum=(
22
+ "The new function reads more data. Use it with "
23
+ + "standard='ASTM G173-03' and extract the 'global' column."
24
+ ),
25
+ )
26
+ def get_am15g(wavelength=None):
27
+ r"""
28
+ Read the ASTM G173-03 AM1.5 global spectrum on a 37-degree tilted surface,
29
+ optionally interpolated to the specified wavelength(s).
30
+
31
+ Global (tilted) irradiance includes direct and diffuse irradiance from sky
32
+ and ground reflections, and is more formally called hemispherical
33
+ irradiance (on a tilted surface). In the context of photovoltaic systems
34
+ the irradiance on a flat receiver is frequently called plane-of-array (POA)
35
+ irradiance.
36
+
37
+ Parameters
38
+ ----------
39
+ wavelength: 1-D sequence of numeric, optional
40
+ Wavelengths at which the spectrum is interpolated.
41
+ By default the 2002 wavelengths of the standard are returned. [nm].
42
+
43
+ Returns
44
+ -------
45
+ am15g: pandas.Series
46
+ The AM1.5g standard spectrum indexed by ``wavelength``. [W/(m²nm)].
47
+
48
+ Notes
49
+ -----
50
+ If ``wavelength`` is specified this function uses linear interpolation.
51
+
52
+ If the values in ``wavelength`` are too widely spaced, the integral of the
53
+ spectrum may deviate from the standard value of 1000.37 W/m².
54
+
55
+ The values in the data file provided with pvlib-python are copied from an
56
+ Excel file distributed by NREL, which is found here:
57
+ https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
58
+
59
+ More information about reference spectra is found here:
60
+ https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
61
+
62
+ See Also
63
+ --------
64
+ pvlib.spectrum.get_reference_spectra : reads also the direct and
65
+ extraterrestrial components of the spectrum.
66
+
67
+ References
68
+ ----------
69
+ .. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
70
+ Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
71
+ """ # noqa: E501
72
+ # Contributed by Anton Driesse (@adriesse), PV Performance Labs. Aug. 2022
73
+ # modified by @echedey-ls, as a wrapper of spectrum.get_reference_spectra
74
+ standard = get_reference_spectra(wavelength, standard="ASTM G173-03")
75
+ return standard["global"]
76
+
77
+
78
+ def get_reference_spectra(wavelengths=None, standard="ASTM G173-03"):
79
+ r"""
80
+ Read a standard spectrum specified by ``standard``, optionally
81
+ interpolated to the specified wavelength(s).
82
+
83
+ Defaults to ``ASTM G173-03`` AM1.5 standard [1]_, which returns
84
+ ``extraterrestrial``, ``global`` and ``direct`` spectrum on a 37-degree
85
+ tilted surface, optionally interpolated to the specified wavelength(s).
86
+
87
+ Parameters
88
+ ----------
89
+ wavelengths : numeric, optional
90
+ Wavelengths at which the spectrum is interpolated. [nm].
91
+ If not provided, the original wavelengths from the specified standard
92
+ are used. Values outside that range are filled with zeros.
93
+
94
+ standard : str, default "ASTM G173-03"
95
+ The reference standard to be read. Only the reference
96
+ ``"ASTM G173-03"`` is available at the moment.
97
+
98
+ Returns
99
+ -------
100
+ standard_spectra : pandas.DataFrame
101
+ The standard spectrum by ``wavelength [nm]``. [W/(m²nm)].
102
+ Column names are ``extraterrestrial``, ``direct`` and ``global``.
103
+
104
+ Notes
105
+ -----
106
+ If ``wavelength`` is specified, linear interpolation is used.
107
+
108
+ If the values in ``wavelength`` are too widely spaced, the integral of each
109
+ spectrum may deviate from its standard value.
110
+ For global spectra, it is about 1000.37 W/m².
111
+
112
+ The values of the ASTM G173-03 provided with pvlib-python are copied from
113
+ an Excel file distributed by NREL, which is found here [2]_:
114
+ https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
115
+
116
+ Examples
117
+ --------
118
+ >>> from pvlib import spectrum
119
+ >>> am15 = spectrum.get_reference_spectra()
120
+ >>> am15_extraterrestrial, am15_global, am15_direct = \
121
+ >>> am15['extraterrestrial'], am15['global'], am15['direct']
122
+ >>> print(am15.head())
123
+ extraterrestrial global direct
124
+ wavelength
125
+ 280.0 0.082 4.730900e-23 2.536100e-26
126
+ 280.5 0.099 1.230700e-21 1.091700e-24
127
+ 281.0 0.150 5.689500e-21 6.125300e-24
128
+ 281.5 0.212 1.566200e-19 2.747900e-22
129
+ 282.0 0.267 1.194600e-18 2.834600e-21
130
+
131
+ >>> am15 = spectrum.get_reference_spectra([300, 500, 800, 1100])
132
+ >>> print(am15)
133
+ extraterrestrial global direct
134
+ wavelength
135
+ 300 0.45794 0.00102 0.000456
136
+ 500 1.91600 1.54510 1.339100
137
+ 800 1.12480 1.07250 0.988590
138
+ 1100 0.60000 0.48577 0.461130
139
+
140
+ References
141
+ ----------
142
+ .. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
143
+ Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
144
+ .. [2] “Reference Air Mass 1.5 Spectra,” www.nrel.gov.
145
+ https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
146
+ """ # Contributed by Echedey Luis, inspired by Anton Driesse (get_am15g)
147
+ SPECTRA_FILES = {
148
+ "ASTM G173-03": "ASTMG173.csv",
149
+ }
150
+ pvlib_datapath = Path(pvlib.__path__[0]) / "data"
151
+
152
+ try:
153
+ filepath = pvlib_datapath / SPECTRA_FILES[standard]
154
+ except KeyError:
155
+ raise ValueError(
156
+ f"Invalid standard identifier '{standard}'. Available "
157
+ + "identifiers are: "
158
+ + ", ".join(SPECTRA_FILES.keys())
159
+ )
160
+
161
+ standard = pd.read_csv(
162
+ filepath,
163
+ header=1, # expect first line of description, then column names
164
+ index_col=0, # first column is "wavelength"
165
+ dtype=float,
166
+ )
167
+
168
+ if wavelengths is not None:
169
+ interpolator = partial(
170
+ np.interp, xp=standard.index, left=0.0, right=0.0
171
+ )
172
+ standard = pd.DataFrame(
173
+ index=wavelengths,
174
+ data={
175
+ col: interpolator(x=wavelengths, fp=standard[col])
176
+ for col in standard.columns
177
+ },
178
+ )
179
+
180
+ return standard
181
+
182
+
183
+ def average_photon_energy(spectra):
184
+ r"""
185
+ Calculate the average photon energy of one or more spectral irradiance
186
+ distributions.
187
+
188
+ Parameters
189
+ ----------
190
+ spectra : pandas.Series or pandas.DataFrame
191
+
192
+ Spectral irradiance, must be positive. [Wm⁻²nm⁻¹]
193
+
194
+ A single spectrum must be a :py:class:`pandas.Series` with wavelength
195
+ [nm] as the index, while multiple spectra must be rows in a
196
+ :py:class:`pandas.DataFrame` with column headers as wavelength [nm].
197
+
198
+ Returns
199
+ -------
200
+ ape : numeric or pandas.Series
201
+ Average Photon Energy [eV].
202
+ Note: returns ``np.nan`` in the case of all-zero spectral irradiance
203
+ input.
204
+
205
+ Notes
206
+ -----
207
+ The average photon energy (APE) is an index used to characterise the solar
208
+ spectrum. It has been used widely in the physics literature since the
209
+ 1900s, but its application for solar spectral irradiance characterisation
210
+ in the context of PV performance modelling was proposed in 2002 [1]_. The
211
+ APE is calculated based on the principle that a photon's energy is
212
+ inversely proportional to its wavelength:
213
+
214
+ .. math::
215
+
216
+ E_\gamma = \frac{hc}{\lambda},
217
+
218
+ where :math:`E_\gamma` is the energy of a photon with wavelength
219
+ :math:`\lambda`, :math:`h` is the Planck constant, and :math:`c` is the
220
+ speed of light. Therefore, the average energy of all photons within a
221
+ single spectral irradiance distribution provides an indication of the
222
+ general shape of the spectrum. A higher average photon energy
223
+ (shorter wavelength) indicates a blue-shifted spectrum, while a lower
224
+ average photon energy (longer wavelength) would indicate a red-shifted
225
+ spectrum. This value of the average photon energy can be calculated by
226
+ dividing the total energy in the spectrum by the total number of photons
227
+ in the spectrum as follows [1]_:
228
+
229
+ .. math::
230
+
231
+ \overline{E_\gamma} = \frac{1}{q} \cdot \frac{\int G(\lambda) \,
232
+ d\lambda}
233
+ {\int \Phi(\lambda) \, d\lambda}.
234
+
235
+ :math:`\Phi(\lambda)` is the photon flux density as a function of
236
+ wavelength, :math:`G(\lambda)` is the spectral irradiance, :math:`q` is the
237
+ elementary charge used here so that the average photon energy,
238
+ :math:`\overline{E_\gamma}`, is expressed in electronvolts (eV). The
239
+ integrals are computed over the full wavelength range of the ``spectra``
240
+ parameter.
241
+
242
+ References
243
+ ----------
244
+ .. [1] Jardine, C., et al., 2002, January. Influence of spectral effects on
245
+ the performance of multijunction amorphous silicon cells. In Proc.
246
+ Photovoltaic in Europe Conference (pp. 1756-1759).
247
+ """
248
+
249
+ if not isinstance(spectra, (pd.Series, pd.DataFrame)):
250
+ raise TypeError('`spectra` must be either a'
251
+ ' pandas Series or DataFrame')
252
+
253
+ if (spectra < 0).any().any():
254
+ raise ValueError('Spectral irradiance data must be positive')
255
+
256
+ hclambda = pd.Series((constants.h*constants.c)/(spectra.T.index*1e-9))
257
+ hclambda.index = spectra.T.index
258
+ pfd = spectra.div(hclambda)
259
+
260
+ def integrate(e):
261
+ return trapezoid(e, x=e.T.index, axis=-1)
262
+
263
+ int_spectra = integrate(spectra)
264
+ int_pfd = integrate(pfd)
265
+
266
+ with np.errstate(invalid='ignore'):
267
+ ape = (1/constants.elementary_charge)*int_spectra/int_pfd
268
+
269
+ if isinstance(spectra, pd.DataFrame):
270
+ ape = pd.Series(ape, index=spectra.index)
271
+
272
+ return ape