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.
- pvlib/__init__.py +1 -0
- pvlib/_deprecation.py +73 -0
- pvlib/atmosphere.py +77 -7
- pvlib/bifacial/infinite_sheds.py +4 -3
- pvlib/bifacial/utils.py +2 -1
- pvlib/clearsky.py +35 -22
- pvlib/iam.py +4 -4
- pvlib/iotools/midc.py +1 -1
- pvlib/iotools/psm3.py +1 -1
- pvlib/iotools/pvgis.py +10 -12
- pvlib/iotools/tmy.py +3 -69
- pvlib/irradiance.py +112 -55
- pvlib/ivtools/sdm.py +75 -52
- pvlib/location.py +73 -33
- pvlib/modelchain.py +18 -35
- pvlib/pvsystem.py +139 -94
- pvlib/snow.py +64 -28
- pvlib/solarposition.py +46 -30
- pvlib/spa.py +4 -2
- pvlib/spectrum/__init__.py +0 -1
- pvlib/spectrum/irradiance.py +2 -64
- pvlib/spectrum/mismatch.py +3 -3
- pvlib/spectrum/spectrl2.py +2 -1
- pvlib/temperature.py +49 -3
- pvlib/tools.py +6 -5
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/METADATA +14 -11
- pvlib-0.12.0.dist-info/RECORD +75 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
- pvlib/data/BIRD_08_16_2012.csv +0 -8761
- pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
- pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
- pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
- pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
- pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
- pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
- pvlib/data/CRN_with_problems.txt +0 -3
- pvlib/data/ET-M772BH550GL.PAN +0 -75
- pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
- pvlib/data/PVsyst_demo.csv +0 -10757
- pvlib/data/PVsyst_demo_model.csv +0 -3588
- pvlib/data/SRML-day-EUPO1801.txt +0 -1441
- pvlib/data/abq19056.dat +0 -6
- pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
- pvlib/data/bishop88_numerical_precision.csv +0 -101
- pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
- pvlib/data/bsrn-pay0616.dat.gz +0 -0
- pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
- pvlib/data/cams_mcclear_monthly.csv +0 -42
- pvlib/data/cams_radiation_1min_verbose.csv +0 -72
- pvlib/data/cams_radiation_monthly.csv +0 -47
- pvlib/data/detect_clearsky_data.csv +0 -35
- pvlib/data/detect_clearsky_threshold_data.csv +0 -126
- pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
- pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
- pvlib/data/inverter_fit_snl_meas.csv +0 -127
- pvlib/data/inverter_fit_snl_sim.csv +0 -19
- pvlib/data/ivtools_numdiff.csv +0 -52
- pvlib/data/midc_20181014.txt +0 -1441
- pvlib/data/midc_raw_20181018.txt +0 -1441
- pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
- pvlib/data/msn19056.dat +0 -6
- pvlib/data/precise_iv_curves1.json +0 -10251
- pvlib/data/precise_iv_curves2.json +0 -10251
- pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
- pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
- pvlib/data/pvgis_tmy_meta.json +0 -32
- pvlib/data/pvgis_tmy_test.dat +0 -8761
- pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
- pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
- pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
- pvlib/data/spectrl2_example_spectra.csv +0 -123
- pvlib/data/surfrad-slv16001.dat +0 -1442
- pvlib/data/test_psm3_2017.csv +0 -17521
- pvlib/data/test_psm3_2019_5min.csv +0 -289
- pvlib/data/test_psm3_tmy-2017.csv +0 -8761
- pvlib/data/test_read_psm3.csv +0 -17523
- pvlib/data/test_read_pvgis_horizon.csv +0 -49
- pvlib/data/tmy_45.000_8.000_2005_2020.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2020.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2020.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2020.txt +0 -8761
- pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
- pvlib/data/variables_style_rules.csv +0 -56
- pvlib/spa_c_files/README.md +0 -81
- pvlib/spa_c_files/cspa_py.pxd +0 -43
- pvlib/spa_c_files/spa_py.pyx +0 -30
- pvlib/tests/__init__.py +0 -0
- pvlib/tests/bifacial/__init__.py +0 -0
- pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
- pvlib/tests/bifacial/test_losses_models.py +0 -54
- pvlib/tests/bifacial/test_pvfactors.py +0 -82
- pvlib/tests/bifacial/test_utils.py +0 -192
- pvlib/tests/conftest.py +0 -476
- pvlib/tests/iotools/__init__.py +0 -0
- pvlib/tests/iotools/test_acis.py +0 -213
- pvlib/tests/iotools/test_bsrn.py +0 -131
- pvlib/tests/iotools/test_crn.py +0 -95
- pvlib/tests/iotools/test_epw.py +0 -23
- pvlib/tests/iotools/test_midc.py +0 -89
- pvlib/tests/iotools/test_panond.py +0 -32
- pvlib/tests/iotools/test_psm3.py +0 -198
- pvlib/tests/iotools/test_pvgis.py +0 -644
- pvlib/tests/iotools/test_sodapro.py +0 -298
- pvlib/tests/iotools/test_solaranywhere.py +0 -287
- pvlib/tests/iotools/test_solargis.py +0 -68
- pvlib/tests/iotools/test_solcast.py +0 -324
- pvlib/tests/iotools/test_solrad.py +0 -152
- pvlib/tests/iotools/test_srml.py +0 -124
- pvlib/tests/iotools/test_surfrad.py +0 -75
- pvlib/tests/iotools/test_tmy.py +0 -133
- pvlib/tests/ivtools/__init__.py +0 -0
- pvlib/tests/ivtools/test_sde.py +0 -230
- pvlib/tests/ivtools/test_sdm.py +0 -407
- pvlib/tests/ivtools/test_utils.py +0 -173
- pvlib/tests/spectrum/__init__.py +0 -0
- pvlib/tests/spectrum/conftest.py +0 -40
- pvlib/tests/spectrum/test_irradiance.py +0 -138
- pvlib/tests/spectrum/test_mismatch.py +0 -304
- pvlib/tests/spectrum/test_response.py +0 -124
- pvlib/tests/spectrum/test_spectrl2.py +0 -72
- pvlib/tests/test_albedo.py +0 -84
- pvlib/tests/test_atmosphere.py +0 -204
- pvlib/tests/test_clearsky.py +0 -878
- pvlib/tests/test_conftest.py +0 -81
- pvlib/tests/test_iam.py +0 -555
- pvlib/tests/test_inverter.py +0 -213
- pvlib/tests/test_irradiance.py +0 -1441
- pvlib/tests/test_location.py +0 -356
- pvlib/tests/test_modelchain.py +0 -2020
- pvlib/tests/test_numerical_precision.py +0 -124
- pvlib/tests/test_pvarray.py +0 -71
- pvlib/tests/test_pvsystem.py +0 -2495
- pvlib/tests/test_scaling.py +0 -207
- pvlib/tests/test_shading.py +0 -391
- pvlib/tests/test_singlediode.py +0 -608
- pvlib/tests/test_snow.py +0 -212
- pvlib/tests/test_soiling.py +0 -230
- pvlib/tests/test_solarposition.py +0 -933
- pvlib/tests/test_spa.py +0 -425
- pvlib/tests/test_temperature.py +0 -470
- pvlib/tests/test_tools.py +0 -146
- pvlib/tests/test_tracking.py +0 -474
- pvlib/tests/test_transformer.py +0 -60
- pvlib-0.11.1.dist-info/RECORD +0 -192
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
pvlib/pvsystem.py
CHANGED
|
@@ -17,7 +17,7 @@ from dataclasses import dataclass
|
|
|
17
17
|
from abc import ABC, abstractmethod
|
|
18
18
|
from typing import Optional, Union
|
|
19
19
|
|
|
20
|
-
from pvlib._deprecation import deprecated
|
|
20
|
+
from pvlib._deprecation import deprecated
|
|
21
21
|
|
|
22
22
|
import pvlib # used to avoid albedo name collision in the Array class
|
|
23
23
|
from pvlib import (atmosphere, iam, inverter, irradiance,
|
|
@@ -29,11 +29,10 @@ import pvlib.tools as tools
|
|
|
29
29
|
# a dict of required parameter names for each DC power model
|
|
30
30
|
_DC_MODEL_PARAMS = {
|
|
31
31
|
'sapm': {
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'C7', 'Isco', 'Impo', 'Voco', 'Vmpo', 'Aisc', 'Aimp', 'Bvoco',
|
|
32
|
+
'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7',
|
|
33
|
+
'Isco', 'Impo', 'Voco', 'Vmpo', 'Aisc', 'Aimp', 'Bvoco',
|
|
35
34
|
'Mbvoc', 'Bvmpo', 'Mbvmp', 'N', 'Cells_in_Series',
|
|
36
|
-
'IXO', 'IXXO'
|
|
35
|
+
'IXO', 'IXXO'},
|
|
37
36
|
'desoto': {
|
|
38
37
|
'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref',
|
|
39
38
|
'R_sh_ref', 'R_s'},
|
|
@@ -104,22 +103,22 @@ class PVSystem:
|
|
|
104
103
|
----------
|
|
105
104
|
arrays : Array or iterable of Array, optional
|
|
106
105
|
An Array or list of arrays that are part of the system. If not
|
|
107
|
-
specified a single array is created from the other parameters (e.g.
|
|
106
|
+
specified, a single array is created from the other parameters (e.g.
|
|
108
107
|
`surface_tilt`, `surface_azimuth`). If specified as a list, the list
|
|
109
108
|
must contain at least one Array;
|
|
110
109
|
if length of arrays is 0 a ValueError is raised. If `arrays` is
|
|
111
110
|
specified the following PVSystem parameters are ignored:
|
|
112
111
|
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
112
|
+
- ``surface_tilt``
|
|
113
|
+
- ``surface_azimuth``
|
|
114
|
+
- ``albedo``
|
|
115
|
+
- ``surface_type``
|
|
116
|
+
- ``module``
|
|
117
|
+
- ``module_type``
|
|
118
|
+
- ``module_parameters``
|
|
119
|
+
- ``temperature_model_parameters``
|
|
120
|
+
- ``modules_per_string``
|
|
121
|
+
- ``strings_per_inverter``
|
|
123
122
|
|
|
124
123
|
surface_tilt: float or array-like, default 0
|
|
125
124
|
Surface tilt angles in decimal degrees.
|
|
@@ -127,7 +126,7 @@ class PVSystem:
|
|
|
127
126
|
(e.g. surface facing up = 0, surface facing horizon = 90)
|
|
128
127
|
|
|
129
128
|
surface_azimuth: float or array-like, default 180
|
|
130
|
-
Azimuth angle of the module surface.
|
|
129
|
+
Azimuth angle of the module surface in decimal degrees.
|
|
131
130
|
North=0, East=90, South=180, West=270.
|
|
132
131
|
|
|
133
132
|
albedo : float, optional
|
|
@@ -142,8 +141,6 @@ class PVSystem:
|
|
|
142
141
|
|
|
143
142
|
module : string, optional
|
|
144
143
|
The model name of the modules.
|
|
145
|
-
May be used to look up the module_parameters dictionary
|
|
146
|
-
via some other method.
|
|
147
144
|
|
|
148
145
|
module_type : string, default 'glass_polymer'
|
|
149
146
|
Describes the module's construction. Valid strings are 'glass_polymer'
|
|
@@ -154,7 +151,8 @@ class PVSystem:
|
|
|
154
151
|
|
|
155
152
|
temperature_model_parameters : dict or Series, optional
|
|
156
153
|
Temperature model parameters as required by one of the models in
|
|
157
|
-
pvlib.temperature (excluding poa_global
|
|
154
|
+
:py:mod:`pvlib.temperature` (excluding ``poa_global``, ``temp_air`` and
|
|
155
|
+
``wind_speed``).
|
|
158
156
|
|
|
159
157
|
modules_per_string: int or float, default 1
|
|
160
158
|
See system topology discussion above.
|
|
@@ -164,15 +162,17 @@ class PVSystem:
|
|
|
164
162
|
|
|
165
163
|
inverter : string, optional
|
|
166
164
|
The model name of the inverters.
|
|
167
|
-
May be used to look up the inverter_parameters dictionary
|
|
168
|
-
via some other method.
|
|
169
165
|
|
|
170
166
|
inverter_parameters : dict or Series, optional
|
|
171
167
|
Inverter parameters as defined by the SAPM, CEC, or other.
|
|
172
168
|
|
|
173
|
-
racking_model : string,
|
|
174
|
-
Valid strings are 'open_rack'
|
|
175
|
-
|
|
169
|
+
racking_model : string, optional
|
|
170
|
+
Valid strings are ``'open_rack'``, ``'close_mount'``,
|
|
171
|
+
``'insulated_back'``, ``'freestanding'`` and ``'insulated'``.
|
|
172
|
+
Used to identify a parameter set for the SAPM or PVsyst cell
|
|
173
|
+
temperature model.
|
|
174
|
+
See :py:func:`~pvlib.temperature.sapm_module` and
|
|
175
|
+
:py:func:`~pvlib.temperature.pvsyst_cell` for definitions.
|
|
176
176
|
|
|
177
177
|
losses_parameters : dict or Series, optional
|
|
178
178
|
Losses parameters as defined by PVWatts or other.
|
|
@@ -186,7 +186,7 @@ class PVSystem:
|
|
|
186
186
|
Raises
|
|
187
187
|
------
|
|
188
188
|
ValueError
|
|
189
|
-
If
|
|
189
|
+
If ``arrays`` is not None and has length 0.
|
|
190
190
|
|
|
191
191
|
See also
|
|
192
192
|
--------
|
|
@@ -312,7 +312,7 @@ class PVSystem:
|
|
|
312
312
|
dni_extra=None, airmass=None, albedo=None,
|
|
313
313
|
model='haydavies', **kwargs):
|
|
314
314
|
"""
|
|
315
|
-
Uses
|
|
315
|
+
Uses :py:func:`pvlib.irradiance.get_total_irradiance` to
|
|
316
316
|
calculate the plane of array irradiance components on the tilted
|
|
317
317
|
surfaces defined by each array's ``surface_tilt`` and
|
|
318
318
|
``surface_azimuth``.
|
|
@@ -323,11 +323,11 @@ class PVSystem:
|
|
|
323
323
|
Solar zenith angle.
|
|
324
324
|
solar_azimuth : float or Series
|
|
325
325
|
Solar azimuth angle.
|
|
326
|
-
dni : float
|
|
326
|
+
dni : float, Series, or tuple of float or Series
|
|
327
327
|
Direct Normal Irradiance. [W/m2]
|
|
328
|
-
ghi : float
|
|
328
|
+
ghi : float, Series, or tuple of float or Series
|
|
329
329
|
Global horizontal irradiance. [W/m2]
|
|
330
|
-
dhi : float
|
|
330
|
+
dhi : float, Series, or tuple of float or Series
|
|
331
331
|
Diffuse horizontal irradiance. [W/m2]
|
|
332
332
|
dni_extra : float, Series or tuple of float or Series, optional
|
|
333
333
|
Extraterrestrial direct normal irradiance. [W/m2]
|
|
@@ -339,15 +339,22 @@ class PVSystem:
|
|
|
339
339
|
Irradiance model.
|
|
340
340
|
|
|
341
341
|
kwargs
|
|
342
|
-
Extra parameters passed to
|
|
342
|
+
Extra parameters passed to
|
|
343
|
+
:py:func:`pvlib.irradiance.get_total_irradiance`.
|
|
343
344
|
|
|
344
345
|
Notes
|
|
345
346
|
-----
|
|
346
|
-
Each of
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
347
|
+
Each of ``dni``, ``ghi``, and ``dni`` may be passed as a float, Series,
|
|
348
|
+
or tuple of float or Series. If passed as a float or Series, these
|
|
349
|
+
values are used for all Arrays. If passed as a tuple, the tuple length
|
|
350
|
+
must be the same as the number of Arrays. The first tuple element is
|
|
351
|
+
used for the first Array, the second tuple element for the second
|
|
352
|
+
Array, and so forth.
|
|
353
|
+
|
|
354
|
+
Some sky irradiance models require ``dni_extra``. For these models,
|
|
355
|
+
if ``dni_extra`` is not provided and ``solar_zenith`` has a
|
|
356
|
+
``DatetimeIndex``, then ``dni_extra`` is calculated.
|
|
357
|
+
Otherwise, ``dni_extra=1367`` is assumed.
|
|
351
358
|
|
|
352
359
|
Returns
|
|
353
360
|
-------
|
|
@@ -1077,7 +1084,7 @@ class Array:
|
|
|
1077
1084
|
"""
|
|
1078
1085
|
Get plane of array irradiance components.
|
|
1079
1086
|
|
|
1080
|
-
Uses
|
|
1087
|
+
Uses :py:func:`pvlib.irradiance.get_total_irradiance` to
|
|
1081
1088
|
calculate the plane of array irradiance components for a surface
|
|
1082
1089
|
defined by ``self.surface_tilt`` and ``self.surface_azimuth``.
|
|
1083
1090
|
|
|
@@ -1112,6 +1119,13 @@ class Array:
|
|
|
1112
1119
|
Column names are: ``'poa_global', 'poa_direct', 'poa_diffuse',
|
|
1113
1120
|
'poa_sky_diffuse', 'poa_ground_diffuse'``.
|
|
1114
1121
|
|
|
1122
|
+
Notes
|
|
1123
|
+
-----
|
|
1124
|
+
Some sky irradiance models require ``dni_extra``. For these models,
|
|
1125
|
+
if ``dni_extra`` is not provided and ``solar_zenith`` has a
|
|
1126
|
+
``DatetimeIndex``, then ``dni_extra`` is calculated.
|
|
1127
|
+
Otherwise, ``dni_extra=1367`` is assumed.
|
|
1128
|
+
|
|
1115
1129
|
See also
|
|
1116
1130
|
--------
|
|
1117
1131
|
:py:func:`pvlib.irradiance.get_total_irradiance`
|
|
@@ -1119,9 +1133,16 @@ class Array:
|
|
|
1119
1133
|
if albedo is None:
|
|
1120
1134
|
albedo = self.albedo
|
|
1121
1135
|
|
|
1122
|
-
# not needed for all models, but this is easier
|
|
1136
|
+
# dni_extra is not needed for all models, but this is easier
|
|
1123
1137
|
if dni_extra is None:
|
|
1124
|
-
|
|
1138
|
+
if (hasattr(solar_zenith, 'index') and
|
|
1139
|
+
isinstance(solar_zenith.index, pd.DatetimeIndex)):
|
|
1140
|
+
# calculate extraterrestrial irradiance
|
|
1141
|
+
dni_extra = irradiance.get_extra_radiation(
|
|
1142
|
+
solar_zenith.index)
|
|
1143
|
+
else:
|
|
1144
|
+
# use the solar constant
|
|
1145
|
+
dni_extra = 1367.0
|
|
1125
1146
|
|
|
1126
1147
|
if airmass is None:
|
|
1127
1148
|
airmass = atmosphere.get_relative_airmass(solar_zenith)
|
|
@@ -1374,8 +1395,12 @@ class FixedMount(AbstractMount):
|
|
|
1374
1395
|
West=270. [degrees]
|
|
1375
1396
|
|
|
1376
1397
|
racking_model : str, optional
|
|
1377
|
-
Valid strings are 'open_rack'
|
|
1378
|
-
|
|
1398
|
+
Valid strings are ``'open_rack'``, ``'close_mount'``,
|
|
1399
|
+
``'insulated_back'``, ``'freestanding'`` and ``'insulated'``.
|
|
1400
|
+
Used to identify a parameter set for the SAPM or PVsyst cell
|
|
1401
|
+
temperature model.
|
|
1402
|
+
See :py:func:`~pvlib.temperature.sapm_module` and
|
|
1403
|
+
:py:func:`~pvlib.temperature.pvsyst_cell` for definitions.
|
|
1379
1404
|
|
|
1380
1405
|
module_height : float, optional
|
|
1381
1406
|
The height above ground of the center of the module [m]. Used for
|
|
@@ -1451,8 +1476,13 @@ class SingleAxisTrackerMount(AbstractMount):
|
|
|
1451
1476
|
`cross_axis_tilt`. [degrees]
|
|
1452
1477
|
|
|
1453
1478
|
racking_model : str, optional
|
|
1454
|
-
Valid strings are 'open_rack'
|
|
1455
|
-
|
|
1479
|
+
Valid strings are ``'open_rack'``, ``'close_mount'``,
|
|
1480
|
+
``'insulated_back'``, ``'freestanding'`` and ``'insulated'``.
|
|
1481
|
+
Used to identify a parameter set for the SAPM or PVsyst cell
|
|
1482
|
+
temperature model. ``'open_rack'`` or ``'freestanding'`` should
|
|
1483
|
+
be used for systems with single-axis trackers.
|
|
1484
|
+
See :py:func:`~pvlib.temperature.sapm_module` and
|
|
1485
|
+
:py:func:`~pvlib.temperature.pvsyst_cell` for definitions.
|
|
1456
1486
|
|
|
1457
1487
|
module_height : float, optional
|
|
1458
1488
|
The height above ground of the center of the module [m]. Used for
|
|
@@ -1679,6 +1709,8 @@ def calcparams_desoto(effective_irradiance, temp_cell,
|
|
|
1679
1709
|
Rs = R_s
|
|
1680
1710
|
|
|
1681
1711
|
numeric_args = (effective_irradiance, temp_cell)
|
|
1712
|
+
# IL: photocurrent, I0: saturation_current, Rs: resistance_series,
|
|
1713
|
+
# Rsh: resistance_shunt
|
|
1682
1714
|
out = (IL, I0, Rs, Rsh, nNsVth)
|
|
1683
1715
|
|
|
1684
1716
|
if all(map(np.isscalar, numeric_args)):
|
|
@@ -1945,6 +1977,8 @@ def calcparams_pvsyst(effective_irradiance, temp_cell,
|
|
|
1945
1977
|
Rs = R_s
|
|
1946
1978
|
|
|
1947
1979
|
numeric_args = (effective_irradiance, temp_cell)
|
|
1980
|
+
# IL: photocurrent, I0: saturation_current, Rs: resistance_series,
|
|
1981
|
+
# Rsh: resistance_shunt
|
|
1948
1982
|
out = (IL, I0, Rs, Rsh, nNsVth)
|
|
1949
1983
|
|
|
1950
1984
|
if all(map(np.isscalar, numeric_args)):
|
|
@@ -1965,10 +1999,10 @@ def retrieve_sam(name=None, path=None):
|
|
|
1965
1999
|
|
|
1966
2000
|
This function will retrieve either:
|
|
1967
2001
|
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2002
|
+
* CEC module database
|
|
2003
|
+
* Sandia Module database
|
|
2004
|
+
* CEC Inverter database
|
|
2005
|
+
* Anton Driesse Inverter database
|
|
1972
2006
|
|
|
1973
2007
|
and return it as a pandas DataFrame.
|
|
1974
2008
|
|
|
@@ -1981,20 +2015,20 @@ def retrieve_sam(name=None, path=None):
|
|
|
1981
2015
|
Use one of the following strings to retrieve a database bundled with
|
|
1982
2016
|
pvlib:
|
|
1983
2017
|
|
|
1984
|
-
* 'CECMod' - returns the CEC module database
|
|
1985
|
-
* 'CECInverter' - returns the CEC Inverter database
|
|
1986
|
-
* 'SandiaInverter' - returns the CEC Inverter database
|
|
2018
|
+
* ``'CECMod'`` - returns the CEC module database
|
|
2019
|
+
* ``'CECInverter'`` - returns the CEC Inverter database
|
|
2020
|
+
* ``'SandiaInverter'`` - returns the CEC Inverter database
|
|
1987
2021
|
(CEC is only current inverter db available; tag kept for
|
|
1988
2022
|
backwards compatibility)
|
|
1989
|
-
* 'SandiaMod' - returns the Sandia Module database
|
|
1990
|
-
* 'ADRInverter' - returns the ADR Inverter database
|
|
2023
|
+
* ``'SandiaMod'`` - returns the Sandia Module database
|
|
2024
|
+
* ``'ADRInverter'`` - returns the ADR Inverter database
|
|
1991
2025
|
|
|
1992
2026
|
path : string, optional
|
|
1993
2027
|
Path to a CSV file or a URL.
|
|
1994
2028
|
|
|
1995
2029
|
Returns
|
|
1996
2030
|
-------
|
|
1997
|
-
|
|
2031
|
+
DataFrame
|
|
1998
2032
|
A DataFrame containing all the elements of the desired database.
|
|
1999
2033
|
Each column represents a module or inverter, and a specific
|
|
2000
2034
|
dataset can be retrieved by the command
|
|
@@ -2012,14 +2046,13 @@ def retrieve_sam(name=None, path=None):
|
|
|
2012
2046
|
-----
|
|
2013
2047
|
Files available at
|
|
2014
2048
|
https://github.com/NREL/SAM/tree/develop/deploy/libraries
|
|
2015
|
-
Documentation for module and inverter data sets:
|
|
2016
|
-
https://sam.nrel.gov/photovoltaic/pv-sub-page-2.html
|
|
2017
2049
|
|
|
2018
2050
|
Examples
|
|
2019
2051
|
--------
|
|
2052
|
+
Using a database bundled with pvlib:
|
|
2020
2053
|
|
|
2021
2054
|
>>> from pvlib import pvsystem
|
|
2022
|
-
>>> invdb = pvsystem.retrieve_sam('CECInverter')
|
|
2055
|
+
>>> invdb = pvsystem.retrieve_sam(name='CECInverter')
|
|
2023
2056
|
>>> inverter = invdb.AE_Solar_Energy__AE6_0__277V_
|
|
2024
2057
|
>>> inverter
|
|
2025
2058
|
Vac 277
|
|
@@ -2039,7 +2072,15 @@ def retrieve_sam(name=None, path=None):
|
|
|
2039
2072
|
CEC_Date NaN
|
|
2040
2073
|
CEC_Type Utility Interactive
|
|
2041
2074
|
Name: AE_Solar_Energy__AE6_0__277V_, dtype: object
|
|
2042
|
-
|
|
2075
|
+
|
|
2076
|
+
Using a remote database, via URL:
|
|
2077
|
+
|
|
2078
|
+
>>> url = "https://raw.githubusercontent.com/NREL/SAM/refs/heads/develop/deploy/libraries/CEC%20Inverters.csv"
|
|
2079
|
+
>>> inv_db = pvsystem.retrieve_sam(path=url)
|
|
2080
|
+
>>> inv_db.keys()
|
|
2081
|
+
Index(['ABB__PVI_3_0_OUTD_S_US_A__208V_', 'ABB__PVI_3_0_OUTD_S_US_A__240V_', ...],
|
|
2082
|
+
dtype='object', length=...)
|
|
2083
|
+
""" # noqa: E501
|
|
2043
2084
|
# error: path was previously silently ignored if name was given GH#2018
|
|
2044
2085
|
if name is not None and path is not None:
|
|
2045
2086
|
raise ValueError("Please provide either 'name' or 'path', not both.")
|
|
@@ -2273,12 +2314,6 @@ def sapm(effective_irradiance, temp_cell, module):
|
|
|
2273
2314
|
return out
|
|
2274
2315
|
|
|
2275
2316
|
|
|
2276
|
-
sapm_spectral_loss = deprecated(
|
|
2277
|
-
since='0.10.0',
|
|
2278
|
-
alternative='pvlib.spectrum.spectral_factor_sapm'
|
|
2279
|
-
)(spectrum.spectral_factor_sapm)
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
2317
|
def sapm_effective_irradiance(poa_direct, poa_diffuse, airmass_absolute, aoi,
|
|
2283
2318
|
module):
|
|
2284
2319
|
r"""
|
|
@@ -2871,46 +2906,49 @@ def pvwatts_losses(soiling=2, shading=3, snow=0, mismatch=2, wiring=2,
|
|
|
2871
2906
|
def dc_ohms_from_percent(vmp_ref, imp_ref, dc_ohmic_percent,
|
|
2872
2907
|
modules_per_string=1,
|
|
2873
2908
|
strings=1):
|
|
2874
|
-
"""
|
|
2875
|
-
|
|
2876
|
-
ohmic loss at
|
|
2877
|
-
|
|
2878
|
-
Equivalent resistance is calculated with the function:
|
|
2879
|
-
|
|
2880
|
-
.. math::
|
|
2881
|
-
Rw = (L_{stc} / 100) * (Varray / Iarray)
|
|
2882
|
-
|
|
2883
|
-
:math:`Rw` is the equivalent resistance in ohms
|
|
2884
|
-
:math:`Varray` is the Vmp of the modules times modules per string
|
|
2885
|
-
:math:`Iarray` is the Imp of the modules times strings per array
|
|
2886
|
-
:math:`L_{stc}` is the input dc loss percent
|
|
2909
|
+
r"""
|
|
2910
|
+
Calculate the equivalent resistance of the conductors from the percent
|
|
2911
|
+
ohmic loss of an array at reference conditions.
|
|
2887
2912
|
|
|
2888
2913
|
Parameters
|
|
2889
2914
|
----------
|
|
2890
2915
|
vmp_ref: numeric
|
|
2891
|
-
|
|
2916
|
+
Maximum power voltage of one module at reference conditions. [V]
|
|
2892
2917
|
imp_ref: numeric
|
|
2893
|
-
|
|
2894
|
-
dc_ohmic_percent: numeric
|
|
2895
|
-
|
|
2918
|
+
Maximum power current of one module at reference conditions. [A]
|
|
2919
|
+
dc_ohmic_percent: numeric
|
|
2920
|
+
Array DC power loss as a percent of DC power loss at reference
|
|
2921
|
+
conditions. In percent, e.g. 1.5% loss is input as 1.5.
|
|
2896
2922
|
modules_per_string: int, default 1
|
|
2897
|
-
Number of modules per string in the array.
|
|
2923
|
+
Number of series-connected modules per string in the array.
|
|
2898
2924
|
strings: int, default 1
|
|
2899
2925
|
Number of parallel strings in the array.
|
|
2900
2926
|
|
|
2901
2927
|
Returns
|
|
2902
2928
|
----------
|
|
2903
2929
|
Rw: numeric
|
|
2904
|
-
Equivalent resistance [ohm]
|
|
2930
|
+
Equivalent resistance. [ohm]
|
|
2905
2931
|
|
|
2906
2932
|
See Also
|
|
2907
2933
|
--------
|
|
2908
2934
|
pvlib.pvsystem.dc_ohmic_losses
|
|
2909
2935
|
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2936
|
+
Notes
|
|
2937
|
+
-----
|
|
2938
|
+
Equivalent resistance is calculated as:
|
|
2939
|
+
|
|
2940
|
+
.. math::
|
|
2941
|
+
|
|
2942
|
+
R_w = \left(\frac{L_{stc}}{100}\right) \times \left(\frac{
|
|
2943
|
+
V_{array}}{I_{array}}\right)
|
|
2944
|
+
|
|
2945
|
+
:math:`R_w` is the equivalent resistance in ohms.
|
|
2946
|
+
:math:`V_{array}` is the array voltage, equal to ``vmp_ref`` times
|
|
2947
|
+
``modules_per_string``.
|
|
2948
|
+
:math:`I_{array}` is the array current, equal to ``imp_ref`` times
|
|
2949
|
+
``strings``.
|
|
2950
|
+
:math:`L_{stc}` is the input DC loss percent at reference conditions.
|
|
2951
|
+
|
|
2914
2952
|
"""
|
|
2915
2953
|
vmp = modules_per_string * vmp_ref
|
|
2916
2954
|
|
|
@@ -2922,30 +2960,37 @@ def dc_ohms_from_percent(vmp_ref, imp_ref, dc_ohmic_percent,
|
|
|
2922
2960
|
|
|
2923
2961
|
|
|
2924
2962
|
def dc_ohmic_losses(resistance, current):
|
|
2925
|
-
"""
|
|
2963
|
+
r"""
|
|
2926
2964
|
Returns ohmic losses in units of power from the equivalent
|
|
2927
2965
|
resistance of the wires and the operating current.
|
|
2928
2966
|
|
|
2929
2967
|
Parameters
|
|
2930
2968
|
----------
|
|
2931
2969
|
resistance: numeric
|
|
2932
|
-
Equivalent resistance of wires [ohm]
|
|
2970
|
+
Equivalent resistance of wires. [ohm]
|
|
2933
2971
|
current: numeric, float or array-like
|
|
2934
|
-
Operating current [A]
|
|
2972
|
+
Operating current. [A]
|
|
2935
2973
|
|
|
2936
2974
|
Returns
|
|
2937
2975
|
----------
|
|
2938
2976
|
loss: numeric
|
|
2939
|
-
Power
|
|
2977
|
+
Power loss. [W]
|
|
2940
2978
|
|
|
2941
2979
|
See Also
|
|
2942
2980
|
--------
|
|
2943
2981
|
pvlib.pvsystem.dc_ohms_from_percent
|
|
2944
2982
|
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2983
|
+
Notes
|
|
2984
|
+
-----
|
|
2985
|
+
Ohmic (also termed joule or heat) loss is the power lost due to current
|
|
2986
|
+
flowing through a conductor. Ohmic loss, :math:`L`, is computed as
|
|
2987
|
+
|
|
2988
|
+
.. math::
|
|
2989
|
+
|
|
2990
|
+
L = I^2 \times R
|
|
2991
|
+
|
|
2992
|
+
where :math:`I` is the current (A) and :math:`R` is the resistance of the
|
|
2993
|
+
conductor (ohms).
|
|
2949
2994
|
"""
|
|
2950
2995
|
return resistance * current * current
|
|
2951
2996
|
|
pvlib/snow.py
CHANGED
|
@@ -13,30 +13,38 @@ def _time_delta_in_hours(times):
|
|
|
13
13
|
return delta.dt.total_seconds().div(3600)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def fully_covered_nrel(snowfall, threshold_snowfall=1
|
|
16
|
+
def fully_covered_nrel(snowfall, snow_depth=None, threshold_snowfall=1.,
|
|
17
|
+
threshold_depth=1.):
|
|
17
18
|
'''
|
|
18
|
-
Calculates the timesteps when
|
|
19
|
-
by snow.
|
|
19
|
+
Calculates the timesteps when modules are fully covered by snow.
|
|
20
20
|
|
|
21
21
|
Parameters
|
|
22
22
|
----------
|
|
23
|
-
snowfall
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
snowfall: Series
|
|
24
|
+
Snowfall in each time period. [cm]
|
|
25
|
+
snow_depth: Series, optional
|
|
26
|
+
Snow depth on the ground at the beginning of each time period.
|
|
27
|
+
Must have the same index as ``snowfall``. [cm]
|
|
28
|
+
threshold_snowfall: float, default 1.0
|
|
29
|
+
Hourly snowfall above which the row is fully covered for that hour.
|
|
30
|
+
[cm/hr]
|
|
31
|
+
threshold_depth: float, default 1.0
|
|
32
|
+
Snow depth on the ground, above which snow can affect the modules. [cm]
|
|
29
33
|
|
|
30
34
|
Returns
|
|
31
35
|
----------
|
|
32
|
-
|
|
33
|
-
True where the snowfall exceeds the defined
|
|
34
|
-
the panel.
|
|
36
|
+
covered: Series
|
|
37
|
+
A Series of boolean, True where the snowfall exceeds the defined
|
|
38
|
+
threshold to fully cover the panel.
|
|
35
39
|
|
|
36
40
|
Notes
|
|
37
41
|
-----
|
|
38
42
|
Implements the model described in [1]_ with minor improvements in [2]_.
|
|
39
43
|
|
|
44
|
+
``snow_depth`` is used to return `False` (not fully covered) when snow
|
|
45
|
+
is less than ``threshold_depth``. This check is described in [2]_ as needed
|
|
46
|
+
for systems with low tilt angle.
|
|
47
|
+
|
|
40
48
|
References
|
|
41
49
|
----------
|
|
42
50
|
.. [1] Marion, B.; Schaefer, R.; Caine, H.; Sanchez, G. (2013).
|
|
@@ -56,15 +64,20 @@ def fully_covered_nrel(snowfall, threshold_snowfall=1.):
|
|
|
56
64
|
hourly_snow_rate.iloc[0] = snowfall.iloc[0] / timedelta
|
|
57
65
|
else: # can't infer frequency from index
|
|
58
66
|
hourly_snow_rate.iloc[0] = 0 # replaces NaN
|
|
59
|
-
|
|
67
|
+
covered = (hourly_snow_rate > threshold_snowfall)
|
|
68
|
+
# no coverage when no snow on the ground
|
|
69
|
+
if snow_depth is not None:
|
|
70
|
+
covered = covered & (snow_depth >= threshold_depth)
|
|
71
|
+
return covered
|
|
60
72
|
|
|
61
73
|
|
|
62
74
|
def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
63
|
-
initial_coverage=0, threshold_snowfall=1.,
|
|
64
|
-
can_slide_coefficient=-80.,
|
|
75
|
+
snow_depth=None, initial_coverage=0, threshold_snowfall=1.,
|
|
76
|
+
threshold_depth=1., can_slide_coefficient=-80.,
|
|
77
|
+
slide_amount_coefficient=0.197):
|
|
65
78
|
'''
|
|
66
|
-
Calculates the fraction of the slant height of a row of modules
|
|
67
|
-
snow at every time step.
|
|
79
|
+
Calculates the fraction of the slant height of a row of modules that is
|
|
80
|
+
covered by snow at every time step.
|
|
68
81
|
|
|
69
82
|
Implements the model described in [1]_ with minor improvements in [2]_,
|
|
70
83
|
with the change that the output is in fraction of the row's slant height
|
|
@@ -74,7 +87,7 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
74
87
|
Parameters
|
|
75
88
|
----------
|
|
76
89
|
snowfall : Series
|
|
77
|
-
|
|
90
|
+
Snowfall within each time period. [cm]
|
|
78
91
|
poa_irradiance : Series
|
|
79
92
|
Total in-plane irradiance [W/m^2]
|
|
80
93
|
temp_air : Series
|
|
@@ -82,12 +95,17 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
82
95
|
surface_tilt : numeric
|
|
83
96
|
Tilt of module's from horizontal, e.g. surface facing up = 0,
|
|
84
97
|
surface facing horizon = 90. [degrees]
|
|
98
|
+
snow_depth : Series, optional
|
|
99
|
+
Snow depth on the ground at the beginning of each time period.
|
|
100
|
+
Must have the same index as ``snowfall``. [cm]
|
|
85
101
|
initial_coverage : float, default 0
|
|
86
102
|
Fraction of row's slant height that is covered with snow at the
|
|
87
103
|
beginning of the simulation. [unitless]
|
|
88
|
-
threshold_snowfall
|
|
89
|
-
Hourly snowfall above which
|
|
90
|
-
|
|
104
|
+
threshold_snowfall: float, default 1.0
|
|
105
|
+
Hourly snowfall above which the row is fully covered for that hour.
|
|
106
|
+
[cm/hr]
|
|
107
|
+
threshold_depth: float, default 1.0
|
|
108
|
+
Snow depth on the ground, above which snow can affect the modules. [cm]
|
|
91
109
|
can_slide_coefficient : float, default -80.
|
|
92
110
|
Coefficient to determine if snow can slide given irradiance and air
|
|
93
111
|
temperature. [W/(m^2 C)]
|
|
@@ -103,8 +121,12 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
103
121
|
|
|
104
122
|
Notes
|
|
105
123
|
-----
|
|
106
|
-
In [1]_,
|
|
107
|
-
|
|
124
|
+
In [1]_, ``can_slide_coefficient`` is termed `m`, and the value of
|
|
125
|
+
``slide_amount_coefficient`` is given in tenths of a module's slant height.
|
|
126
|
+
|
|
127
|
+
``snow_depth`` is used to set ``snow_coverage`` to 0 (not fully covered)
|
|
128
|
+
when snow is less than ``threshold_depth``. This check is described in
|
|
129
|
+
[2]_ as needed for systems with low tilt angle.
|
|
108
130
|
|
|
109
131
|
References
|
|
110
132
|
----------
|
|
@@ -117,7 +139,8 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
117
139
|
'''
|
|
118
140
|
|
|
119
141
|
# find times with new snowfall
|
|
120
|
-
new_snowfall = fully_covered_nrel(snowfall, threshold_snowfall
|
|
142
|
+
new_snowfall = fully_covered_nrel(snowfall, snow_depth, threshold_snowfall,
|
|
143
|
+
threshold_depth)
|
|
121
144
|
|
|
122
145
|
# set up output Series
|
|
123
146
|
snow_coverage = pd.Series(np.nan, index=poa_irradiance.index)
|
|
@@ -132,6 +155,13 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
132
155
|
# don't slide in the interval preceding the snowfall data
|
|
133
156
|
slide_amt.iloc[0] = 0
|
|
134
157
|
|
|
158
|
+
if snow_depth is not None:
|
|
159
|
+
# All slides off if snow on the ground is less than threshold_depth.
|
|
160
|
+
# Described in [2] to avoid non-sliding snow for low-tilt systems.
|
|
161
|
+
# Default threshold_depth of 1cm is from [2[ and SAM's implementation.
|
|
162
|
+
# https://github.com/NREL/ssc/issues/1265
|
|
163
|
+
slide_amt[snow_depth < threshold_depth] = 1.
|
|
164
|
+
|
|
135
165
|
# build time series of cumulative slide amounts
|
|
136
166
|
sliding_period_ID = new_snowfall.cumsum()
|
|
137
167
|
cumulative_sliding = slide_amt.groupby(sliding_period_ID).cumsum()
|
|
@@ -143,7 +173,6 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
|
|
|
143
173
|
snow_coverage.ffill(inplace=True)
|
|
144
174
|
snow_coverage -= cumulative_sliding
|
|
145
175
|
|
|
146
|
-
# clean up periods where row is completely uncovered
|
|
147
176
|
return snow_coverage.clip(lower=0)
|
|
148
177
|
|
|
149
178
|
|
|
@@ -278,9 +307,8 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity,
|
|
|
278
307
|
axis to the module edge.
|
|
279
308
|
|
|
280
309
|
The parameter `string_factor` is an enhancement added to the model after
|
|
281
|
-
publication of [1]_
|
|
282
|
-
definition for snow events documented above is
|
|
283
|
-
communication with the model's author.
|
|
310
|
+
publication of [1]_, as described in [2]_.
|
|
311
|
+
The definition for snow events documented above is based on [3]_.
|
|
284
312
|
|
|
285
313
|
References
|
|
286
314
|
----------
|
|
@@ -288,6 +316,14 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity,
|
|
|
288
316
|
update from two winters of measurements in the SIERRA. 37th IEEE
|
|
289
317
|
Photovoltaic Specialists Conference, Seattle, WA, USA.
|
|
290
318
|
:doi:`10.1109/PVSC.2011.6186627`
|
|
319
|
+
.. [2] Townsend, T. and Previtali, J. (2023). A Fresh Dusting: Current
|
|
320
|
+
Uses of the Townsend Snow Model. In "Photovoltaic Reliability
|
|
321
|
+
Workshop (PVRW) 2023 Proceedings: Posters.", ed. Silverman,
|
|
322
|
+
T. J. Dec. 2023. NREL/CP-5900-87918.
|
|
323
|
+
Available at: https://www.nrel.gov/docs/fy25osti/90585.pdf
|
|
324
|
+
.. [3] Townsend, T. (2013). Predicting PV Energy Loss Caused by Snow.
|
|
325
|
+
Solar Power International, Chicago IL.
|
|
326
|
+
:doi:`10.13140/RG.2.2.14299.68647`
|
|
291
327
|
'''
|
|
292
328
|
|
|
293
329
|
# unit conversions from cm and m to in, from C to K, and from % to fraction
|