pvlib 0.9.4a1__py3-none-any.whl → 0.10.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.
- pvlib/__init__.py +3 -2
- pvlib/atmosphere.py +23 -173
- pvlib/bifacial/infinite_sheds.py +88 -277
- pvlib/bifacial/utils.py +270 -28
- pvlib/data/adr-library-cec-inverters-2019-03-05.csv +5009 -0
- pvlib/data/precise_iv_curves1.json +10251 -0
- pvlib/data/precise_iv_curves2.json +10251 -0
- pvlib/data/precise_iv_curves_parameter_sets1.csv +33 -0
- pvlib/data/precise_iv_curves_parameter_sets2.csv +33 -0
- pvlib/data/test_psm3_2017.csv +17521 -17521
- pvlib/data/test_psm3_2019_5min.csv +288 -288
- pvlib/data/test_read_psm3.csv +17522 -17522
- pvlib/data/test_read_pvgis_horizon.csv +49 -0
- pvlib/data/variables_style_rules.csv +3 -0
- pvlib/iam.py +207 -51
- pvlib/inverter.py +6 -1
- pvlib/iotools/__init__.py +7 -2
- pvlib/iotools/acis.py +516 -0
- pvlib/iotools/midc.py +4 -4
- pvlib/iotools/psm3.py +59 -42
- pvlib/iotools/pvgis.py +84 -28
- pvlib/iotools/sodapro.py +8 -6
- pvlib/iotools/srml.py +121 -18
- pvlib/iotools/surfrad.py +2 -2
- pvlib/iotools/tmy.py +146 -102
- pvlib/irradiance.py +270 -15
- pvlib/ivtools/sde.py +14 -20
- pvlib/ivtools/sdm.py +31 -20
- pvlib/ivtools/utils.py +127 -6
- pvlib/location.py +3 -2
- pvlib/modelchain.py +67 -70
- pvlib/pvarray.py +225 -0
- pvlib/pvsystem.py +169 -539
- pvlib/shading.py +43 -2
- pvlib/singlediode.py +216 -66
- pvlib/snow.py +36 -15
- pvlib/soiling.py +3 -3
- pvlib/spa.py +327 -368
- pvlib/spectrum/__init__.py +8 -2
- pvlib/spectrum/mismatch.py +335 -0
- pvlib/temperature.py +124 -13
- pvlib/tests/bifacial/test_infinite_sheds.py +44 -106
- pvlib/tests/bifacial/test_utils.py +102 -5
- pvlib/tests/conftest.py +0 -31
- pvlib/tests/iotools/test_acis.py +213 -0
- pvlib/tests/iotools/test_midc.py +6 -6
- pvlib/tests/iotools/test_psm3.py +7 -5
- pvlib/tests/iotools/test_pvgis.py +21 -14
- pvlib/tests/iotools/test_sodapro.py +1 -1
- pvlib/tests/iotools/test_srml.py +71 -6
- pvlib/tests/iotools/test_tmy.py +43 -8
- pvlib/tests/ivtools/test_sde.py +19 -17
- pvlib/tests/ivtools/test_sdm.py +9 -4
- pvlib/tests/ivtools/test_utils.py +96 -1
- pvlib/tests/test_atmosphere.py +8 -64
- pvlib/tests/test_clearsky.py +0 -1
- pvlib/tests/test_iam.py +74 -1
- pvlib/tests/test_irradiance.py +56 -2
- pvlib/tests/test_location.py +1 -1
- pvlib/tests/test_modelchain.py +33 -76
- pvlib/tests/test_pvarray.py +46 -0
- pvlib/tests/test_pvsystem.py +366 -201
- pvlib/tests/test_shading.py +35 -0
- pvlib/tests/test_singlediode.py +306 -29
- pvlib/tests/test_snow.py +84 -1
- pvlib/tests/test_soiling.py +8 -7
- pvlib/tests/test_solarposition.py +7 -7
- pvlib/tests/test_spa.py +6 -7
- pvlib/tests/test_spectrum.py +145 -1
- pvlib/tests/test_temperature.py +29 -11
- pvlib/tests/test_tools.py +41 -0
- pvlib/tests/test_tracking.py +0 -149
- pvlib/tools.py +49 -25
- pvlib/tracking.py +1 -269
- pvlib-0.10.0.dist-info/AUTHORS.md +35 -0
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/LICENSE +5 -2
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/METADATA +3 -13
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/RECORD +80 -75
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/WHEEL +1 -1
- pvlib/data/adr-library-2013-10-01.csv +0 -1762
- pvlib/forecast.py +0 -1211
- pvlib/iotools/ecmwf_macc.py +0 -312
- pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
- pvlib/tests/test_forecast.py +0 -228
- pvlib-0.9.4a1.dist-info/AUTHORS.md +0 -32
- {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
pvlib/iotools/tmy.py
CHANGED
|
@@ -3,9 +3,29 @@
|
|
|
3
3
|
import datetime
|
|
4
4
|
import re
|
|
5
5
|
import pandas as pd
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import warnings
|
|
7
|
+
from pvlib._deprecation import pvlibDeprecationWarning
|
|
8
|
+
|
|
9
|
+
# Dictionary mapping TMY3 names to pvlib names
|
|
10
|
+
VARIABLE_MAP = {
|
|
11
|
+
'GHI (W/m^2)': 'ghi',
|
|
12
|
+
'ETR (W/m^2)': 'ghi_extra',
|
|
13
|
+
'DNI (W/m^2)': 'dni',
|
|
14
|
+
'ETRN (W/m^2)': 'dni_extra',
|
|
15
|
+
'DHI (W/m^2)': 'dhi',
|
|
16
|
+
'Pressure (mbar)': 'pressure',
|
|
17
|
+
'Wdir (degrees)': 'wind_direction',
|
|
18
|
+
'Wspd (m/s)': 'wind_speed',
|
|
19
|
+
'Dry-bulb (C)': 'temp_air',
|
|
20
|
+
'Dew-point (C)': 'temp_dew',
|
|
21
|
+
'RHum (%)': 'relative_humidity',
|
|
22
|
+
'Alb (unitless)': 'albedo',
|
|
23
|
+
'Pwat (cm)': 'precipitable_water'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def read_tmy3(filename, coerce_year=None, map_variables=None, recolumn=None,
|
|
28
|
+
encoding=None):
|
|
9
29
|
"""Read a TMY3 file into a pandas dataframe.
|
|
10
30
|
|
|
11
31
|
Note that values contained in the metadata dictionary are unchanged
|
|
@@ -24,9 +44,18 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
24
44
|
If supplied, the year of the index will be set to `coerce_year`, except
|
|
25
45
|
for the last index value which will be set to the *next* year so that
|
|
26
46
|
the index increases monotonically.
|
|
27
|
-
|
|
47
|
+
map_variables : bool, default None
|
|
48
|
+
When True, renames columns of the DataFrame to pvlib variable names
|
|
49
|
+
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
50
|
+
recolumn : bool (deprecated, use map_variables instead)
|
|
28
51
|
If ``True``, apply standard names to TMY3 columns. Typically this
|
|
29
52
|
results in stripping the units from the column name.
|
|
53
|
+
Cannot be used in combination with ``map_variables``.
|
|
54
|
+
encoding : str, optional
|
|
55
|
+
Encoding of the file. For files that contain non-UTF8 characters it may
|
|
56
|
+
be necessary to specify an alternative encoding, e.g., for
|
|
57
|
+
SolarAnywhere TMY3 files the encoding should be 'iso-8859-1'. Users
|
|
58
|
+
may also consider using the 'utf-8-sig' encoding.
|
|
30
59
|
|
|
31
60
|
Returns
|
|
32
61
|
-------
|
|
@@ -35,7 +64,7 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
35
64
|
data : DataFrame
|
|
36
65
|
A pandas dataframe with the columns described in the table
|
|
37
66
|
below. For more detailed descriptions of each component, please
|
|
38
|
-
consult the TMY3 User's Manual
|
|
67
|
+
consult the TMY3 User's Manual [1]_, especially tables 1-1
|
|
39
68
|
through 1-6.
|
|
40
69
|
|
|
41
70
|
metadata : dict
|
|
@@ -57,80 +86,83 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
57
86
|
USAF Int USAF identifier
|
|
58
87
|
=============== ====== ===================
|
|
59
88
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
89
|
+
|
|
90
|
+
======================== ======================================================================================================================================================
|
|
91
|
+
field description
|
|
92
|
+
======================== ======================================================================================================================================================
|
|
93
|
+
**† denotes variables that are mapped when `map_variables` is True**
|
|
94
|
+
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
95
|
+
Index A pandas datetime index. NOTE, the index is timezone aware, and times are set to local standard time (daylight savings is not included)
|
|
96
|
+
ghi_extra† Extraterrestrial horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
|
|
97
|
+
dni_extra† Extraterrestrial normal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
|
|
98
|
+
ghi† Direct and diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
|
|
99
|
+
GHI source See [1]_, Table 1-4
|
|
100
|
+
GHI uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
101
|
+
dni† Amount of direct normal radiation (modeled) recv'd during 60 mintues prior to timestamp, Wh/m^2
|
|
102
|
+
DNI source See [1]_, Table 1-4
|
|
103
|
+
DNI uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
104
|
+
dhi† Amount of diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
|
|
105
|
+
DHI source See [1]_, Table 1-4
|
|
106
|
+
DHI uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
107
|
+
GH illum (lx) Avg. total horizontal illuminance recv'd during the 60 minutes prior to timestamp, lx
|
|
108
|
+
GH illum source See [1]_, Table 1-4
|
|
109
|
+
GH illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
110
|
+
DN illum (lx) Avg. direct normal illuminance recv'd during the 60 minutes prior to timestamp, lx
|
|
111
|
+
DN illum source See [1]_, Table 1-4
|
|
112
|
+
DN illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
113
|
+
DH illum (lx) Avg. horizontal diffuse illuminance recv'd during the 60 minutes prior to timestamp, lx
|
|
114
|
+
DH illum source See [1]_, Table 1-4
|
|
115
|
+
DH illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
|
|
116
|
+
Zenith lum (cd/m^2) Avg. luminance at the sky's zenith during the 60 minutes prior to timestamp, cd/m^2
|
|
117
|
+
Zenith lum source See [1]_, Table 1-4
|
|
118
|
+
Zenith lum uncert (%) Uncertainty based on random and bias error estimates see [1]_ section 2.10
|
|
119
|
+
TotCld (tenths) Amount of sky dome covered by clouds or obscuring phenonema at time stamp, tenths of sky
|
|
120
|
+
TotCld source See [1]_, Table 1-5
|
|
121
|
+
TotCld uncert (code) See [1]_, Table 1-6
|
|
122
|
+
OpqCld (tenths) Amount of sky dome covered by clouds or obscuring phenonema that prevent observing the sky at time stamp, tenths of sky
|
|
123
|
+
OpqCld source See [1]_, Table 1-5
|
|
124
|
+
OpqCld uncert (code) See [1]_, Table 1-6
|
|
125
|
+
temp_air† Dry bulb temperature at the time indicated, deg C
|
|
126
|
+
Dry-bulb source See [1]_, Table 1-5
|
|
127
|
+
Dry-bulb uncert (code) See [1]_, Table 1-6
|
|
128
|
+
temp_dew† Dew-point temperature at the time indicated, deg C
|
|
129
|
+
Dew-point source See [1]_, Table 1-5
|
|
130
|
+
Dew-point uncert (code) See [1]_, Table 1-6
|
|
131
|
+
relative_humidity† Relatitudeive humidity at the time indicated, percent
|
|
132
|
+
RHum source See [1]_, Table 1-5
|
|
133
|
+
RHum uncert (code) See [1]_, Table 1-6
|
|
134
|
+
pressure† Station pressure at the time indicated, 1 mbar
|
|
135
|
+
Pressure source See [1]_, Table 1-5
|
|
136
|
+
Pressure uncert (code) See [1]_, Table 1-6
|
|
137
|
+
wind_direction† Wind direction at time indicated, degrees from north (360 = north; 0 = undefined,calm)
|
|
138
|
+
Wdir source See [1]_, Table 1-5
|
|
139
|
+
Wdir uncert (code) See [1]_, Table 1-6
|
|
140
|
+
wind_speed† Wind speed at the time indicated, meter/second
|
|
141
|
+
Wspd source See [1]_, Table 1-5
|
|
142
|
+
Wspd uncert (code) See [1]_, Table 1-6
|
|
143
|
+
Hvis (m) Distance to discernable remote objects at time indicated (7777=unlimited), meter
|
|
144
|
+
Hvis source See [1]_, Table 1-5
|
|
145
|
+
Hvis uncert (coe) See [1]_, Table 1-6
|
|
146
|
+
CeilHgt (m) Height of cloud base above local terrain (7777=unlimited), meter
|
|
147
|
+
CeilHgt source See [1]_, Table 1-5
|
|
148
|
+
CeilHgt uncert (code) See [1]_, Table 1-6
|
|
149
|
+
precipitable_water† Total precipitable water contained in a column of unit cross section from earth to top of atmosphere, cm
|
|
150
|
+
Pwat source See [1]_, Table 1-5
|
|
151
|
+
Pwat uncert (code) See [1]_, Table 1-6
|
|
152
|
+
AOD The broadband aerosol optical depth per unit of air mass due to extinction by aerosol component of atmosphere, unitless
|
|
153
|
+
AOD source See [1]_, Table 1-5
|
|
154
|
+
AOD uncert (code) See [1]_, Table 1-6
|
|
155
|
+
albedo† The ratio of reflected solar irradiance to global horizontal irradiance, unitless
|
|
156
|
+
Alb source See [1]_, Table 1-5
|
|
157
|
+
Alb uncert (code) See [1]_, Table 1-6
|
|
158
|
+
Lprecip depth (mm) The amount of liquid precipitation observed at indicated time for the period indicated in the liquid precipitation quantity field, millimeter
|
|
159
|
+
Lprecip quantity (hr) The period of accumulatitudeion for the liquid precipitation depth field, hour
|
|
160
|
+
Lprecip source See [1]_, Table 1-5
|
|
161
|
+
Lprecip uncert (code) See [1]_, Table 1-6
|
|
162
|
+
PresWth (METAR code) Present weather code, see [2]_.
|
|
163
|
+
PresWth source Present weather code source, see [2]_.
|
|
164
|
+
PresWth uncert (code) Present weather code uncertainty, see [2]_.
|
|
165
|
+
======================== ======================================================================================================================================================
|
|
134
166
|
|
|
135
167
|
.. admonition:: Midnight representation
|
|
136
168
|
|
|
@@ -152,21 +184,21 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
152
184
|
----------
|
|
153
185
|
.. [1] Wilcox, S and Marion, W. "Users Manual for TMY3 Data Sets".
|
|
154
186
|
NREL/TP-581-43156, Revised May 2008.
|
|
187
|
+
:doi:`10.2172/928611`
|
|
155
188
|
.. [2] Wilcox, S. (2007). National Solar Radiation Database 1991 2005
|
|
156
189
|
Update: Users Manual. 472 pp.; NREL Report No. TP-581-41364.
|
|
190
|
+
:doi:`10.2172/901864`
|
|
157
191
|
.. [3] `SolarAnywhere file formats
|
|
158
192
|
<https://www.solaranywhere.com/support/historical-data/file-formats/>`_
|
|
159
193
|
""" # noqa: E501
|
|
160
194
|
head = ['USAF', 'Name', 'State', 'TZ', 'latitude', 'longitude', 'altitude']
|
|
161
195
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
with open(str(filename), 'r', encoding='iso-8859-1') as fbuf:
|
|
169
|
-
firstline, data = _parse_tmy3(fbuf)
|
|
196
|
+
with open(str(filename), 'r', encoding=encoding) as fbuf:
|
|
197
|
+
# header information on the 1st line (0 indexing)
|
|
198
|
+
firstline = fbuf.readline()
|
|
199
|
+
# use pandas to read the csv file buffer
|
|
200
|
+
# header is actually the second line, but tell pandas to look for
|
|
201
|
+
data = pd.read_csv(fbuf, header=0)
|
|
170
202
|
|
|
171
203
|
meta = dict(zip(head, firstline.rstrip('\n').split(",")))
|
|
172
204
|
# convert metadata strings to numeric types
|
|
@@ -178,8 +210,10 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
178
210
|
|
|
179
211
|
# get the date column as a pd.Series of numpy datetime64
|
|
180
212
|
data_ymd = pd.to_datetime(data['Date (MM/DD/YYYY)'], format='%m/%d/%Y')
|
|
213
|
+
# extract minutes
|
|
214
|
+
minutes = data['Time (HH:MM)'].str.split(':').str[1].astype(int)
|
|
181
215
|
# shift the time column so that midnite is 00:00 instead of 24:00
|
|
182
|
-
shifted_hour = data['Time (HH:MM)'].str[
|
|
216
|
+
shifted_hour = data['Time (HH:MM)'].str.split(':').str[0].astype(int) % 24
|
|
183
217
|
# shift the dates at midnight (24:00) so they correspond to the next day.
|
|
184
218
|
# If midnight is specified as 00:00 do not shift date.
|
|
185
219
|
data_ymd[data['Time (HH:MM)'].str[:2] == '24'] += datetime.timedelta(days=1) # noqa: E501
|
|
@@ -197,25 +231,34 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
|
|
|
197
231
|
data_ymd.iloc[-1] = data_ymd.iloc[-1].replace(year=coerce_year+1)
|
|
198
232
|
# NOTE: as of pvlib-0.6.3, min req is pandas-0.18.1, so pd.to_timedelta
|
|
199
233
|
# unit must be in (D,h,m,s,ms,us,ns), but pandas>=0.24 allows unit='hour'
|
|
200
|
-
data.index = data_ymd + pd.to_timedelta(shifted_hour, unit='h')
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
234
|
+
data.index = data_ymd + pd.to_timedelta(shifted_hour, unit='h') \
|
|
235
|
+
+ pd.to_timedelta(minutes, unit='min')
|
|
236
|
+
# shouldnt' specify both recolumn and map_variables
|
|
237
|
+
if recolumn is not None and map_variables is not None:
|
|
238
|
+
msg = "`map_variables` and `recolumn` cannot both be specified"
|
|
239
|
+
raise ValueError(msg)
|
|
240
|
+
elif map_variables is None and recolumn is not None:
|
|
241
|
+
warnings.warn(
|
|
242
|
+
'The recolumn parameter is deprecated and will be removed in '
|
|
243
|
+
'pvlib 0.11.0. Use `map_variables` instead, although note that '
|
|
244
|
+
'its behavior is different from `recolumn`.',
|
|
245
|
+
pvlibDeprecationWarning)
|
|
246
|
+
elif map_variables is None and recolumn is None:
|
|
247
|
+
warnings.warn(
|
|
248
|
+
'TMY3 variable names will be renamed to pvlib conventions by '
|
|
249
|
+
'default starting in pvlib 0.11.0. Specify map_variables=True '
|
|
250
|
+
'to enable that behavior now, or specify map_variables=False '
|
|
251
|
+
'to hide this warning.', pvlibDeprecationWarning)
|
|
252
|
+
if map_variables:
|
|
253
|
+
data = data.rename(columns=VARIABLE_MAP)
|
|
254
|
+
elif recolumn or (recolumn is None and map_variables is None):
|
|
255
|
+
data = _recolumn(data)
|
|
204
256
|
|
|
205
257
|
data = data.tz_localize(int(meta['TZ'] * 3600))
|
|
206
258
|
|
|
207
259
|
return data, meta
|
|
208
260
|
|
|
209
261
|
|
|
210
|
-
def _parse_tmy3(fbuf):
|
|
211
|
-
# header information on the 1st line (0 indexing)
|
|
212
|
-
firstline = fbuf.readline()
|
|
213
|
-
# use pandas to read the csv file buffer
|
|
214
|
-
# header is actually the second line, but tell pandas to look for
|
|
215
|
-
data = pd.read_csv(fbuf, header=0)
|
|
216
|
-
return firstline, data
|
|
217
|
-
|
|
218
|
-
|
|
219
262
|
def _recolumn(tmy3_dataframe):
|
|
220
263
|
"""
|
|
221
264
|
Rename the columns of the TMY3 DataFrame.
|
|
@@ -283,7 +326,7 @@ def read_tmy2(filename):
|
|
|
283
326
|
data : DataFrame
|
|
284
327
|
A dataframe with the columns described in the table below. For a
|
|
285
328
|
more detailed descriptions of each component, please consult the
|
|
286
|
-
TMY2 User's Manual
|
|
329
|
+
TMY2 User's Manual [1]_, especially tables 3-1 through 3-6, and
|
|
287
330
|
Appendix B.
|
|
288
331
|
|
|
289
332
|
metadata : dict
|
|
@@ -385,6 +428,7 @@ def read_tmy2(filename):
|
|
|
385
428
|
----------
|
|
386
429
|
.. [1] Marion, W and Urban, K. "Wilcox, S and Marion, W. "User's Manual
|
|
387
430
|
for TMY2s". NREL 1995.
|
|
431
|
+
:doi:`10.2172/87130`
|
|
388
432
|
""" # noqa: E501
|
|
389
433
|
# paste in the column info as one long line
|
|
390
434
|
string = '%2d%2d%2d%2d%4d%4d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%2d%1s%1d%2d%1s%1d%4d%1s%1d%4d%1s%1d%3d%1s%1d%4d%1s%1d%3d%1s%1d%3d%1s%1d%4d%1s%1d%5d%1s%1d%10d%3d%1s%1d%3d%1s%1d%3d%1s%1d%2d%1s%1d' # noqa: E501
|
pvlib/irradiance.py
CHANGED
|
@@ -1481,24 +1481,24 @@ def _disc_kn(clearness_index, airmass, max_airmass=12):
|
|
|
1481
1481
|
|
|
1482
1482
|
am = np.minimum(am, max_airmass) # GH 450
|
|
1483
1483
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1484
|
+
is_cloudy = (kt <= 0.6)
|
|
1485
|
+
# Use Horner's method to compute polynomials efficiently
|
|
1486
|
+
a = np.where(
|
|
1487
|
+
is_cloudy,
|
|
1488
|
+
0.512 + kt*(-1.56 + kt*(2.286 - 2.222*kt)),
|
|
1489
|
+
-5.743 + kt*(21.77 + kt*(-27.49 + 11.56*kt)))
|
|
1490
|
+
b = np.where(
|
|
1491
|
+
is_cloudy,
|
|
1492
|
+
0.37 + 0.962*kt,
|
|
1493
|
+
41.4 + kt*(-118.5 + kt*(66.05 + 31.9*kt)))
|
|
1494
|
+
c = np.where(
|
|
1495
|
+
is_cloudy,
|
|
1496
|
+
-0.28 + kt*(0.932 - 2.048*kt),
|
|
1497
|
+
-47.01 + kt*(184.2 + kt*(-222.0 + 73.81*kt)))
|
|
1498
1498
|
|
|
1499
1499
|
delta_kn = a + b * np.exp(c*am)
|
|
1500
1500
|
|
|
1501
|
-
Knc = 0.866 -
|
|
1501
|
+
Knc = 0.866 + am*(-0.122 + am*(0.0121 + am*(-0.000653 + 1.4e-05*am)))
|
|
1502
1502
|
Kn = Knc - delta_kn
|
|
1503
1503
|
return Kn, am
|
|
1504
1504
|
|
|
@@ -2227,6 +2227,8 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
|
|
|
2227
2227
|
--------
|
|
2228
2228
|
dirint
|
|
2229
2229
|
disc
|
|
2230
|
+
orgill_hollands
|
|
2231
|
+
boland
|
|
2230
2232
|
"""
|
|
2231
2233
|
|
|
2232
2234
|
dni_extra = get_extra_radiation(datetime_or_doy)
|
|
@@ -2265,6 +2267,198 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
|
|
|
2265
2267
|
return data
|
|
2266
2268
|
|
|
2267
2269
|
|
|
2270
|
+
def orgill_hollands(ghi, zenith, datetime_or_doy, dni_extra=None,
|
|
2271
|
+
min_cos_zenith=0.065, max_zenith=87):
|
|
2272
|
+
"""Estimate DNI and DHI from GHI using the Orgill and Hollands model.
|
|
2273
|
+
|
|
2274
|
+
The Orgill and Hollands model [1]_ estimates the diffuse fraction DF from
|
|
2275
|
+
global horizontal irradiance through an empirical relationship between
|
|
2276
|
+
hourly DF observations (in Toronto, Canada) and the ratio of GHI to
|
|
2277
|
+
extraterrestrial irradiance, Kt.
|
|
2278
|
+
|
|
2279
|
+
Parameters
|
|
2280
|
+
----------
|
|
2281
|
+
ghi: numeric
|
|
2282
|
+
Global horizontal irradiance in W/m^2.
|
|
2283
|
+
zenith: numeric
|
|
2284
|
+
True (not refraction-corrected) zenith angles in decimal degrees.
|
|
2285
|
+
datetime_or_doy : int, float, array, pd.DatetimeIndex
|
|
2286
|
+
Day of year or array of days of year e.g.
|
|
2287
|
+
pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
|
|
2288
|
+
dni_extra : None or numeric, default None
|
|
2289
|
+
Extraterrestrial direct normal irradiance. [W/m2]
|
|
2290
|
+
min_cos_zenith : numeric, default 0.065
|
|
2291
|
+
Minimum value of cos(zenith) to allow when calculating global
|
|
2292
|
+
clearness index `kt`. Equivalent to zenith = 86.273 degrees.
|
|
2293
|
+
max_zenith : numeric, default 87
|
|
2294
|
+
Maximum value of zenith to allow in DNI calculation. DNI will be
|
|
2295
|
+
set to 0 for times with zenith values greater than `max_zenith`.
|
|
2296
|
+
|
|
2297
|
+
Returns
|
|
2298
|
+
-------
|
|
2299
|
+
data : OrderedDict or DataFrame
|
|
2300
|
+
Contains the following keys/columns:
|
|
2301
|
+
|
|
2302
|
+
* ``dni``: the modeled direct normal irradiance in W/m^2.
|
|
2303
|
+
* ``dhi``: the modeled diffuse horizontal irradiance in
|
|
2304
|
+
W/m^2.
|
|
2305
|
+
* ``kt``: Ratio of global to extraterrestrial irradiance
|
|
2306
|
+
on a horizontal plane.
|
|
2307
|
+
|
|
2308
|
+
References
|
|
2309
|
+
----------
|
|
2310
|
+
.. [1] Orgill, J.F., Hollands, K.G.T., Correlation equation for hourly
|
|
2311
|
+
diffuse radiation on a horizontal surface, Solar Energy 19(4), pp 357–359,
|
|
2312
|
+
1977. Eqs. 3(a), 3(b) and 3(c)
|
|
2313
|
+
:doi:`10.1016/0038-092X(77)90006-8`
|
|
2314
|
+
|
|
2315
|
+
See Also
|
|
2316
|
+
--------
|
|
2317
|
+
dirint
|
|
2318
|
+
disc
|
|
2319
|
+
erbs
|
|
2320
|
+
boland
|
|
2321
|
+
"""
|
|
2322
|
+
if dni_extra is None:
|
|
2323
|
+
dni_extra = get_extra_radiation(datetime_or_doy)
|
|
2324
|
+
|
|
2325
|
+
kt = clearness_index(ghi, zenith, dni_extra, min_cos_zenith=min_cos_zenith,
|
|
2326
|
+
max_clearness_index=1)
|
|
2327
|
+
|
|
2328
|
+
# For Kt < 0.35, set the diffuse fraction
|
|
2329
|
+
df = 1 - 0.249*kt
|
|
2330
|
+
|
|
2331
|
+
# For Kt >= 0.35 and Kt <= 0.75, set the diffuse fraction
|
|
2332
|
+
df = np.where((kt >= 0.35) & (kt <= 0.75),
|
|
2333
|
+
1.557 - 1.84*kt, df)
|
|
2334
|
+
|
|
2335
|
+
# For Kt > 0.75, set the diffuse fraction
|
|
2336
|
+
df = np.where(kt > 0.75, 0.177, df)
|
|
2337
|
+
|
|
2338
|
+
dhi = df * ghi
|
|
2339
|
+
|
|
2340
|
+
dni = (ghi - dhi) / tools.cosd(zenith)
|
|
2341
|
+
bad_values = (zenith > max_zenith) | (ghi < 0) | (dni < 0)
|
|
2342
|
+
dni = np.where(bad_values, 0, dni)
|
|
2343
|
+
# ensure that closure relationship remains valid
|
|
2344
|
+
dhi = np.where(bad_values, ghi, dhi)
|
|
2345
|
+
|
|
2346
|
+
data = OrderedDict()
|
|
2347
|
+
data['dni'] = dni
|
|
2348
|
+
data['dhi'] = dhi
|
|
2349
|
+
data['kt'] = kt
|
|
2350
|
+
|
|
2351
|
+
if isinstance(datetime_or_doy, pd.DatetimeIndex):
|
|
2352
|
+
data = pd.DataFrame(data, index=datetime_or_doy)
|
|
2353
|
+
|
|
2354
|
+
return data
|
|
2355
|
+
|
|
2356
|
+
|
|
2357
|
+
def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
|
|
2358
|
+
min_cos_zenith=0.065, max_zenith=87):
|
|
2359
|
+
r"""
|
|
2360
|
+
Estimate DNI and DHI from GHI using the Boland clearness index model.
|
|
2361
|
+
|
|
2362
|
+
The Boland model [1]_, [2]_ estimates the diffuse fraction, DF, from global
|
|
2363
|
+
horizontal irradiance, GHI, through an empirical relationship between DF
|
|
2364
|
+
and the clearness index, :math:`k_t`, the ratio of GHI to horizontal
|
|
2365
|
+
extraterrestrial irradiance.
|
|
2366
|
+
|
|
2367
|
+
.. math::
|
|
2368
|
+
|
|
2369
|
+
\mathit{DF} = \frac{1}{1 + \exp\left(a \left(k_t - b\right)\right)}
|
|
2370
|
+
|
|
2371
|
+
|
|
2372
|
+
Parameters
|
|
2373
|
+
----------
|
|
2374
|
+
ghi: numeric
|
|
2375
|
+
Global horizontal irradiance. [W/m^2]
|
|
2376
|
+
solar_zenith: numeric
|
|
2377
|
+
True (not refraction-corrected) zenith angles in decimal degrees.
|
|
2378
|
+
datetime_or_doy : numeric, pandas.DatetimeIndex
|
|
2379
|
+
Day of year or array of days of year e.g.
|
|
2380
|
+
pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
|
|
2381
|
+
a_coeff : float, default 8.645
|
|
2382
|
+
Logistic curve fit coefficient.
|
|
2383
|
+
b_coeff : float, default 0.613
|
|
2384
|
+
Logistic curve fit coefficient.
|
|
2385
|
+
min_cos_zenith : numeric, default 0.065
|
|
2386
|
+
Minimum value of cos(zenith) to allow when calculating global
|
|
2387
|
+
clearness index :math:`k_t`. Equivalent to zenith = 86.273 degrees.
|
|
2388
|
+
max_zenith : numeric, default 87
|
|
2389
|
+
Maximum value of zenith to allow in DNI calculation. DNI will be
|
|
2390
|
+
set to 0 for times with zenith values greater than `max_zenith`.
|
|
2391
|
+
|
|
2392
|
+
Returns
|
|
2393
|
+
-------
|
|
2394
|
+
data : OrderedDict or DataFrame
|
|
2395
|
+
Contains the following keys/columns:
|
|
2396
|
+
|
|
2397
|
+
* ``dni``: the modeled direct normal irradiance in W/m^2.
|
|
2398
|
+
* ``dhi``: the modeled diffuse horizontal irradiance in
|
|
2399
|
+
W/m^2.
|
|
2400
|
+
* ``kt``: Ratio of global to extraterrestrial irradiance
|
|
2401
|
+
on a horizontal plane.
|
|
2402
|
+
|
|
2403
|
+
References
|
|
2404
|
+
----------
|
|
2405
|
+
.. [1] J. Boland, B. Ridley (2008) Models of Diffuse Solar Fraction. In:
|
|
2406
|
+
Badescu V. (eds) Modeling Solar Radiation at the Earth’s Surface.
|
|
2407
|
+
Springer, Berlin, Heidelberg. :doi:`10.1007/978-3-540-77455-6_8`
|
|
2408
|
+
.. [2] John Boland, Lynne Scott, and Mark Luther, Modelling the diffuse
|
|
2409
|
+
fraction of global solar radiation on a horizontal surface,
|
|
2410
|
+
Environmetrics 12(2), pp 103-116, 2001,
|
|
2411
|
+
:doi:`10.1002/1099-095X(200103)12:2%3C103::AID-ENV447%3E3.0.CO;2-2`
|
|
2412
|
+
|
|
2413
|
+
See also
|
|
2414
|
+
--------
|
|
2415
|
+
dirint
|
|
2416
|
+
disc
|
|
2417
|
+
erbs
|
|
2418
|
+
orgill_hollands
|
|
2419
|
+
|
|
2420
|
+
Notes
|
|
2421
|
+
-----
|
|
2422
|
+
Boland diffuse fraction differs from other decomposition algorithms by use
|
|
2423
|
+
of a logistic function to fit the entire range of clearness index,
|
|
2424
|
+
:math:`k_t`. Parameters ``a_coeff`` and ``b_coeff`` are reported in [2]_
|
|
2425
|
+
for different time intervals:
|
|
2426
|
+
|
|
2427
|
+
* 15-minute: ``a = 8.645`` and ``b = 0.613``
|
|
2428
|
+
* 1-hour: ``a = 7.997`` and ``b = 0.586``
|
|
2429
|
+
"""
|
|
2430
|
+
|
|
2431
|
+
dni_extra = get_extra_radiation(datetime_or_doy)
|
|
2432
|
+
|
|
2433
|
+
kt = clearness_index(
|
|
2434
|
+
ghi, solar_zenith, dni_extra, min_cos_zenith=min_cos_zenith,
|
|
2435
|
+
max_clearness_index=1)
|
|
2436
|
+
|
|
2437
|
+
# Boland equation
|
|
2438
|
+
df = 1.0 / (1.0 + np.exp(a_coeff * (kt - b_coeff)))
|
|
2439
|
+
# NOTE: [2] has different coefficients, for different time intervals
|
|
2440
|
+
# 15-min: df = 1 / (1 + exp(8.645 * (kt - 0.613)))
|
|
2441
|
+
# 1-hour: df = 1 / (1 + exp(7.997 * (kt - 0.586)))
|
|
2442
|
+
|
|
2443
|
+
dhi = df * ghi
|
|
2444
|
+
|
|
2445
|
+
dni = (ghi - dhi) / tools.cosd(solar_zenith)
|
|
2446
|
+
bad_values = (solar_zenith > max_zenith) | (ghi < 0) | (dni < 0)
|
|
2447
|
+
dni = np.where(bad_values, 0, dni)
|
|
2448
|
+
# ensure that closure relationship remains valid
|
|
2449
|
+
dhi = np.where(bad_values, ghi, dhi)
|
|
2450
|
+
|
|
2451
|
+
data = OrderedDict()
|
|
2452
|
+
data['dni'] = dni
|
|
2453
|
+
data['dhi'] = dhi
|
|
2454
|
+
data['kt'] = kt
|
|
2455
|
+
|
|
2456
|
+
if isinstance(datetime_or_doy, pd.DatetimeIndex):
|
|
2457
|
+
data = pd.DataFrame(data, index=datetime_or_doy)
|
|
2458
|
+
|
|
2459
|
+
return data
|
|
2460
|
+
|
|
2461
|
+
|
|
2268
2462
|
def campbell_norman(zenith, transmittance, pressure=101325.0,
|
|
2269
2463
|
dni_extra=1367.0):
|
|
2270
2464
|
'''
|
|
@@ -3013,3 +3207,64 @@ def complete_irradiance(solar_zenith,
|
|
|
3013
3207
|
'dhi': dhi,
|
|
3014
3208
|
'dni': dni})
|
|
3015
3209
|
return component_sum_df
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
def louche(ghi, solar_zenith, datetime_or_doy, max_zenith=90):
|
|
3213
|
+
"""
|
|
3214
|
+
Determine DNI and DHI from GHI using the Louche model.
|
|
3215
|
+
|
|
3216
|
+
Parameters
|
|
3217
|
+
----------
|
|
3218
|
+
ghi : numeric
|
|
3219
|
+
Global horizontal irradiance. [W/m^2]
|
|
3220
|
+
|
|
3221
|
+
solar_zenith : numeric
|
|
3222
|
+
True (not refraction-corrected) zenith angles in decimal
|
|
3223
|
+
degrees. Angles must be >=0 and <=90.
|
|
3224
|
+
|
|
3225
|
+
datetime_or_doy : numeric, pandas.DatetimeIndex
|
|
3226
|
+
Day of year or array of days of year e.g.
|
|
3227
|
+
pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
|
|
3228
|
+
|
|
3229
|
+
Returns
|
|
3230
|
+
-------
|
|
3231
|
+
data: OrderedDict or DataFrame
|
|
3232
|
+
Contains the following keys/columns:
|
|
3233
|
+
|
|
3234
|
+
* ``dni``: the modeled direct normal irradiance in W/m^2.
|
|
3235
|
+
* ``dhi``: the modeled diffuse horizontal irradiance in
|
|
3236
|
+
W/m^2.
|
|
3237
|
+
* ``kt``: Ratio of global to extraterrestrial irradiance
|
|
3238
|
+
on a horizontal plane.
|
|
3239
|
+
|
|
3240
|
+
References
|
|
3241
|
+
-------
|
|
3242
|
+
.. [1] Louche A, Notton G, Poggi P, Simonnot G. Correlations for direct
|
|
3243
|
+
normal and global horizontal irradiation on a French Mediterranean site.
|
|
3244
|
+
Solar Energy 1991;46:261-6. :doi:`10.1016/0038-092X(91)90072-5`
|
|
3245
|
+
|
|
3246
|
+
"""
|
|
3247
|
+
|
|
3248
|
+
I0 = get_extra_radiation(datetime_or_doy)
|
|
3249
|
+
|
|
3250
|
+
Kt = clearness_index(ghi, solar_zenith, I0)
|
|
3251
|
+
|
|
3252
|
+
kb = -10.627*Kt**5 + 15.307*Kt**4 - 5.205 * \
|
|
3253
|
+
Kt**3 + 0.994*Kt**2 - 0.059*Kt + 0.002
|
|
3254
|
+
dni = kb*I0
|
|
3255
|
+
dhi = ghi - dni*tools.cosd(solar_zenith)
|
|
3256
|
+
|
|
3257
|
+
bad_values = (solar_zenith > max_zenith) | (ghi < 0) | (dni < 0)
|
|
3258
|
+
dni = np.where(bad_values, 0, dni)
|
|
3259
|
+
# ensure that closure relationship remains valid
|
|
3260
|
+
dhi = np.where(bad_values, ghi, dhi)
|
|
3261
|
+
|
|
3262
|
+
data = OrderedDict()
|
|
3263
|
+
data['dni'] = dni
|
|
3264
|
+
data['dhi'] = dhi
|
|
3265
|
+
data['kt'] = Kt
|
|
3266
|
+
|
|
3267
|
+
if isinstance(datetime_or_doy, pd.DatetimeIndex):
|
|
3268
|
+
data = pd.DataFrame(data, index=datetime_or_doy)
|
|
3269
|
+
|
|
3270
|
+
return data
|