pvlib 0.9.5__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 +6 -171
- pvlib/bifacial/infinite_sheds.py +30 -267
- pvlib/bifacial/utils.py +225 -5
- pvlib/data/test_psm3_2017.csv +17521 -17521
- 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 +17 -4
- 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 +32 -31
- 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 +151 -0
- pvlib/ivtools/sde.py +11 -7
- pvlib/ivtools/sdm.py +16 -10
- pvlib/ivtools/utils.py +6 -6
- pvlib/location.py +3 -2
- pvlib/modelchain.py +67 -70
- pvlib/pvsystem.py +160 -532
- pvlib/shading.py +41 -0
- pvlib/singlediode.py +215 -65
- 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 +1 -8
- pvlib/tests/bifacial/test_infinite_sheds.py +0 -111
- pvlib/tests/bifacial/test_utils.py +101 -4
- 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 +3 -3
- 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/test_atmosphere.py +6 -62
- pvlib/tests/test_iam.py +12 -0
- pvlib/tests/test_irradiance.py +40 -2
- pvlib/tests/test_location.py +1 -1
- pvlib/tests/test_modelchain.py +33 -76
- pvlib/tests/test_pvsystem.py +366 -201
- pvlib/tests/test_shading.py +28 -0
- pvlib/tests/test_singlediode.py +166 -30
- pvlib/tests/test_soiling.py +8 -7
- pvlib/tests/test_spa.py +6 -7
- pvlib/tests/test_spectrum.py +145 -1
- pvlib/tests/test_temperature.py +0 -7
- pvlib/tests/test_tools.py +25 -0
- pvlib/tests/test_tracking.py +0 -149
- pvlib/tools.py +26 -1
- pvlib/tracking.py +1 -269
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/METADATA +1 -9
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/RECORD +67 -68
- 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.5.dist-info → pvlib-0.10.0.dist-info}/AUTHORS.md +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/LICENSE +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/WHEEL +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
pvlib/__init__.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
from pvlib.version import __version__ # noqa: F401
|
|
2
2
|
|
|
3
3
|
from pvlib import ( # noqa: F401
|
|
4
|
+
# list spectrum first so it's available for atmosphere & pvsystem (GH 1628)
|
|
5
|
+
spectrum,
|
|
6
|
+
|
|
4
7
|
atmosphere,
|
|
5
8
|
bifacial,
|
|
6
9
|
clearsky,
|
|
7
|
-
# forecast
|
|
8
10
|
iam,
|
|
9
11
|
inverter,
|
|
10
12
|
iotools,
|
|
@@ -20,7 +22,6 @@ from pvlib import ( # noqa: F401
|
|
|
20
22
|
soiling,
|
|
21
23
|
solarposition,
|
|
22
24
|
spa,
|
|
23
|
-
spectrum,
|
|
24
25
|
temperature,
|
|
25
26
|
tools,
|
|
26
27
|
tracking,
|
pvlib/atmosphere.py
CHANGED
|
@@ -3,11 +3,11 @@ The ``atmosphere`` module contains methods to calculate relative and
|
|
|
3
3
|
absolute airmass and to determine pressure from altitude or vice versa.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from warnings import warn
|
|
7
|
-
|
|
8
6
|
import numpy as np
|
|
9
7
|
import pandas as pd
|
|
8
|
+
import pvlib
|
|
10
9
|
|
|
10
|
+
from pvlib._deprecation import deprecated
|
|
11
11
|
|
|
12
12
|
APPARENT_ZENITH_MODELS = ('simple', 'kasten1966', 'kastenyoung1989',
|
|
13
13
|
'gueymard1993', 'pickering2002')
|
|
@@ -336,175 +336,10 @@ def gueymard94_pw(temp_air, relative_humidity):
|
|
|
336
336
|
return pw
|
|
337
337
|
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
Spectral mismatch modifier based on precipitable water and absolute
|
|
344
|
-
(pressure-adjusted) airmass.
|
|
345
|
-
|
|
346
|
-
Estimates a spectral mismatch modifier :math:`M` representing the effect on
|
|
347
|
-
module short circuit current of variation in the spectral
|
|
348
|
-
irradiance. :math:`M` is estimated from absolute (pressure currected) air
|
|
349
|
-
mass, :math:`AM_a`, and precipitable water, :math:`Pw`, using the following
|
|
350
|
-
function:
|
|
351
|
-
|
|
352
|
-
.. math::
|
|
353
|
-
|
|
354
|
-
M = c_1 + c_2 AM_a + c_3 Pw + c_4 AM_a^{0.5}
|
|
355
|
-
+ c_5 Pw^{0.5} + c_6 \frac{AM_a} {Pw^{0.5}}
|
|
356
|
-
|
|
357
|
-
Default coefficients are determined for several cell types with
|
|
358
|
-
known quantum efficiency curves, by using the Simple Model of the
|
|
359
|
-
Atmospheric Radiative Transfer of Sunshine (SMARTS) [1]_. Using
|
|
360
|
-
SMARTS, spectrums are simulated with all combinations of AMa and
|
|
361
|
-
Pw where:
|
|
362
|
-
|
|
363
|
-
* :math:`0.5 \textrm{cm} <= Pw <= 5 \textrm{cm}`
|
|
364
|
-
* :math:`1.0 <= AM_a <= 5.0`
|
|
365
|
-
* Spectral range is limited to that of CMP11 (280 nm to 2800 nm)
|
|
366
|
-
* spectrum simulated on a plane normal to the sun
|
|
367
|
-
* All other parameters fixed at G173 standard
|
|
368
|
-
|
|
369
|
-
From these simulated spectra, M is calculated using the known
|
|
370
|
-
quantum efficiency curves. Multiple linear regression is then
|
|
371
|
-
applied to fit Eq. 1 to determine the coefficients for each module.
|
|
372
|
-
|
|
373
|
-
Based on the PVLIB Matlab function ``pvl_FSspeccorr`` by Mitchell
|
|
374
|
-
Lee and Alex Panchula of First Solar, 2016 [2]_.
|
|
375
|
-
|
|
376
|
-
Parameters
|
|
377
|
-
----------
|
|
378
|
-
pw : array-like
|
|
379
|
-
atmospheric precipitable water. [cm]
|
|
380
|
-
|
|
381
|
-
airmass_absolute : array-like
|
|
382
|
-
absolute (pressure-adjusted) airmass. [unitless]
|
|
383
|
-
|
|
384
|
-
min_pw : float, default 0.1
|
|
385
|
-
minimum atmospheric precipitable water. Any pw value lower than min_pw
|
|
386
|
-
is set to min_pw to avoid model divergence. [cm]
|
|
387
|
-
|
|
388
|
-
max_pw : float, default 8
|
|
389
|
-
maximum atmospheric precipitable water. Any pw value higher than max_pw
|
|
390
|
-
is set to NaN to avoid model divergence. [cm]
|
|
391
|
-
|
|
392
|
-
module_type : None or string, default None
|
|
393
|
-
a string specifying a cell type. Values of 'cdte', 'monosi', 'xsi',
|
|
394
|
-
'multisi', and 'polysi' (can be lower or upper case). If provided,
|
|
395
|
-
module_type selects default coefficients for the following modules:
|
|
396
|
-
|
|
397
|
-
* 'cdte' - First Solar Series 4-2 CdTe module.
|
|
398
|
-
* 'monosi', 'xsi' - First Solar TetraSun module.
|
|
399
|
-
* 'multisi', 'polysi' - anonymous multi-crystalline silicon module.
|
|
400
|
-
* 'cigs' - anonymous copper indium gallium selenide module.
|
|
401
|
-
* 'asi' - anonymous amorphous silicon module.
|
|
402
|
-
|
|
403
|
-
The module used to calculate the spectral correction
|
|
404
|
-
coefficients corresponds to the Multi-crystalline silicon
|
|
405
|
-
Manufacturer 2 Model C from [3]_. The spectral response (SR) of CIGS
|
|
406
|
-
and a-Si modules used to derive coefficients can be found in [4]_
|
|
407
|
-
|
|
408
|
-
coefficients : None or array-like, default None
|
|
409
|
-
Allows for entry of user-defined spectral correction
|
|
410
|
-
coefficients. Coefficients must be of length 6. Derivation of
|
|
411
|
-
coefficients requires use of SMARTS and PV module quantum
|
|
412
|
-
efficiency curve. Useful for modeling PV module types which are
|
|
413
|
-
not included as defaults, or to fine tune the spectral
|
|
414
|
-
correction to a particular PV module. Note that the parameters for
|
|
415
|
-
modules with very similar quantum efficiency should be similar,
|
|
416
|
-
in most cases limiting the need for module specific coefficients.
|
|
417
|
-
|
|
418
|
-
Returns
|
|
419
|
-
-------
|
|
420
|
-
modifier: array-like
|
|
421
|
-
spectral mismatch factor (unitless) which is can be multiplied
|
|
422
|
-
with broadband irradiance reaching a module's cells to estimate
|
|
423
|
-
effective irradiance, i.e., the irradiance that is converted to
|
|
424
|
-
electrical current.
|
|
425
|
-
|
|
426
|
-
References
|
|
427
|
-
----------
|
|
428
|
-
.. [1] Gueymard, Christian. SMARTS2: a simple model of the atmospheric
|
|
429
|
-
radiative transfer of sunshine: algorithms and performance
|
|
430
|
-
assessment. Cocoa, FL: Florida Solar Energy Center, 1995.
|
|
431
|
-
.. [2] Lee, Mitchell, and Panchula, Alex. "Spectral Correction for
|
|
432
|
-
Photovoltaic Module Performance Based on Air Mass and Precipitable
|
|
433
|
-
Water." IEEE Photovoltaic Specialists Conference, Portland, 2016
|
|
434
|
-
.. [3] Marion, William F., et al. User's Manual for Data for Validating
|
|
435
|
-
Models for PV Module Performance. National Renewable Energy
|
|
436
|
-
Laboratory, 2014. http://www.nrel.gov/docs/fy14osti/61610.pdf
|
|
437
|
-
.. [4] Schweiger, M. and Hermann, W, Influence of Spectral Effects
|
|
438
|
-
on Energy Yield of Different PV Modules: Comparison of Pwat and
|
|
439
|
-
MMF Approach, TUV Rheinland Energy GmbH report 21237296.003,
|
|
440
|
-
January 2017
|
|
441
|
-
"""
|
|
442
|
-
|
|
443
|
-
# --- Screen Input Data ---
|
|
444
|
-
|
|
445
|
-
# *** Pw ***
|
|
446
|
-
# Replace Pw Values below 0.1 cm with 0.1 cm to prevent model from
|
|
447
|
-
# diverging"
|
|
448
|
-
pw = np.atleast_1d(pw)
|
|
449
|
-
pw = pw.astype('float64')
|
|
450
|
-
if np.min(pw) < min_pw:
|
|
451
|
-
pw = np.maximum(pw, min_pw)
|
|
452
|
-
warn(f'Exceptionally low pw values replaced with {min_pw} cm to '
|
|
453
|
-
'prevent model divergence')
|
|
454
|
-
|
|
455
|
-
# Warn user about Pw data that is exceptionally high
|
|
456
|
-
if np.max(pw) > max_pw:
|
|
457
|
-
pw[pw > max_pw] = np.nan
|
|
458
|
-
warn('Exceptionally high pw values replaced by np.nan: '
|
|
459
|
-
'check input data.')
|
|
460
|
-
|
|
461
|
-
# *** AMa ***
|
|
462
|
-
# Replace Extremely High AM with AM 10 to prevent model divergence
|
|
463
|
-
# AM > 10 will only occur very close to sunset
|
|
464
|
-
if np.max(airmass_absolute) > 10:
|
|
465
|
-
airmass_absolute = np.minimum(airmass_absolute, 10)
|
|
466
|
-
|
|
467
|
-
# Warn user about AMa data that is exceptionally low
|
|
468
|
-
if np.min(airmass_absolute) < 0.58:
|
|
469
|
-
warn('Exceptionally low air mass: ' +
|
|
470
|
-
'model not intended for extra-terrestrial use')
|
|
471
|
-
# pvl_absoluteairmass(1,pvl_alt2pres(4340)) = 0.58 Elevation of
|
|
472
|
-
# Mina Pirquita, Argentian = 4340 m. Highest elevation city with
|
|
473
|
-
# population over 50,000.
|
|
474
|
-
|
|
475
|
-
_coefficients = {}
|
|
476
|
-
_coefficients['cdte'] = (
|
|
477
|
-
0.86273, -0.038948, -0.012506, 0.098871, 0.084658, -0.0042948)
|
|
478
|
-
_coefficients['monosi'] = (
|
|
479
|
-
0.85914, -0.020880, -0.0058853, 0.12029, 0.026814, -0.0017810)
|
|
480
|
-
_coefficients['xsi'] = _coefficients['monosi']
|
|
481
|
-
_coefficients['polysi'] = (
|
|
482
|
-
0.84090, -0.027539, -0.0079224, 0.13570, 0.038024, -0.0021218)
|
|
483
|
-
_coefficients['multisi'] = _coefficients['polysi']
|
|
484
|
-
_coefficients['cigs'] = (
|
|
485
|
-
0.85252, -0.022314, -0.0047216, 0.13666, 0.013342, -0.0008945)
|
|
486
|
-
_coefficients['asi'] = (
|
|
487
|
-
1.12094, -0.047620, -0.0083627, -0.10443, 0.098382, -0.0033818)
|
|
488
|
-
|
|
489
|
-
if module_type is not None and coefficients is None:
|
|
490
|
-
coefficients = _coefficients[module_type.lower()]
|
|
491
|
-
elif module_type is None and coefficients is not None:
|
|
492
|
-
pass
|
|
493
|
-
elif module_type is None and coefficients is None:
|
|
494
|
-
raise TypeError('No valid input provided, both module_type and ' +
|
|
495
|
-
'coefficients are None')
|
|
496
|
-
else:
|
|
497
|
-
raise TypeError('Cannot resolve input, must supply only one of ' +
|
|
498
|
-
'module_type and coefficients')
|
|
499
|
-
|
|
500
|
-
# Evaluate Spectral Shift
|
|
501
|
-
coeff = coefficients
|
|
502
|
-
ama = airmass_absolute
|
|
503
|
-
modifier = (
|
|
504
|
-
coeff[0] + coeff[1]*ama + coeff[2]*pw + coeff[3]*np.sqrt(ama) +
|
|
505
|
-
coeff[4]*np.sqrt(pw) + coeff[5]*ama/np.sqrt(pw))
|
|
506
|
-
|
|
507
|
-
return modifier
|
|
339
|
+
first_solar_spectral_correction = deprecated(
|
|
340
|
+
since='0.10.0',
|
|
341
|
+
alternative='pvlib.spectrum.spectral_factor_firstsolar'
|
|
342
|
+
)(pvlib.spectrum.spectral_factor_firstsolar)
|
|
508
343
|
|
|
509
344
|
|
|
510
345
|
def bird_hulstrom80_aod_bb(aod380, aod500):
|
pvlib/bifacial/infinite_sheds.py
CHANGED
|
@@ -6,64 +6,8 @@ import numpy as np
|
|
|
6
6
|
import pandas as pd
|
|
7
7
|
from pvlib.tools import cosd, sind, tand
|
|
8
8
|
from pvlib.bifacial import utils
|
|
9
|
-
from pvlib.shading import masking_angle
|
|
10
9
|
from pvlib.irradiance import beam_component, aoi, haydavies
|
|
11
10
|
|
|
12
|
-
def _vf_ground_sky_integ(surface_tilt, surface_azimuth, gcr, height,
|
|
13
|
-
pitch, max_rows=10, npoints=100, vectorize=False):
|
|
14
|
-
"""
|
|
15
|
-
Integrated view factor to the sky from the ground underneath
|
|
16
|
-
interior rows of the array.
|
|
17
|
-
|
|
18
|
-
Parameters
|
|
19
|
-
----------
|
|
20
|
-
surface_tilt : numeric
|
|
21
|
-
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
22
|
-
= 0, surface facing horizon = 90. [degree]
|
|
23
|
-
surface_azimuth : numeric
|
|
24
|
-
Surface azimuth angles in decimal degrees east of north
|
|
25
|
-
(e.g. North = 0, South = 180, East = 90, West = 270).
|
|
26
|
-
``surface_azimuth`` must be >=0 and <=360.
|
|
27
|
-
gcr : float
|
|
28
|
-
Ratio of row slant length to row spacing (pitch). [unitless]
|
|
29
|
-
height : float
|
|
30
|
-
Height of the center point of the row above the ground; must be in the
|
|
31
|
-
same units as ``pitch``.
|
|
32
|
-
pitch : float
|
|
33
|
-
Distance between two rows. Must be in the same units as ``height``.
|
|
34
|
-
max_rows : int, default 10
|
|
35
|
-
Maximum number of rows to consider in front and behind the current row.
|
|
36
|
-
npoints : int, default 100
|
|
37
|
-
Number of points used to discretize distance along the ground.
|
|
38
|
-
vectorize : bool, default False
|
|
39
|
-
If True, vectorize the view factor calculation across ``surface_tilt``.
|
|
40
|
-
This increases speed with the cost of increased memory usage.
|
|
41
|
-
|
|
42
|
-
Returns
|
|
43
|
-
-------
|
|
44
|
-
fgnd_sky : numeric
|
|
45
|
-
Integration of view factor over the length between adjacent, interior
|
|
46
|
-
rows. Shape matches that of ``surface_tilt``. [unitless]
|
|
47
|
-
"""
|
|
48
|
-
# Abuse utils._vf_ground_sky_2d by supplying surface_tilt in place
|
|
49
|
-
# of a signed rotation. This is OK because
|
|
50
|
-
# 1) z span the full distance between 2 rows, and
|
|
51
|
-
# 2) max_rows is set to be large upstream, and
|
|
52
|
-
# 3) _vf_ground_sky_2d considers [-max_rows, +max_rows]
|
|
53
|
-
# The VFs to the sky will thus be symmetric around z=0.5
|
|
54
|
-
z = np.linspace(0, 1, npoints)
|
|
55
|
-
rotation = np.atleast_1d(surface_tilt)
|
|
56
|
-
if vectorize:
|
|
57
|
-
fz_sky = utils._vf_ground_sky_2d(z, rotation, gcr, pitch, height,
|
|
58
|
-
max_rows)
|
|
59
|
-
else:
|
|
60
|
-
fz_sky = np.zeros((npoints, len(rotation)))
|
|
61
|
-
for k, r in enumerate(rotation):
|
|
62
|
-
vf = utils._vf_ground_sky_2d(z, r, gcr, pitch, height, max_rows)
|
|
63
|
-
fz_sky[:, k] = vf[:, 0] # remove spurious rotation dimension
|
|
64
|
-
# calculate the integrated view factor for all of the ground between rows
|
|
65
|
-
return np.trapz(fz_sky, z, axis=0)
|
|
66
|
-
|
|
67
11
|
|
|
68
12
|
def _poa_ground_shadows(poa_ground, f_gnd_beam, df, vf_gnd_sky):
|
|
69
13
|
"""
|
|
@@ -94,15 +38,16 @@ def _poa_ground_shadows(poa_ground, f_gnd_beam, df, vf_gnd_sky):
|
|
|
94
38
|
return poa_ground * (f_gnd_beam*(1 - df) + df*vf_gnd_sky)
|
|
95
39
|
|
|
96
40
|
|
|
97
|
-
def
|
|
98
|
-
"""
|
|
41
|
+
def _poa_sky_diffuse_pv(dhi, gcr, surface_tilt):
|
|
42
|
+
r"""
|
|
99
43
|
Integrated view factors from the shaded and unshaded parts of
|
|
100
44
|
the row slant height to the sky.
|
|
101
45
|
|
|
102
46
|
Parameters
|
|
103
47
|
----------
|
|
104
48
|
f_x : numeric
|
|
105
|
-
Fraction of row slant height from the bottom that is shaded
|
|
49
|
+
Fraction of row slant height from the bottom that is shaded from
|
|
50
|
+
direct irradiance. [unitless]
|
|
106
51
|
surface_tilt : numeric
|
|
107
52
|
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
108
53
|
= 0, surface facing horizon = 90. [degree]
|
|
@@ -111,231 +56,67 @@ def _vf_row_sky_integ(f_x, surface_tilt, gcr, npoints=100):
|
|
|
111
56
|
npoints : int, default 100
|
|
112
57
|
Number of points for integration. [unitless]
|
|
113
58
|
|
|
114
|
-
|
|
115
|
-
-------
|
|
116
|
-
vf_shade_sky_integ : numeric
|
|
117
|
-
Integrated view factor from the shaded part of the row to the sky.
|
|
118
|
-
[unitless]
|
|
119
|
-
vf_noshade_sky_integ : numeric
|
|
120
|
-
Integrated view factor from the unshaded part of the row to the sky.
|
|
121
|
-
[unitless]
|
|
59
|
+
A detailed calculation would be
|
|
122
60
|
|
|
123
|
-
|
|
124
|
-
-----
|
|
125
|
-
The view factor to the sky at a point x along the row slant height is
|
|
126
|
-
given by
|
|
61
|
+
dhi * (f_x * vf_shade_sky_integ + (1 - f_x) * vf_noshade_sky_integ)
|
|
127
62
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
\\cos \\left(\\beta\\right) \\right)
|
|
63
|
+
where vf_shade_sky_integ is the average view factor between 0 and f_x
|
|
64
|
+
(the shaded portion). But the average view factor is
|
|
131
65
|
|
|
132
|
-
|
|
133
|
-
x to the top of the facing row, and :math:`\\beta` is the surface tilt.
|
|
66
|
+
1/(f_x - 0) Integral_0^f_x vf(x) dx
|
|
134
67
|
|
|
135
|
-
|
|
136
|
-
of the row slant height.
|
|
68
|
+
so the detailed calculation is equivalent to
|
|
137
69
|
|
|
138
|
-
|
|
139
|
-
# handle Series inputs
|
|
140
|
-
surface_tilt = np.array(surface_tilt)
|
|
141
|
-
cst = cosd(surface_tilt)
|
|
142
|
-
# shaded portion
|
|
143
|
-
x = np.linspace(0, f_x, num=npoints)
|
|
144
|
-
psi_t_shaded = masking_angle(surface_tilt, gcr, x)
|
|
145
|
-
y = 0.5 * (cosd(psi_t_shaded) + cst)
|
|
146
|
-
# integrate view factors from each point in the discretization. This is an
|
|
147
|
-
# improvement over the algorithm described in [2]
|
|
148
|
-
vf_shade_sky_integ = np.trapz(y, x, axis=0)
|
|
149
|
-
# unshaded portion
|
|
150
|
-
x = np.linspace(f_x, 1., num=npoints)
|
|
151
|
-
psi_t_unshaded = masking_angle(surface_tilt, gcr, x)
|
|
152
|
-
y = 0.5 * (cosd(psi_t_unshaded) + cst)
|
|
153
|
-
vf_noshade_sky_integ = np.trapz(y, x, axis=0)
|
|
154
|
-
return vf_shade_sky_integ, vf_noshade_sky_integ
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
def _poa_sky_diffuse_pv(f_x, dhi, vf_shade_sky_integ, vf_noshade_sky_integ):
|
|
158
|
-
"""
|
|
159
|
-
Sky diffuse POA from integrated view factors combined for both shaded and
|
|
160
|
-
unshaded parts of the surface.
|
|
70
|
+
dhi * 1/(1 - 0) Integral_0^1 vf(x) dx
|
|
161
71
|
|
|
162
72
|
Parameters
|
|
163
73
|
----------
|
|
164
74
|
f_x : numeric
|
|
165
|
-
Fraction of row slant height from the bottom that is shaded
|
|
75
|
+
Fraction of row slant height from the bottom that is shaded from
|
|
76
|
+
direct irradiance. [unitless]
|
|
166
77
|
dhi : numeric
|
|
167
78
|
Diffuse horizontal irradiance (DHI). [W/m^2]
|
|
168
|
-
vf_shade_sky_integ : numeric
|
|
169
|
-
Integrated view factor from the shaded part of the row to the sky.
|
|
170
|
-
[unitless]
|
|
171
|
-
vf_noshade_sky_integ : numeric
|
|
172
|
-
Integrated view factor from the unshaded part of the row to the sky.
|
|
173
|
-
[unitless]
|
|
174
|
-
|
|
175
|
-
Returns
|
|
176
|
-
-------
|
|
177
|
-
poa_sky_diffuse_pv : numeric
|
|
178
|
-
Total sky diffuse irradiance incident on the PV surface. [W/m^2]
|
|
179
|
-
"""
|
|
180
|
-
return dhi * (f_x * vf_shade_sky_integ + (1 - f_x) * vf_noshade_sky_integ)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def _ground_angle(x, surface_tilt, gcr):
|
|
184
|
-
"""
|
|
185
|
-
Angle from horizontal of the line from a point x on the row slant length
|
|
186
|
-
to the bottom of the facing row.
|
|
187
|
-
|
|
188
|
-
The angles are clockwise from horizontal, rather than the usual
|
|
189
|
-
counterclockwise direction.
|
|
190
|
-
|
|
191
|
-
Parameters
|
|
192
|
-
----------
|
|
193
|
-
x : numeric
|
|
194
|
-
fraction of row slant length from bottom, ``x = 0`` is at the row
|
|
195
|
-
bottom, ``x = 1`` is at the top of the row.
|
|
196
|
-
surface_tilt : numeric
|
|
197
|
-
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
198
|
-
= 0, surface facing horizon = 90. [degree]
|
|
199
79
|
gcr : float
|
|
200
80
|
ground coverage ratio, ratio of row slant length to row spacing.
|
|
201
81
|
[unitless]
|
|
202
|
-
|
|
203
|
-
Returns
|
|
204
|
-
-------
|
|
205
|
-
psi : numeric
|
|
206
|
-
Angle [degree].
|
|
207
|
-
"""
|
|
208
|
-
# : \\ \
|
|
209
|
-
# : \\ \
|
|
210
|
-
# : \\ \
|
|
211
|
-
# : \\ \ facing row
|
|
212
|
-
# : \\.___________\
|
|
213
|
-
# : \ ^*-. psi \
|
|
214
|
-
# : \ x *-. \
|
|
215
|
-
# : \ v *-.\
|
|
216
|
-
# : \<-----P---->\
|
|
217
|
-
|
|
218
|
-
x1 = gcr * x * sind(surface_tilt)
|
|
219
|
-
x2 = gcr * x * cosd(surface_tilt) + 1
|
|
220
|
-
psi = np.arctan2(x1, x2) # do this first because it handles 0 / 0
|
|
221
|
-
return np.rad2deg(psi)
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def _vf_row_ground(x, surface_tilt, gcr):
|
|
225
|
-
"""
|
|
226
|
-
View factor from a point x on the row to the ground.
|
|
227
|
-
|
|
228
|
-
Parameters
|
|
229
|
-
----------
|
|
230
|
-
x : numeric
|
|
231
|
-
Fraction of row slant height from the bottom. [unitless]
|
|
232
82
|
surface_tilt : numeric
|
|
233
83
|
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
234
84
|
= 0, surface facing horizon = 90. [degree]
|
|
235
|
-
gcr : float
|
|
236
|
-
Ground coverage ratio, ratio of row slant length to row spacing.
|
|
237
|
-
[unitless]
|
|
238
85
|
|
|
239
86
|
Returns
|
|
240
87
|
-------
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
"""
|
|
245
|
-
cst = cosd(surface_tilt)
|
|
246
|
-
# angle from horizontal at the point x on the row slant height to the
|
|
247
|
-
# bottom of the facing row
|
|
248
|
-
psi_t_shaded = _ground_angle(x, surface_tilt, gcr)
|
|
249
|
-
# view factor from the point on the row to the ground
|
|
250
|
-
return 0.5 * (cosd(psi_t_shaded) - cst)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def _vf_row_ground_integ(f_x, surface_tilt, gcr, npoints=100):
|
|
88
|
+
poa_sky_diffuse_pv : numeric
|
|
89
|
+
Total sky diffuse irradiance incident on the PV surface. [W/m^2]
|
|
254
90
|
"""
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
Parameters
|
|
258
|
-
----------
|
|
259
|
-
f_x : numeric
|
|
260
|
-
Fraction of row slant height from the bottom that is shaded. [unitless]
|
|
261
|
-
surface_tilt : numeric
|
|
262
|
-
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
263
|
-
= 0, surface facing horizon = 90. [degree]
|
|
264
|
-
gcr : float
|
|
265
|
-
Ground coverage ratio, ratio of row slant length to row spacing.
|
|
266
|
-
[unitless]
|
|
267
|
-
npoints : int, default 100
|
|
268
|
-
Number of points for integration. [unitless]
|
|
91
|
+
vf_integ = utils.vf_row_sky_2d_integ(surface_tilt, gcr, 0., 1.)
|
|
92
|
+
return dhi * vf_integ
|
|
269
93
|
|
|
270
|
-
Returns
|
|
271
|
-
-------
|
|
272
|
-
vf_shade_ground_integ : numeric
|
|
273
|
-
View factor from the shaded portion of the row to the ground.
|
|
274
|
-
[unitless]
|
|
275
|
-
vf_noshade_ground_integ : numeric
|
|
276
|
-
View factor from the unshaded portion of the row to the ground.
|
|
277
|
-
[unitless]
|
|
278
94
|
|
|
279
|
-
|
|
280
|
-
-----
|
|
281
|
-
The view factor to the ground at a point x along the row slant height is
|
|
282
|
-
given by
|
|
283
|
-
|
|
284
|
-
.. math ::
|
|
285
|
-
\\large{f_{gr} = \frac{1}{2} \\left(\\cos\\left(\\psi_t\\right) -
|
|
286
|
-
\\cos \\left(\\beta\\right) \\right)
|
|
287
|
-
|
|
288
|
-
where :math:`\\psi_t` is the angle from horizontal of the line from point
|
|
289
|
-
x to the bottom of the facing row, and :math:`\\beta` is the surface tilt.
|
|
290
|
-
|
|
291
|
-
Each view factor is integrated over the relevant portion of the row
|
|
292
|
-
slant height.
|
|
293
|
-
"""
|
|
294
|
-
# handle Series inputs
|
|
295
|
-
surface_tilt = np.array(surface_tilt)
|
|
296
|
-
# shaded portion of row slant height
|
|
297
|
-
x = np.linspace(0, f_x, num=npoints)
|
|
298
|
-
# view factor from the point on the row to the ground
|
|
299
|
-
y = _vf_row_ground(x, surface_tilt, gcr)
|
|
300
|
-
# integrate view factors along the shaded portion of the row slant height.
|
|
301
|
-
# This is an improvement over the algorithm described in [2]
|
|
302
|
-
vf_shade_ground_integ = np.trapz(y, x, axis=0)
|
|
303
|
-
|
|
304
|
-
# unshaded portion of row slant height
|
|
305
|
-
x = np.linspace(f_x, 1., num=npoints)
|
|
306
|
-
# view factor from the point on the row to the ground
|
|
307
|
-
y = _vf_row_ground(x, surface_tilt, gcr)
|
|
308
|
-
# integrate view factors along the unshaded portion.
|
|
309
|
-
# This is an improvement over the algorithm described in [2]
|
|
310
|
-
vf_noshade_ground_integ = np.trapz(y, x, axis=0)
|
|
311
|
-
|
|
312
|
-
return vf_shade_ground_integ, vf_noshade_ground_integ
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
def _poa_ground_pv(f_x, poa_ground, f_gnd_pv_shade, f_gnd_pv_noshade):
|
|
95
|
+
def _poa_ground_pv(poa_ground, gcr, surface_tilt):
|
|
316
96
|
"""
|
|
317
97
|
Reduce ground-reflected irradiance to account for limited view of the
|
|
318
98
|
ground from the row surface.
|
|
319
99
|
|
|
320
100
|
Parameters
|
|
321
101
|
----------
|
|
322
|
-
f_x : numeric
|
|
323
|
-
Fraction of row slant height from the bottom that is shaded. [unitless]
|
|
324
102
|
poa_ground : numeric
|
|
325
103
|
Ground-reflected irradiance that would reach the row surface if the
|
|
326
104
|
full ground was visible. poa_gnd_sky accounts for limited view of the
|
|
327
105
|
sky from the ground. [W/m^2]
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
106
|
+
gcr : float
|
|
107
|
+
ground coverage ratio, ratio of row slant length to row spacing.
|
|
108
|
+
[unitless]
|
|
109
|
+
surface_tilt : numeric
|
|
110
|
+
Surface tilt angle in degrees from horizontal, e.g., surface facing up
|
|
111
|
+
= 0, surface facing horizon = 90. [degree]
|
|
332
112
|
|
|
333
113
|
Returns
|
|
334
114
|
-------
|
|
335
115
|
numeric
|
|
336
116
|
Ground diffuse irradiance on the row plane. [W/m^2]
|
|
337
117
|
"""
|
|
338
|
-
|
|
118
|
+
vf_integ = utils.vf_row_ground_2d_integ(surface_tilt, gcr, 0., 1.)
|
|
119
|
+
return poa_ground * vf_integ
|
|
339
120
|
|
|
340
121
|
|
|
341
122
|
def _shaded_fraction(solar_zenith, solar_azimuth, surface_tilt,
|
|
@@ -541,32 +322,15 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
|
|
|
541
322
|
# adjacent rows interior to the array
|
|
542
323
|
# method differs from [1], Eq. 7 and Eq. 8; height is defined at row
|
|
543
324
|
# center rather than at row lower edge as in [1].
|
|
544
|
-
vf_gnd_sky =
|
|
545
|
-
surface_tilt,
|
|
325
|
+
vf_gnd_sky = utils.vf_ground_sky_2d_integ(
|
|
326
|
+
surface_tilt, gcr, height, pitch, max_rows, npoints,
|
|
546
327
|
vectorize)
|
|
547
328
|
# fraction of row slant height that is shaded from direct irradiance
|
|
548
329
|
f_x = _shaded_fraction(solar_zenith, solar_azimuth, surface_tilt,
|
|
549
330
|
surface_azimuth, gcr)
|
|
550
331
|
|
|
551
|
-
# Integrated view factors to the sky from the shaded and unshaded parts of
|
|
552
|
-
# the row slant height
|
|
553
|
-
# Differs from [1] Eq. 15 and Eq. 16. Here, we integrate over each
|
|
554
|
-
# interval (shaded or unshaded) rather than averaging values at each
|
|
555
|
-
# interval's end points.
|
|
556
|
-
vf_shade_sky, vf_noshade_sky = _vf_row_sky_integ(
|
|
557
|
-
f_x, surface_tilt, gcr, npoints)
|
|
558
|
-
|
|
559
|
-
# view factors from the ground to shaded and unshaded portions of the row
|
|
560
|
-
# slant height
|
|
561
|
-
# Differs from [1] Eq. 17 and Eq. 18. Here, we integrate over each
|
|
562
|
-
# interval (shaded or unshaded) rather than averaging values at each
|
|
563
|
-
# interval's end points.
|
|
564
|
-
f_gnd_pv_shade, f_gnd_pv_noshade = _vf_row_ground_integ(
|
|
565
|
-
f_x, surface_tilt, gcr, npoints)
|
|
566
|
-
|
|
567
332
|
# Total sky diffuse received by both shaded and unshaded portions
|
|
568
|
-
poa_sky_pv = _poa_sky_diffuse_pv(
|
|
569
|
-
f_x, dhi, vf_shade_sky, vf_noshade_sky)
|
|
333
|
+
poa_sky_pv = _poa_sky_diffuse_pv(dhi, gcr, surface_tilt)
|
|
570
334
|
|
|
571
335
|
# irradiance reflected from the ground before accounting for shadows
|
|
572
336
|
# and restricted views
|
|
@@ -591,8 +355,7 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
|
|
|
591
355
|
# the usual ground-reflected irradiance includes the single row to ground
|
|
592
356
|
# view factor (1 - cos(tilt))/2, and Eq. 10, 11 and later multiply
|
|
593
357
|
# this quantity by a ratio of view factors.
|
|
594
|
-
poa_gnd_pv = _poa_ground_pv(
|
|
595
|
-
f_x, ground_diffuse, f_gnd_pv_shade, f_gnd_pv_noshade)
|
|
358
|
+
poa_gnd_pv = _poa_ground_pv(ground_diffuse, gcr, surface_tilt)
|
|
596
359
|
|
|
597
360
|
# add sky and ground-reflected irradiance on the row by irradiance
|
|
598
361
|
# component
|