pvlib 0.11.0a1__py3-none-any.whl → 0.11.2__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.
- pvlib/_deprecation.py +73 -0
- pvlib/atmosphere.py +236 -1
- pvlib/bifacial/__init__.py +4 -4
- pvlib/bifacial/loss_models.py +163 -0
- pvlib/clearsky.py +53 -51
- pvlib/data/pvgis_tmy_meta.json +32 -93
- pvlib/data/pvgis_tmy_test.csv +8761 -0
- pvlib/data/tmy_45.000_8.000_2005_2023.csv +8789 -0
- pvlib/data/tmy_45.000_8.000_2005_2023.epw +8768 -0
- pvlib/data/tmy_45.000_8.000_2005_2023.json +1 -0
- pvlib/data/tmy_45.000_8.000_2005_2023.txt +8761 -0
- pvlib/data/tmy_45.000_8.000_userhorizon.json +1 -1
- pvlib/iam.py +4 -4
- pvlib/iotools/midc.py +1 -1
- pvlib/iotools/pvgis.py +39 -13
- pvlib/irradiance.py +237 -173
- pvlib/ivtools/sdm.py +75 -52
- pvlib/location.py +5 -5
- pvlib/modelchain.py +1 -1
- pvlib/pvsystem.py +134 -86
- pvlib/shading.py +8 -8
- pvlib/singlediode.py +1 -1
- pvlib/solarposition.py +101 -80
- pvlib/spa.py +28 -24
- pvlib/spectrum/__init__.py +9 -4
- pvlib/spectrum/irradiance.py +273 -0
- pvlib/spectrum/mismatch.py +118 -508
- pvlib/spectrum/response.py +280 -0
- pvlib/spectrum/spectrl2.py +18 -17
- pvlib/temperature.py +49 -3
- pvlib/tests/bifacial/test_losses_models.py +54 -0
- pvlib/tests/iotools/test_pvgis.py +58 -12
- pvlib/tests/ivtools/test_sdm.py +23 -1
- pvlib/tests/spectrum/__init__.py +0 -0
- pvlib/tests/spectrum/conftest.py +40 -0
- pvlib/tests/spectrum/test_irradiance.py +138 -0
- pvlib/tests/{test_spectrum.py → spectrum/test_mismatch.py} +32 -306
- pvlib/tests/spectrum/test_response.py +124 -0
- pvlib/tests/spectrum/test_spectrl2.py +72 -0
- pvlib/tests/test__deprecation.py +97 -0
- pvlib/tests/test_atmosphere.py +218 -0
- pvlib/tests/test_clearsky.py +44 -26
- pvlib/tests/test_conftest.py +0 -44
- pvlib/tests/test_irradiance.py +62 -16
- pvlib/tests/test_pvsystem.py +17 -1
- pvlib/tests/test_solarposition.py +117 -36
- pvlib/tests/test_spa.py +30 -1
- pvlib/tools.py +26 -2
- pvlib/tracking.py +53 -47
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/METADATA +34 -31
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/RECORD +55 -47
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/WHEEL +1 -1
- pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
- pvlib/data/pvgis_tmy_test.dat +0 -8761
- pvlib/data/tmy_45.000_8.000_2005_2016.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2016.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2016.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2016.txt +0 -8761
- pvlib/data/variables_style_rules.csv +0 -55
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/AUTHORS.md +0 -0
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/LICENSE +0 -0
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/top_level.txt +0 -0
pvlib/spectrum/mismatch.py
CHANGED
|
@@ -1,259 +1,15 @@
|
|
|
1
1
|
"""
|
|
2
|
-
The ``mismatch`` module provides functions for
|
|
2
|
+
The ``mismatch`` module in the ``spectrum`` package provides functions for
|
|
3
|
+
spectral mismatch calculations. Spectral mismatch models quantify the effect on
|
|
4
|
+
a device's photocurrent (or its short-circuit current) of changes in the solar
|
|
5
|
+
spectrum due to the atmosphere.
|
|
3
6
|
"""
|
|
4
|
-
|
|
5
7
|
import pvlib
|
|
6
|
-
from pvlib._deprecation import deprecated
|
|
7
|
-
from pvlib.tools import normalize_max2one
|
|
8
8
|
import numpy as np
|
|
9
9
|
import pandas as pd
|
|
10
|
-
import scipy.constants
|
|
11
10
|
from scipy.integrate import trapezoid
|
|
12
|
-
from scipy.interpolate import interp1d
|
|
13
11
|
|
|
14
|
-
from pathlib import Path
|
|
15
12
|
from warnings import warn
|
|
16
|
-
from functools import partial
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
_PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION = (
|
|
20
|
-
scipy.constants.speed_of_light
|
|
21
|
-
* scipy.constants.Planck
|
|
22
|
-
/ scipy.constants.elementary_charge
|
|
23
|
-
* 1e9
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def get_example_spectral_response(wavelength=None):
|
|
28
|
-
'''
|
|
29
|
-
Generate a generic smooth spectral response (SR) for tests and experiments.
|
|
30
|
-
|
|
31
|
-
Parameters
|
|
32
|
-
----------
|
|
33
|
-
wavelength: 1-D sequence of numeric, optional
|
|
34
|
-
Wavelengths at which spectral response values are generated.
|
|
35
|
-
By default ``wavelength`` is from 280 to 1200 in 5 nm intervals. [nm]
|
|
36
|
-
|
|
37
|
-
Returns
|
|
38
|
-
-------
|
|
39
|
-
spectral_response : pandas.Series
|
|
40
|
-
The relative spectral response indexed by ``wavelength`` in nm. [-]
|
|
41
|
-
|
|
42
|
-
Notes
|
|
43
|
-
-----
|
|
44
|
-
This spectral response is based on measurements taken on a c-Si cell.
|
|
45
|
-
A small number of points near the measured curve are used to define
|
|
46
|
-
a cubic spline having no undue oscillations, as shown in [1]_. The spline
|
|
47
|
-
can be interpolated at arbitrary wavelengths to produce a continuous,
|
|
48
|
-
smooth curve , which makes it suitable for experimenting with spectral
|
|
49
|
-
data of different resolutions.
|
|
50
|
-
|
|
51
|
-
References
|
|
52
|
-
----------
|
|
53
|
-
.. [1] Driesse, Anton, and Stein, Joshua. "Global Normal Spectral
|
|
54
|
-
Irradiance in Albuquerque: a One-Year Open Dataset for PV Research".
|
|
55
|
-
United States 2020. :doi:`10.2172/1814068`.
|
|
56
|
-
'''
|
|
57
|
-
# Contributed by Anton Driesse (@adriesse), PV Performance Labs. Aug. 2022
|
|
58
|
-
|
|
59
|
-
SR_DATA = np.array([[290, 0.00],
|
|
60
|
-
[350, 0.27],
|
|
61
|
-
[400, 0.37],
|
|
62
|
-
[500, 0.52],
|
|
63
|
-
[650, 0.71],
|
|
64
|
-
[800, 0.88],
|
|
65
|
-
[900, 0.97],
|
|
66
|
-
[950, 1.00],
|
|
67
|
-
[1000, 0.93],
|
|
68
|
-
[1050, 0.58],
|
|
69
|
-
[1100, 0.21],
|
|
70
|
-
[1150, 0.05],
|
|
71
|
-
[1190, 0.00]]).transpose()
|
|
72
|
-
|
|
73
|
-
if wavelength is None:
|
|
74
|
-
resolution = 5.0
|
|
75
|
-
wavelength = np.arange(280, 1200 + resolution, resolution)
|
|
76
|
-
|
|
77
|
-
interpolator = interp1d(SR_DATA[0], SR_DATA[1],
|
|
78
|
-
kind='cubic',
|
|
79
|
-
bounds_error=False,
|
|
80
|
-
fill_value=0.0,
|
|
81
|
-
copy=False,
|
|
82
|
-
assume_sorted=True)
|
|
83
|
-
|
|
84
|
-
sr = pd.Series(data=interpolator(wavelength), index=wavelength)
|
|
85
|
-
|
|
86
|
-
sr.index.name = 'wavelength'
|
|
87
|
-
sr.name = 'spectral_response'
|
|
88
|
-
|
|
89
|
-
return sr
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
@deprecated(
|
|
93
|
-
since="0.11",
|
|
94
|
-
removal="0.12",
|
|
95
|
-
name="pvlib.spectrum.get_am15g",
|
|
96
|
-
alternative="pvlib.spectrum.get_reference_spectra",
|
|
97
|
-
addendum=(
|
|
98
|
-
"The new function reads more data. Use it with "
|
|
99
|
-
+ "standard='ASTM G173-03' and extract the 'global' column."
|
|
100
|
-
),
|
|
101
|
-
)
|
|
102
|
-
def get_am15g(wavelength=None):
|
|
103
|
-
r"""
|
|
104
|
-
Read the ASTM G173-03 AM1.5 global spectrum on a 37-degree tilted surface,
|
|
105
|
-
optionally interpolated to the specified wavelength(s).
|
|
106
|
-
|
|
107
|
-
Global (tilted) irradiance includes direct and diffuse irradiance from sky
|
|
108
|
-
and ground reflections, and is more formally called hemispherical
|
|
109
|
-
irradiance (on a tilted surface). In the context of photovoltaic systems
|
|
110
|
-
the irradiance on a flat receiver is frequently called plane-of-array (POA)
|
|
111
|
-
irradiance.
|
|
112
|
-
|
|
113
|
-
Parameters
|
|
114
|
-
----------
|
|
115
|
-
wavelength: 1-D sequence of numeric, optional
|
|
116
|
-
Wavelengths at which the spectrum is interpolated.
|
|
117
|
-
By default the 2002 wavelengths of the standard are returned. [nm].
|
|
118
|
-
|
|
119
|
-
Returns
|
|
120
|
-
-------
|
|
121
|
-
am15g: pandas.Series
|
|
122
|
-
The AM1.5g standard spectrum indexed by ``wavelength``. [W/(m²nm)].
|
|
123
|
-
|
|
124
|
-
Notes
|
|
125
|
-
-----
|
|
126
|
-
If ``wavelength`` is specified this function uses linear interpolation.
|
|
127
|
-
|
|
128
|
-
If the values in ``wavelength`` are too widely spaced, the integral of the
|
|
129
|
-
spectrum may deviate from the standard value of 1000.37 W/m².
|
|
130
|
-
|
|
131
|
-
The values in the data file provided with pvlib-python are copied from an
|
|
132
|
-
Excel file distributed by NREL, which is found here:
|
|
133
|
-
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
|
|
134
|
-
|
|
135
|
-
More information about reference spectra is found here:
|
|
136
|
-
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
|
|
137
|
-
|
|
138
|
-
See Also
|
|
139
|
-
--------
|
|
140
|
-
pvlib.spectrum.get_reference_spectra : reads also the direct and
|
|
141
|
-
extraterrestrial components of the spectrum.
|
|
142
|
-
|
|
143
|
-
References
|
|
144
|
-
----------
|
|
145
|
-
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
|
|
146
|
-
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
|
|
147
|
-
""" # noqa: E501
|
|
148
|
-
# Contributed by Anton Driesse (@adriesse), PV Performance Labs. Aug. 2022
|
|
149
|
-
# modified by @echedey-ls, as a wrapper of spectrum.get_reference_spectra
|
|
150
|
-
standard = get_reference_spectra(wavelength, standard="ASTM G173-03")
|
|
151
|
-
return standard["global"]
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def get_reference_spectra(wavelengths=None, standard="ASTM G173-03"):
|
|
155
|
-
r"""
|
|
156
|
-
Read a standard spectrum specified by ``standard``, optionally
|
|
157
|
-
interpolated to the specified wavelength(s).
|
|
158
|
-
|
|
159
|
-
Defaults to ``ASTM G173-03`` AM1.5 standard [1]_, which returns
|
|
160
|
-
``extraterrestrial``, ``global`` and ``direct`` spectrum on a 37-degree
|
|
161
|
-
tilted surface, optionally interpolated to the specified wavelength(s).
|
|
162
|
-
|
|
163
|
-
Parameters
|
|
164
|
-
----------
|
|
165
|
-
wavelengths : numeric, optional
|
|
166
|
-
Wavelengths at which the spectrum is interpolated. [nm].
|
|
167
|
-
If not provided, the original wavelengths from the specified standard
|
|
168
|
-
are used. Values outside that range are filled with zeros.
|
|
169
|
-
|
|
170
|
-
standard : str, default "ASTM G173-03"
|
|
171
|
-
The reference standard to be read. Only the reference
|
|
172
|
-
``"ASTM G173-03"`` is available at the moment.
|
|
173
|
-
|
|
174
|
-
Returns
|
|
175
|
-
-------
|
|
176
|
-
standard_spectra : pandas.DataFrame
|
|
177
|
-
The standard spectrum by ``wavelength [nm]``. [W/(m²nm)].
|
|
178
|
-
Column names are ``extraterrestrial``, ``direct`` and ``global``.
|
|
179
|
-
|
|
180
|
-
Notes
|
|
181
|
-
-----
|
|
182
|
-
If ``wavelength`` is specified, linear interpolation is used.
|
|
183
|
-
|
|
184
|
-
If the values in ``wavelength`` are too widely spaced, the integral of each
|
|
185
|
-
spectrum may deviate from its standard value.
|
|
186
|
-
For global spectra, it is about 1000.37 W/m².
|
|
187
|
-
|
|
188
|
-
The values of the ASTM G173-03 provided with pvlib-python are copied from
|
|
189
|
-
an Excel file distributed by NREL, which is found here [2]_:
|
|
190
|
-
https://www.nrel.gov/grid/solar-resource/assets/data/astmg173.xls
|
|
191
|
-
|
|
192
|
-
Examples
|
|
193
|
-
--------
|
|
194
|
-
>>> from pvlib import spectrum
|
|
195
|
-
>>> am15 = spectrum.get_reference_spectra()
|
|
196
|
-
>>> am15_extraterrestrial, am15_global, am15_direct = \
|
|
197
|
-
>>> am15['extraterrestrial'], am15['global'], am15['direct']
|
|
198
|
-
>>> print(am15.head())
|
|
199
|
-
extraterrestrial global direct
|
|
200
|
-
wavelength
|
|
201
|
-
280.0 0.082 4.730900e-23 2.536100e-26
|
|
202
|
-
280.5 0.099 1.230700e-21 1.091700e-24
|
|
203
|
-
281.0 0.150 5.689500e-21 6.125300e-24
|
|
204
|
-
281.5 0.212 1.566200e-19 2.747900e-22
|
|
205
|
-
282.0 0.267 1.194600e-18 2.834600e-21
|
|
206
|
-
|
|
207
|
-
>>> am15 = spectrum.get_reference_spectra([300, 500, 800, 1100])
|
|
208
|
-
>>> print(am15)
|
|
209
|
-
extraterrestrial global direct
|
|
210
|
-
wavelength
|
|
211
|
-
300 0.45794 0.00102 0.000456
|
|
212
|
-
500 1.91600 1.54510 1.339100
|
|
213
|
-
800 1.12480 1.07250 0.988590
|
|
214
|
-
1100 0.60000 0.48577 0.461130
|
|
215
|
-
|
|
216
|
-
References
|
|
217
|
-
----------
|
|
218
|
-
.. [1] ASTM "G173-03 Standard Tables for Reference Solar Spectral
|
|
219
|
-
Irradiances: Direct Normal and Hemispherical on 37° Tilted Surface."
|
|
220
|
-
.. [2] “Reference Air Mass 1.5 Spectra,” www.nrel.gov.
|
|
221
|
-
https://www.nrel.gov/grid/solar-resource/spectra-am1.5.html
|
|
222
|
-
""" # Contributed by Echedey Luis, inspired by Anton Driesse (get_am15g)
|
|
223
|
-
SPECTRA_FILES = {
|
|
224
|
-
"ASTM G173-03": "ASTMG173.csv",
|
|
225
|
-
}
|
|
226
|
-
pvlib_datapath = Path(pvlib.__path__[0]) / "data"
|
|
227
|
-
|
|
228
|
-
try:
|
|
229
|
-
filepath = pvlib_datapath / SPECTRA_FILES[standard]
|
|
230
|
-
except KeyError:
|
|
231
|
-
raise ValueError(
|
|
232
|
-
f"Invalid standard identifier '{standard}'. Available "
|
|
233
|
-
+ "identifiers are: "
|
|
234
|
-
+ ", ".join(SPECTRA_FILES.keys())
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
standard = pd.read_csv(
|
|
238
|
-
filepath,
|
|
239
|
-
header=1, # expect first line of description, then column names
|
|
240
|
-
index_col=0, # first column is "wavelength"
|
|
241
|
-
dtype=float,
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
if wavelengths is not None:
|
|
245
|
-
interpolator = partial(
|
|
246
|
-
np.interp, xp=standard.index, left=0.0, right=0.0
|
|
247
|
-
)
|
|
248
|
-
standard = pd.DataFrame(
|
|
249
|
-
index=wavelengths,
|
|
250
|
-
data={
|
|
251
|
-
col: interpolator(x=wavelengths, fp=standard[col])
|
|
252
|
-
for col in standard.columns
|
|
253
|
-
},
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
return standard
|
|
257
13
|
|
|
258
14
|
|
|
259
15
|
def calc_spectral_mismatch_field(sr, e_sun, e_ref=None):
|
|
@@ -331,7 +87,8 @@ def calc_spectral_mismatch_field(sr, e_sun, e_ref=None):
|
|
|
331
87
|
|
|
332
88
|
# get the reference spectrum at wavelengths matching the measured spectra
|
|
333
89
|
if e_ref is None:
|
|
334
|
-
e_ref = get_reference_spectra(
|
|
90
|
+
e_ref = pvlib.spectrum.get_reference_spectra(
|
|
91
|
+
wavelengths=e_sun.T.index)["global"]
|
|
335
92
|
|
|
336
93
|
# interpolate the sr at the wavelengths of the spectra
|
|
337
94
|
# reference spectrum wavelengths may differ if e_ref is from caller
|
|
@@ -358,21 +115,17 @@ def calc_spectral_mismatch_field(sr, e_sun, e_ref=None):
|
|
|
358
115
|
def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
359
116
|
module_type=None, coefficients=None,
|
|
360
117
|
min_precipitable_water=0.1,
|
|
361
|
-
max_precipitable_water=8
|
|
118
|
+
max_precipitable_water=8,
|
|
119
|
+
min_airmass_absolute=0.58,
|
|
120
|
+
max_airmass_absolute=10):
|
|
362
121
|
r"""
|
|
363
122
|
Spectral mismatch modifier based on precipitable water and absolute
|
|
364
123
|
(pressure-adjusted) air mass.
|
|
365
124
|
|
|
366
|
-
Estimates
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
mass, :math:`AM_a`, and precipitable water, :math:`Pw
|
|
370
|
-
function:
|
|
371
|
-
|
|
372
|
-
.. math::
|
|
373
|
-
|
|
374
|
-
M = c_1 + c_2 AM_a + c_3 Pw + c_4 AM_a^{0.5}
|
|
375
|
-
+ c_5 Pw^{0.5} + c_6 \frac{AM_a} {Pw^{0.5}}
|
|
125
|
+
Estimates the spectral mismatch modifier, :math:`M`, representing the
|
|
126
|
+
effect of variation in the spectral irradiance on the module short circuit
|
|
127
|
+
current :math:`M` is estimated from absolute (pressure-corrected) air
|
|
128
|
+
mass, :math:`AM_a`, and precipitable water, :math:`Pw`.
|
|
376
129
|
|
|
377
130
|
Default coefficients are determined for several cell types with
|
|
378
131
|
known quantum efficiency curves, by using the Simple Model of the
|
|
@@ -383,15 +136,13 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
383
136
|
* :math:`0.5 \textrm{cm} <= Pw <= 5 \textrm{cm}`
|
|
384
137
|
* :math:`1.0 <= AM_a <= 5.0`
|
|
385
138
|
* Spectral range is limited to that of CMP11 (280 nm to 2800 nm)
|
|
386
|
-
*
|
|
139
|
+
* Spectrum simulated on an equatorial facing surface with 37° tilt
|
|
387
140
|
* All other parameters fixed at G173 standard
|
|
388
141
|
|
|
389
|
-
From these simulated spectra, M is calculated using the known
|
|
142
|
+
From these simulated spectra, :math:`M` is calculated using the known
|
|
390
143
|
quantum efficiency curves. Multiple linear regression is then
|
|
391
|
-
applied to fit Eq. 1 to determine the coefficients for each module.
|
|
392
|
-
|
|
393
|
-
Based on the PVLIB Matlab function ``pvl_FSspeccorr`` by Mitchell
|
|
394
|
-
Lee and Alex Panchula of First Solar, 2016 [2]_.
|
|
144
|
+
applied to fit Eq. 1 to determine the coefficients for each module. More
|
|
145
|
+
details on the model can be found in [2]_.
|
|
395
146
|
|
|
396
147
|
Parameters
|
|
397
148
|
----------
|
|
@@ -406,11 +157,12 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
406
157
|
'multisi', and 'polysi' (can be lower or upper case). If provided,
|
|
407
158
|
module_type selects default coefficients for the following modules:
|
|
408
159
|
|
|
409
|
-
* 'cdte' - First Solar Series 4-2 CdTe module.
|
|
410
|
-
* 'monosi'
|
|
411
|
-
* 'multisi'
|
|
412
|
-
|
|
413
|
-
* '
|
|
160
|
+
* ``'cdte'`` - First Solar Series 4-2 CdTe module.
|
|
161
|
+
* ``'monosi'``, ``'xsi'`` - First Solar TetraSun module.
|
|
162
|
+
* ``'multisi'``, ``'polysi'`` - anonymous multi-crystalline silicon
|
|
163
|
+
module.
|
|
164
|
+
* ``'cigs'`` - anonymous copper indium gallium selenide module.
|
|
165
|
+
* ``'asi'`` - anonymous amorphous silicon module.
|
|
414
166
|
|
|
415
167
|
The module used to calculate the spectral correction
|
|
416
168
|
coefficients corresponds to the Multi-crystalline silicon
|
|
@@ -430,12 +182,20 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
430
182
|
min_precipitable_water : float, default 0.1
|
|
431
183
|
minimum atmospheric precipitable water. Any ``precipitable_water``
|
|
432
184
|
value lower than ``min_precipitable_water``
|
|
433
|
-
is set to ``min_precipitable_water
|
|
185
|
+
is set to ``min_precipitable_water``. [cm]
|
|
434
186
|
|
|
435
187
|
max_precipitable_water : float, default 8
|
|
436
188
|
maximum atmospheric precipitable water. Any ``precipitable_water``
|
|
437
189
|
value greater than ``max_precipitable_water``
|
|
438
|
-
is set to ``np.nan
|
|
190
|
+
is set to ``np.nan``. [cm]
|
|
191
|
+
|
|
192
|
+
min_airmass_absolute : float, default 0.58
|
|
193
|
+
minimum absolute airmass. Any ``airmass_absolute`` value lower than
|
|
194
|
+
``min_airmass_absolute`` is set to ``min_airmass_absolute``. [unitless]
|
|
195
|
+
|
|
196
|
+
max_airmass_absolute : float, default 10
|
|
197
|
+
minimum absolute airmass. Any ``airmass_absolute`` value greater than
|
|
198
|
+
``max_airmass_absolute`` is set to ``max_airmass_absolute``. [unitless]
|
|
439
199
|
|
|
440
200
|
Returns
|
|
441
201
|
-------
|
|
@@ -445,6 +205,22 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
445
205
|
effective irradiance, i.e., the irradiance that is converted to
|
|
446
206
|
electrical current.
|
|
447
207
|
|
|
208
|
+
Notes
|
|
209
|
+
----
|
|
210
|
+
The ``spectral_factor_firstsolar`` model takes the following form:
|
|
211
|
+
|
|
212
|
+
.. math::
|
|
213
|
+
|
|
214
|
+
M = c_1 + c_2 AM_a + c_3 Pw + c_4 AM_a^{0.5}
|
|
215
|
+
+ c_5 Pw^{0.5} + c_6 \frac{AM_a} {Pw^{0.5}}.
|
|
216
|
+
|
|
217
|
+
The default values for the limits applied to :math:`AM_a` and :math:`Pw`
|
|
218
|
+
via the ``min_precipitable_water``, ``max_precipitable_water``,
|
|
219
|
+
``min_airmass_absolute``, and ``max_airmass_absolute`` are set to prevent
|
|
220
|
+
divergence of the model presented above. These default values were
|
|
221
|
+
determined by the publication authors in the original pvlib-python
|
|
222
|
+
implementation (:pull:`208`).
|
|
223
|
+
|
|
448
224
|
References
|
|
449
225
|
----------
|
|
450
226
|
.. [1] Gueymard, Christian. SMARTS2: a simple model of the atmospheric
|
|
@@ -461,36 +237,27 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
461
237
|
MMF Approach, TUV Rheinland Energy GmbH report 21237296.003,
|
|
462
238
|
January 2017
|
|
463
239
|
"""
|
|
464
|
-
|
|
465
|
-
# --- Screen Input Data ---
|
|
466
|
-
|
|
467
|
-
# *** Pw ***
|
|
468
|
-
# Replace Pw Values below 0.1 cm with 0.1 cm to prevent model from
|
|
469
|
-
# diverging"
|
|
470
240
|
pw = np.atleast_1d(precipitable_water)
|
|
471
241
|
pw = pw.astype('float64')
|
|
472
242
|
if np.min(pw) < min_precipitable_water:
|
|
473
243
|
pw = np.maximum(pw, min_precipitable_water)
|
|
474
|
-
warn('
|
|
475
|
-
f'{min_precipitable_water} cm
|
|
244
|
+
warn('Low precipitable water values replaced with '
|
|
245
|
+
f'{min_precipitable_water} cm in the calculation of spectral '
|
|
246
|
+
'mismatch.')
|
|
476
247
|
|
|
477
|
-
# Warn user about Pw data that is exceptionally high
|
|
478
248
|
if np.max(pw) > max_precipitable_water:
|
|
479
249
|
pw[pw > max_precipitable_water] = np.nan
|
|
480
|
-
warn('
|
|
481
|
-
'
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
warn('Exceptionally low air mass: ' +
|
|
492
|
-
'model not intended for extra-terrestrial use')
|
|
493
|
-
# pvl_absoluteairmass(1,pvl_alt2pres(4340)) = 0.58 Elevation of
|
|
250
|
+
warn('High precipitable water values replaced with np.nan in '
|
|
251
|
+
'the calculation of spectral mismatch.')
|
|
252
|
+
|
|
253
|
+
airmass_absolute = np.minimum(airmass_absolute, max_airmass_absolute)
|
|
254
|
+
|
|
255
|
+
if np.min(airmass_absolute) < min_airmass_absolute:
|
|
256
|
+
airmass_absolute = np.maximum(airmass_absolute, min_airmass_absolute)
|
|
257
|
+
warn('Low airmass values replaced with 'f'{min_airmass_absolute} in '
|
|
258
|
+
'the calculation of spectral mismatch.')
|
|
259
|
+
# pvlib.atmosphere.get_absolute_airmass(1,
|
|
260
|
+
# pvlib.atmosphere.alt2pres(4340)) = 0.58 Elevation of
|
|
494
261
|
# Mina Pirquita, Argentian = 4340 m. Highest elevation city with
|
|
495
262
|
# population over 50,000.
|
|
496
263
|
|
|
@@ -519,7 +286,6 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
519
286
|
raise TypeError('Cannot resolve input, must supply only one of ' +
|
|
520
287
|
'module_type and coefficients')
|
|
521
288
|
|
|
522
|
-
# Evaluate Spectral Shift
|
|
523
289
|
coeff = coefficients
|
|
524
290
|
ama = airmass_absolute
|
|
525
291
|
modifier = (
|
|
@@ -531,26 +297,68 @@ def spectral_factor_firstsolar(precipitable_water, airmass_absolute,
|
|
|
531
297
|
|
|
532
298
|
def spectral_factor_sapm(airmass_absolute, module):
|
|
533
299
|
"""
|
|
534
|
-
Calculates the
|
|
300
|
+
Calculates the spectral mismatch factor, :math:`f_1`,
|
|
301
|
+
using the Sandia Array Performance Model approach.
|
|
302
|
+
|
|
303
|
+
The SAPM spectral factor function is part of the broader Sandia Array
|
|
304
|
+
Performance Model, which defines five points on an IV curve using empirical
|
|
305
|
+
module-specific coefficients. Module coefficients for the SAPM are
|
|
306
|
+
available in the SAPM database and can be retrieved for use in the
|
|
307
|
+
``module`` parameter through
|
|
308
|
+
:py:func:`pvlib.pvsystem.retrieve_sam()`. More details on the
|
|
309
|
+
SAPM can be found in [1]_, while a full description of the procedure to
|
|
310
|
+
determine the empirical model coefficients, including those for the SAPM
|
|
311
|
+
spectral correction, can be found in [2]_.
|
|
535
312
|
|
|
536
313
|
Parameters
|
|
537
314
|
----------
|
|
538
315
|
airmass_absolute : numeric
|
|
539
|
-
Absolute airmass
|
|
316
|
+
Absolute airmass [unitless]
|
|
317
|
+
|
|
318
|
+
Note: ``np.nan`` airmass values will result in 0 output.
|
|
540
319
|
|
|
541
320
|
module : dict-like
|
|
542
|
-
A dict, Series, or DataFrame defining the SAPM
|
|
543
|
-
|
|
544
|
-
details.
|
|
321
|
+
A dict, Series, or DataFrame defining the SAPM parameters.
|
|
322
|
+
Must contain keys `'A0'` through `'A4'`.
|
|
323
|
+
See the :py:func:`pvlib.pvsystem.sapm` notes section for more details.
|
|
545
324
|
|
|
546
325
|
Returns
|
|
547
326
|
-------
|
|
548
|
-
|
|
549
|
-
The
|
|
327
|
+
f1 : numeric
|
|
328
|
+
The spectral mismatch factor. [unitless]
|
|
550
329
|
|
|
551
330
|
Notes
|
|
552
331
|
-----
|
|
553
|
-
|
|
332
|
+
The SAPM spectral correction functions parameterises :math:`f_1` as a
|
|
333
|
+
fourth order polynomial function of absolute air mass:
|
|
334
|
+
|
|
335
|
+
.. math::
|
|
336
|
+
|
|
337
|
+
f_1 = a_0 + a_1 AM_a + a_2 AM_a^2 + a_3 AM_a^3 + a_4 AM_a^4,
|
|
338
|
+
|
|
339
|
+
where :math:`f_1` is the spectral mismatch factor, :math:`a_{0-4}` are
|
|
340
|
+
the module-specific coefficients, and :math:`AM_a` is the absolute airmass,
|
|
341
|
+
which is calculated by applying a pressure correction to the relative
|
|
342
|
+
airmass. More detail on how this spectral correction function was developed
|
|
343
|
+
can be found in [3]_.
|
|
344
|
+
|
|
345
|
+
References
|
|
346
|
+
----------
|
|
347
|
+
.. [1] King, D., Kratochvil, J., and Boyson W. (2004), "Sandia
|
|
348
|
+
Photovoltaic Array Performance Model", (No. SAND2004-3535), Sandia
|
|
349
|
+
National Laboratories, Albuquerque, NM (United States).
|
|
350
|
+
:doi:`10.2172/919131`
|
|
351
|
+
.. [2] King, B., Hansen, C., Riley, D., Robinson, C., and Pratt, L.
|
|
352
|
+
(2016). Procedure to determine coefficients for the Sandia Array
|
|
353
|
+
Performance Model (SAPM) (No. SAND2016-5284). Sandia National
|
|
354
|
+
Laboratories, Albuquerque, NM (United States).
|
|
355
|
+
:doi:`10.2172/1256510`
|
|
356
|
+
.. [3] King, D., Kratochvil, J., and Boyson, W. "Measuring solar spectral
|
|
357
|
+
and angle-of-incidence effects on photovoltaic modules and solar
|
|
358
|
+
irradiance sensors." Conference Record of the 26th IEEE Potovoltaic
|
|
359
|
+
Specialists Conference (PVSC). IEEE, 1997.
|
|
360
|
+
:doi:`10.1109/PVSC.1997.654283`
|
|
361
|
+
|
|
554
362
|
"""
|
|
555
363
|
|
|
556
364
|
am_coeff = [module['A4'], module['A3'], module['A2'], module['A1'],
|
|
@@ -581,7 +389,7 @@ def spectral_factor_caballero(precipitable_water, airmass_absolute, aod500,
|
|
|
581
389
|
available here via the ``module_type`` parameter were determined
|
|
582
390
|
by fitting the model equations to spectral factors calculated from
|
|
583
391
|
global tilted spectral irradiance measurements taken in the city of
|
|
584
|
-
Jaén, Spain.
|
|
392
|
+
Jaén, Spain. See [1]_ for details.
|
|
585
393
|
|
|
586
394
|
Parameters
|
|
587
395
|
----------
|
|
@@ -598,8 +406,8 @@ def spectral_factor_caballero(precipitable_water, airmass_absolute, aod500,
|
|
|
598
406
|
One of the following PV technology strings from [1]_:
|
|
599
407
|
|
|
600
408
|
* ``'cdte'`` - anonymous CdTe module.
|
|
601
|
-
* ``'monosi'
|
|
602
|
-
* ``'multisi'
|
|
409
|
+
* ``'monosi'`` - anonymous sc-si module.
|
|
410
|
+
* ``'multisi'`` - anonymous mc-si- module.
|
|
603
411
|
* ``'cigs'`` - anonymous copper indium gallium selenide module.
|
|
604
412
|
* ``'asi'`` - anonymous amorphous silicon module.
|
|
605
413
|
* ``'perovskite'`` - anonymous pervoskite module.
|
|
@@ -713,8 +521,8 @@ def spectral_factor_pvspec(airmass_absolute, clearsky_index,
|
|
|
713
521
|
|
|
714
522
|
* ``'fs4-1'`` - First Solar series 4-1 and earlier CdTe module.
|
|
715
523
|
* ``'fs4-2'`` - First Solar 4-2 and later CdTe module.
|
|
716
|
-
* ``'monosi'
|
|
717
|
-
* ``'multisi'
|
|
524
|
+
* ``'monosi'`` - anonymous monocrystalline Si module.
|
|
525
|
+
* ``'multisi'`` - anonymous multicrystalline Si module.
|
|
718
526
|
* ``'cigs'`` - anonymous copper indium gallium selenide module.
|
|
719
527
|
* ``'asi'`` - anonymous amorphous silicon module.
|
|
720
528
|
|
|
@@ -902,201 +710,3 @@ def spectral_factor_jrc(airmass, clearsky_index, module_type=None,
|
|
|
902
710
|
+ coeff[2] * (airmass - 1.5)
|
|
903
711
|
)
|
|
904
712
|
return mismatch
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
def sr_to_qe(sr, wavelength=None, normalize=False):
|
|
908
|
-
"""
|
|
909
|
-
Convert spectral responsivities to quantum efficiencies.
|
|
910
|
-
If ``wavelength`` is not provided, the spectral responsivity ``sr`` must be
|
|
911
|
-
a :py:class:`pandas.Series` or :py:class:`pandas.DataFrame`, with the
|
|
912
|
-
wavelengths in the index.
|
|
913
|
-
|
|
914
|
-
Provide wavelengths in nanometers, [nm].
|
|
915
|
-
|
|
916
|
-
Conversion is described in [1]_.
|
|
917
|
-
|
|
918
|
-
.. versionadded:: 0.11.0
|
|
919
|
-
|
|
920
|
-
Parameters
|
|
921
|
-
----------
|
|
922
|
-
sr : numeric, pandas.Series or pandas.DataFrame
|
|
923
|
-
Spectral response, [A/W].
|
|
924
|
-
Index must be the wavelength in nanometers, [nm].
|
|
925
|
-
|
|
926
|
-
wavelength : numeric, optional
|
|
927
|
-
Points where spectral response is measured, in nanometers, [nm].
|
|
928
|
-
|
|
929
|
-
normalize : bool, default False
|
|
930
|
-
If True, the quantum efficiency is normalized so that the maximum value
|
|
931
|
-
is 1.
|
|
932
|
-
For ``pandas.DataFrame``, normalization is done for each column.
|
|
933
|
-
For 2D arrays, normalization is done for each sub-array.
|
|
934
|
-
|
|
935
|
-
Returns
|
|
936
|
-
-------
|
|
937
|
-
quantum_efficiency : numeric, same type as ``sr``
|
|
938
|
-
Quantum efficiency, in the interval [0, 1].
|
|
939
|
-
|
|
940
|
-
Notes
|
|
941
|
-
-----
|
|
942
|
-
- If ``sr`` is of type ``pandas.Series`` or ``pandas.DataFrame``,
|
|
943
|
-
column names will remain unchanged in the returned object.
|
|
944
|
-
- If ``wavelength`` is provided it will be used independently of the
|
|
945
|
-
datatype of ``sr``.
|
|
946
|
-
|
|
947
|
-
Examples
|
|
948
|
-
--------
|
|
949
|
-
>>> import numpy as np
|
|
950
|
-
>>> import pandas as pd
|
|
951
|
-
>>> from pvlib import spectrum
|
|
952
|
-
>>> wavelengths = np.array([350, 550, 750])
|
|
953
|
-
>>> spectral_response = np.array([0.25, 0.40, 0.57])
|
|
954
|
-
>>> quantum_efficiency = spectrum.sr_to_qe(spectral_response, wavelengths)
|
|
955
|
-
>>> print(quantum_efficiency)
|
|
956
|
-
array([0.88560142, 0.90170326, 0.94227991])
|
|
957
|
-
|
|
958
|
-
>>> spectral_response_series = pd.Series(spectral_response, index=wavelengths, name="dataset")
|
|
959
|
-
>>> qe = spectrum.sr_to_qe(spectral_response_series)
|
|
960
|
-
>>> print(qe)
|
|
961
|
-
350 0.885601
|
|
962
|
-
550 0.901703
|
|
963
|
-
750 0.942280
|
|
964
|
-
Name: dataset, dtype: float64
|
|
965
|
-
|
|
966
|
-
>>> qe = spectrum.sr_to_qe(spectral_response_series, normalize=True)
|
|
967
|
-
>>> print(qe)
|
|
968
|
-
350 0.939850
|
|
969
|
-
550 0.956938
|
|
970
|
-
750 1.000000
|
|
971
|
-
Name: dataset, dtype: float64
|
|
972
|
-
|
|
973
|
-
References
|
|
974
|
-
----------
|
|
975
|
-
.. [1] “Spectral Response,” PV Performance Modeling Collaborative (PVPMC).
|
|
976
|
-
https://pvpmc.sandia.gov/modeling-guide/2-dc-module-iv/effective-irradiance/spectral-response/
|
|
977
|
-
.. [2] “Spectral Response | PVEducation,” www.pveducation.org.
|
|
978
|
-
https://www.pveducation.org/pvcdrom/solar-cell-operation/spectral-response
|
|
979
|
-
|
|
980
|
-
See Also
|
|
981
|
-
--------
|
|
982
|
-
pvlib.spectrum.qe_to_sr
|
|
983
|
-
""" # noqa: E501
|
|
984
|
-
if wavelength is None:
|
|
985
|
-
if hasattr(sr, "index"): # true for pandas objects
|
|
986
|
-
# use reference to index values instead of index alone so
|
|
987
|
-
# sr / wavelength returns a series with the same name
|
|
988
|
-
wavelength = sr.index.array
|
|
989
|
-
else:
|
|
990
|
-
raise TypeError(
|
|
991
|
-
"'sr' must have an '.index' attribute"
|
|
992
|
-
+ " or 'wavelength' must be provided"
|
|
993
|
-
)
|
|
994
|
-
quantum_efficiency = (
|
|
995
|
-
sr
|
|
996
|
-
/ wavelength
|
|
997
|
-
* _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION
|
|
998
|
-
)
|
|
999
|
-
|
|
1000
|
-
if normalize:
|
|
1001
|
-
quantum_efficiency = normalize_max2one(quantum_efficiency)
|
|
1002
|
-
|
|
1003
|
-
return quantum_efficiency
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
def qe_to_sr(qe, wavelength=None, normalize=False):
|
|
1007
|
-
"""
|
|
1008
|
-
Convert quantum efficiencies to spectral responsivities.
|
|
1009
|
-
If ``wavelength`` is not provided, the quantum efficiency ``qe`` must be
|
|
1010
|
-
a :py:class:`pandas.Series` or :py:class:`pandas.DataFrame`, with the
|
|
1011
|
-
wavelengths in the index.
|
|
1012
|
-
|
|
1013
|
-
Provide wavelengths in nanometers, [nm].
|
|
1014
|
-
|
|
1015
|
-
Conversion is described in [1]_.
|
|
1016
|
-
|
|
1017
|
-
.. versionadded:: 0.11.0
|
|
1018
|
-
|
|
1019
|
-
Parameters
|
|
1020
|
-
----------
|
|
1021
|
-
qe : numeric, pandas.Series or pandas.DataFrame
|
|
1022
|
-
Quantum efficiency.
|
|
1023
|
-
If pandas subtype, index must be the wavelength in nanometers, [nm].
|
|
1024
|
-
|
|
1025
|
-
wavelength : numeric, optional
|
|
1026
|
-
Points where quantum efficiency is measured, in nanometers, [nm].
|
|
1027
|
-
|
|
1028
|
-
normalize : bool, default False
|
|
1029
|
-
If True, the spectral response is normalized so that the maximum value
|
|
1030
|
-
is 1.
|
|
1031
|
-
For ``pandas.DataFrame``, normalization is done for each column.
|
|
1032
|
-
For 2D arrays, normalization is done for each sub-array.
|
|
1033
|
-
|
|
1034
|
-
Returns
|
|
1035
|
-
-------
|
|
1036
|
-
spectral_response : numeric, same type as ``qe``
|
|
1037
|
-
Spectral response, [A/W].
|
|
1038
|
-
|
|
1039
|
-
Notes
|
|
1040
|
-
-----
|
|
1041
|
-
- If ``qe`` is of type ``pandas.Series`` or ``pandas.DataFrame``,
|
|
1042
|
-
column names will remain unchanged in the returned object.
|
|
1043
|
-
- If ``wavelength`` is provided it will be used independently of the
|
|
1044
|
-
datatype of ``qe``.
|
|
1045
|
-
|
|
1046
|
-
Examples
|
|
1047
|
-
--------
|
|
1048
|
-
>>> import numpy as np
|
|
1049
|
-
>>> import pandas as pd
|
|
1050
|
-
>>> from pvlib import spectrum
|
|
1051
|
-
>>> wavelengths = np.array([350, 550, 750])
|
|
1052
|
-
>>> quantum_efficiency = np.array([0.86, 0.90, 0.94])
|
|
1053
|
-
>>> spectral_response = spectrum.qe_to_sr(quantum_efficiency, wavelengths)
|
|
1054
|
-
>>> print(spectral_response)
|
|
1055
|
-
array([0.24277287, 0.39924442, 0.56862085])
|
|
1056
|
-
|
|
1057
|
-
>>> quantum_efficiency_series = pd.Series(quantum_efficiency, index=wavelengths, name="dataset")
|
|
1058
|
-
>>> sr = spectrum.qe_to_sr(quantum_efficiency_series)
|
|
1059
|
-
>>> print(sr)
|
|
1060
|
-
350 0.242773
|
|
1061
|
-
550 0.399244
|
|
1062
|
-
750 0.568621
|
|
1063
|
-
Name: dataset, dtype: float64
|
|
1064
|
-
|
|
1065
|
-
>>> sr = spectrum.qe_to_sr(quantum_efficiency_series, normalize=True)
|
|
1066
|
-
>>> print(sr)
|
|
1067
|
-
350 0.426950
|
|
1068
|
-
550 0.702128
|
|
1069
|
-
750 1.000000
|
|
1070
|
-
Name: dataset, dtype: float64
|
|
1071
|
-
|
|
1072
|
-
References
|
|
1073
|
-
----------
|
|
1074
|
-
.. [1] “Spectral Response,” PV Performance Modeling Collaborative (PVPMC).
|
|
1075
|
-
https://pvpmc.sandia.gov/modeling-guide/2-dc-module-iv/effective-irradiance/spectral-response/
|
|
1076
|
-
.. [2] “Spectral Response | PVEducation,” www.pveducation.org.
|
|
1077
|
-
https://www.pveducation.org/pvcdrom/solar-cell-operation/spectral-response
|
|
1078
|
-
|
|
1079
|
-
See Also
|
|
1080
|
-
--------
|
|
1081
|
-
pvlib.spectrum.sr_to_qe
|
|
1082
|
-
""" # noqa: E501
|
|
1083
|
-
if wavelength is None:
|
|
1084
|
-
if hasattr(qe, "index"): # true for pandas objects
|
|
1085
|
-
# use reference to index values instead of index alone so
|
|
1086
|
-
# sr / wavelength returns a series with the same name
|
|
1087
|
-
wavelength = qe.index.array
|
|
1088
|
-
else:
|
|
1089
|
-
raise TypeError(
|
|
1090
|
-
"'qe' must have an '.index' attribute"
|
|
1091
|
-
+ " or 'wavelength' must be provided"
|
|
1092
|
-
)
|
|
1093
|
-
spectral_responsivity = (
|
|
1094
|
-
qe
|
|
1095
|
-
* wavelength
|
|
1096
|
-
/ _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION
|
|
1097
|
-
)
|
|
1098
|
-
|
|
1099
|
-
if normalize:
|
|
1100
|
-
spectral_responsivity = normalize_max2one(spectral_responsivity)
|
|
1101
|
-
|
|
1102
|
-
return spectral_responsivity
|