pvlib 0.11.0a1__py3-none-any.whl → 0.11.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pvlib/atmosphere.py +157 -1
- pvlib/bifacial/__init__.py +4 -4
- pvlib/bifacial/loss_models.py +163 -0
- pvlib/clearsky.py +18 -29
- pvlib/data/pvgis_tmy_meta.json +32 -93
- pvlib/data/pvgis_tmy_test.dat +8761 -8761
- pvlib/data/tmy_45.000_8.000_2005_2020.csv +8789 -0
- pvlib/data/tmy_45.000_8.000_2005_2020.epw +8768 -0
- pvlib/data/tmy_45.000_8.000_2005_2020.json +1 -0
- pvlib/data/tmy_45.000_8.000_2005_2020.txt +8761 -0
- pvlib/data/tmy_45.000_8.000_userhorizon.json +1 -1
- pvlib/data/variables_style_rules.csv +2 -1
- pvlib/iotools/pvgis.py +39 -3
- pvlib/irradiance.py +141 -120
- pvlib/location.py +5 -5
- pvlib/modelchain.py +1 -1
- pvlib/pvsystem.py +2 -2
- pvlib/shading.py +8 -8
- pvlib/singlediode.py +1 -1
- pvlib/solarposition.py +55 -50
- pvlib/spa.py +24 -22
- pvlib/spectrum/__init__.py +9 -4
- pvlib/spectrum/irradiance.py +272 -0
- pvlib/spectrum/mismatch.py +118 -508
- pvlib/spectrum/response.py +280 -0
- pvlib/spectrum/spectrl2.py +16 -16
- pvlib/tests/bifacial/test_losses_models.py +54 -0
- pvlib/tests/iotools/test_pvgis.py +57 -11
- pvlib/tests/spectrum/__init__.py +0 -0
- pvlib/tests/spectrum/conftest.py +40 -0
- pvlib/tests/spectrum/test_irradiance.py +138 -0
- pvlib/tests/{test_spectrum.py → spectrum/test_mismatch.py} +32 -306
- pvlib/tests/spectrum/test_response.py +124 -0
- pvlib/tests/spectrum/test_spectrl2.py +72 -0
- pvlib/tests/test_atmosphere.py +71 -0
- pvlib/tests/test_clearsky.py +37 -25
- pvlib/tests/test_irradiance.py +6 -6
- pvlib/tests/test_solarposition.py +84 -36
- pvlib/tests/test_spa.py +1 -1
- pvlib/tools.py +26 -2
- pvlib/tracking.py +53 -47
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/METADATA +31 -29
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/RECORD +47 -38
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/WHEEL +1 -1
- pvlib/data/tmy_45.000_8.000_2005_2016.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2016.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2016.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2016.txt +0 -8761
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/AUTHORS.md +0 -0
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/LICENSE +0 -0
- {pvlib-0.11.0a1.dist-info → pvlib-0.11.1.dist-info}/top_level.txt +0 -0
pvlib/pvsystem.py
CHANGED
|
@@ -841,7 +841,7 @@ class PVSystem:
|
|
|
841
841
|
@_unwrap_single_value
|
|
842
842
|
def pvwatts_dc(self, g_poa_effective, temp_cell):
|
|
843
843
|
"""
|
|
844
|
-
|
|
844
|
+
Calculates DC power according to the PVWatts model using
|
|
845
845
|
:py:func:`pvlib.pvsystem.pvwatts_dc`, `self.module_parameters['pdc0']`,
|
|
846
846
|
and `self.module_parameters['gamma_pdc']`.
|
|
847
847
|
|
|
@@ -1550,7 +1550,7 @@ def calcparams_desoto(effective_irradiance, temp_cell,
|
|
|
1550
1550
|
Light-generated current in amperes
|
|
1551
1551
|
|
|
1552
1552
|
saturation_current : numeric
|
|
1553
|
-
Diode saturation
|
|
1553
|
+
Diode saturation current in amperes
|
|
1554
1554
|
|
|
1555
1555
|
resistance_series : numeric
|
|
1556
1556
|
Series resistance in ohms
|
pvlib/shading.py
CHANGED
|
@@ -449,11 +449,11 @@ def shaded_fraction1d(
|
|
|
449
449
|
Tilted row with a pitch of 3 m, a collector width of
|
|
450
450
|
2 m, and row rotations of 30°. In the morning.
|
|
451
451
|
|
|
452
|
-
>>> shaded_fraction1d(solar_zenith=80, solar_azimuth=
|
|
452
|
+
>>> shaded_fraction1d(solar_zenith=80, solar_azimuth=135,
|
|
453
453
|
... axis_azimuth=90, shaded_row_rotation=30, shading_row_rotation=30,
|
|
454
454
|
... collector_width=2, pitch=3, axis_tilt=0,
|
|
455
455
|
... surface_to_axis_offset=0.05, cross_axis_slope=0)
|
|
456
|
-
0.
|
|
456
|
+
0.47755694708090535
|
|
457
457
|
|
|
458
458
|
**Fixed-tilt north-facing array on sloped terrain**
|
|
459
459
|
|
|
@@ -463,11 +463,11 @@ def shaded_fraction1d(
|
|
|
463
463
|
10° slope, where their axis is on the most inclined
|
|
464
464
|
direction (zero cross-axis slope). Shaded in the morning.
|
|
465
465
|
|
|
466
|
-
>>> shaded_fraction1d(solar_zenith=
|
|
466
|
+
>>> shaded_fraction1d(solar_zenith=80, solar_azimuth=75.5,
|
|
467
467
|
... axis_azimuth=270, shaded_row_rotation=50, shading_row_rotation=30,
|
|
468
468
|
... collector_width=2.5, pitch=4, axis_tilt=10,
|
|
469
469
|
... surface_to_axis_offset=0.05, cross_axis_slope=0)
|
|
470
|
-
0.
|
|
470
|
+
0.793244836197256
|
|
471
471
|
|
|
472
472
|
**N-S single-axis tracker on sloped terrain**
|
|
473
473
|
|
|
@@ -476,10 +476,10 @@ def shaded_fraction1d(
|
|
|
476
476
|
in the morning. Terrain slope is 7° west-east (east-most
|
|
477
477
|
tracker is higher than the west-most tracker).
|
|
478
478
|
|
|
479
|
-
>>> shaded_fraction1d(solar_zenith=
|
|
479
|
+
>>> shaded_fraction1d(solar_zenith=80, solar_azimuth=90, axis_azimuth=180,
|
|
480
480
|
... shaded_row_rotation=-30, collector_width=1.4, pitch=3, axis_tilt=0,
|
|
481
481
|
... surface_to_axis_offset=0.10, cross_axis_slope=7)
|
|
482
|
-
0.
|
|
482
|
+
0.8242176864434579
|
|
483
483
|
|
|
484
484
|
Note the previous example only is valid for the shaded fraction of the
|
|
485
485
|
west-most tracker in the morning, and assuming it is the
|
|
@@ -491,10 +491,10 @@ def shaded_fraction1d(
|
|
|
491
491
|
tracker, you must input the corresponding ``shaded_row_rotation``
|
|
492
492
|
in the afternoon.
|
|
493
493
|
|
|
494
|
-
>>> shaded_fraction1d(solar_zenith=
|
|
494
|
+
>>> shaded_fraction1d(solar_zenith=80, solar_azimuth=270, axis_azimuth=180,
|
|
495
495
|
... shaded_row_rotation=30, collector_width=1.4, pitch=3, axis_tilt=0,
|
|
496
496
|
... surface_to_axis_offset=0.10, cross_axis_slope=7)
|
|
497
|
-
0.
|
|
497
|
+
0.018002567182254348
|
|
498
498
|
|
|
499
499
|
You must switch the input/output depending on the
|
|
500
500
|
sign of the projected solar zenith angle. See
|
pvlib/singlediode.py
CHANGED
|
@@ -632,7 +632,7 @@ def _shape_of_max_size(*args):
|
|
|
632
632
|
def _prepare_newton_inputs(x0, args, method_kwargs):
|
|
633
633
|
"""
|
|
634
634
|
Make inputs compatible with Scipy's newton by:
|
|
635
|
-
- converting all
|
|
635
|
+
- converting all arguments (`x0` and `args`) into numpy.ndarrays if any
|
|
636
636
|
argument is not a scalar.
|
|
637
637
|
- broadcasting the initial guess `x0` to the shape of the argument with
|
|
638
638
|
the greatest size.
|
pvlib/solarposition.py
CHANGED
|
@@ -22,9 +22,8 @@ import numpy as np
|
|
|
22
22
|
import pandas as pd
|
|
23
23
|
import scipy.optimize as so
|
|
24
24
|
import warnings
|
|
25
|
-
import datetime
|
|
26
25
|
|
|
27
|
-
from pvlib import atmosphere
|
|
26
|
+
from pvlib import atmosphere, tools
|
|
28
27
|
from pvlib.tools import datetime_to_djd, djd_to_datetime
|
|
29
28
|
|
|
30
29
|
|
|
@@ -200,11 +199,7 @@ def spa_c(time, latitude, longitude, pressure=101325, altitude=0,
|
|
|
200
199
|
raise ImportError('Could not import built-in SPA calculator. ' +
|
|
201
200
|
'You may need to recompile the SPA code.')
|
|
202
201
|
|
|
203
|
-
|
|
204
|
-
try:
|
|
205
|
-
time_utc = time.tz_convert('UTC')
|
|
206
|
-
except TypeError:
|
|
207
|
-
time_utc = time
|
|
202
|
+
time_utc = tools._pandas_to_utc(time)
|
|
208
203
|
|
|
209
204
|
spa_out = []
|
|
210
205
|
|
|
@@ -313,13 +308,11 @@ def spa_python(time, latitude, longitude,
|
|
|
313
308
|
avg. yearly air pressure in Pascals.
|
|
314
309
|
temperature : int or float, optional, default 12
|
|
315
310
|
avg. yearly air temperature in degrees C.
|
|
316
|
-
delta_t : float, optional, default 67.0
|
|
311
|
+
delta_t : float or array, optional, default 67.0
|
|
317
312
|
Difference between terrestrial time and UT1.
|
|
318
313
|
If delta_t is None, uses spa.calculate_deltat
|
|
319
314
|
using time.year and time.month from pandas.DatetimeIndex.
|
|
320
315
|
For most simulations the default delta_t is sufficient.
|
|
321
|
-
*Note: delta_t = None will break code using nrel_numba,
|
|
322
|
-
this will be fixed in a future version.*
|
|
323
316
|
The USNO has historical and forecasted delta_t [3]_.
|
|
324
317
|
atmos_refrac : float, optional
|
|
325
318
|
The approximate atmospheric refraction (in degrees)
|
|
@@ -379,7 +372,9 @@ def spa_python(time, latitude, longitude,
|
|
|
379
372
|
|
|
380
373
|
spa = _spa_python_import(how)
|
|
381
374
|
|
|
382
|
-
|
|
375
|
+
if delta_t is None:
|
|
376
|
+
time_utc = tools._pandas_to_utc(time)
|
|
377
|
+
delta_t = spa.calculate_deltat(time_utc.year, time_utc.month)
|
|
383
378
|
|
|
384
379
|
app_zenith, zenith, app_elevation, elevation, azimuth, eot = \
|
|
385
380
|
spa.solar_position(unixtime, lat, lon, elev, pressure, temperature,
|
|
@@ -419,13 +414,11 @@ def sun_rise_set_transit_spa(times, latitude, longitude, how='numpy',
|
|
|
419
414
|
Options are 'numpy' or 'numba'. If numba >= 0.17.0
|
|
420
415
|
is installed, how='numba' will compile the spa functions
|
|
421
416
|
to machine code and run them multithreaded.
|
|
422
|
-
delta_t : float, optional, default 67.0
|
|
417
|
+
delta_t : float or array, optional, default 67.0
|
|
423
418
|
Difference between terrestrial time and UT1.
|
|
424
419
|
If delta_t is None, uses spa.calculate_deltat
|
|
425
420
|
using times.year and times.month from pandas.DatetimeIndex.
|
|
426
421
|
For most simulations the default delta_t is sufficient.
|
|
427
|
-
*Note: delta_t = None will break code using nrel_numba,
|
|
428
|
-
this will be fixed in a future version.*
|
|
429
422
|
numthreads : int, optional, default 4
|
|
430
423
|
Number of threads to use if how == 'numba'.
|
|
431
424
|
|
|
@@ -453,12 +446,13 @@ def sun_rise_set_transit_spa(times, latitude, longitude, how='numpy',
|
|
|
453
446
|
raise ValueError('times must be localized')
|
|
454
447
|
|
|
455
448
|
# must convert to midnight UTC on day of interest
|
|
456
|
-
|
|
457
|
-
unixtime = _datetime_to_unixtime(
|
|
449
|
+
times_utc = times.tz_convert('UTC')
|
|
450
|
+
unixtime = _datetime_to_unixtime(times_utc.normalize())
|
|
458
451
|
|
|
459
452
|
spa = _spa_python_import(how)
|
|
460
453
|
|
|
461
|
-
|
|
454
|
+
if delta_t is None:
|
|
455
|
+
delta_t = spa.calculate_deltat(times_utc.year, times_utc.month)
|
|
462
456
|
|
|
463
457
|
transit, sunrise, sunset = spa.transit_sunrise_sunset(
|
|
464
458
|
unixtime, lat, lon, delta_t, numthreads)
|
|
@@ -582,12 +576,11 @@ def sun_rise_set_transit_ephem(times, latitude, longitude,
|
|
|
582
576
|
sunrise = []
|
|
583
577
|
sunset = []
|
|
584
578
|
trans = []
|
|
585
|
-
for thetime in times:
|
|
586
|
-
thetime = thetime.to_pydatetime()
|
|
579
|
+
for thetime in tools._pandas_to_utc(times):
|
|
587
580
|
# older versions of pyephem ignore timezone when converting to its
|
|
588
581
|
# internal datetime format, so convert to UTC here to support
|
|
589
582
|
# all versions. GH #1449
|
|
590
|
-
obs.date = ephem.Date(thetime
|
|
583
|
+
obs.date = ephem.Date(thetime)
|
|
591
584
|
sunrise.append(_ephem_to_timezone(rising(sun), tzinfo))
|
|
592
585
|
sunset.append(_ephem_to_timezone(setting(sun), tzinfo))
|
|
593
586
|
trans.append(_ephem_to_timezone(transit(sun), tzinfo))
|
|
@@ -645,11 +638,7 @@ def pyephem(time, latitude, longitude, altitude=0, pressure=101325,
|
|
|
645
638
|
except ImportError:
|
|
646
639
|
raise ImportError('PyEphem must be installed')
|
|
647
640
|
|
|
648
|
-
|
|
649
|
-
try:
|
|
650
|
-
time_utc = time.tz_convert('UTC')
|
|
651
|
-
except TypeError:
|
|
652
|
-
time_utc = time
|
|
641
|
+
time_utc = tools._pandas_to_utc(time)
|
|
653
642
|
|
|
654
643
|
sun_coords = pd.DataFrame(index=time)
|
|
655
644
|
|
|
@@ -718,11 +707,11 @@ def ephemeris(time, latitude, longitude, pressure=101325, temperature=12):
|
|
|
718
707
|
|
|
719
708
|
* apparent_elevation : apparent sun elevation accounting for
|
|
720
709
|
atmospheric refraction.
|
|
710
|
+
This is the complement of the apparent zenith angle.
|
|
721
711
|
* elevation : actual elevation (not accounting for refraction)
|
|
722
712
|
of the sun in decimal degrees, 0 = on horizon.
|
|
723
713
|
The complement of the zenith angle.
|
|
724
714
|
* azimuth : Azimuth of the sun in decimal degrees East of North.
|
|
725
|
-
This is the complement of the apparent zenith angle.
|
|
726
715
|
* apparent_zenith : apparent sun zenith accounting for atmospheric
|
|
727
716
|
refraction.
|
|
728
717
|
* zenith : Solar zenith angle
|
|
@@ -766,11 +755,7 @@ def ephemeris(time, latitude, longitude, pressure=101325, temperature=12):
|
|
|
766
755
|
# the SPA algorithm needs time to be expressed in terms of
|
|
767
756
|
# decimal UTC hours of the day of the year.
|
|
768
757
|
|
|
769
|
-
|
|
770
|
-
try:
|
|
771
|
-
time_utc = time.tz_convert('UTC')
|
|
772
|
-
except TypeError:
|
|
773
|
-
time_utc = time
|
|
758
|
+
time_utc = tools._pandas_to_utc(time)
|
|
774
759
|
|
|
775
760
|
# strip out the day of the year and calculate the decimal hour
|
|
776
761
|
DayOfYear = time_utc.dayofyear
|
|
@@ -957,7 +942,10 @@ def pyephem_earthsun_distance(time):
|
|
|
957
942
|
|
|
958
943
|
sun = ephem.Sun()
|
|
959
944
|
earthsun = []
|
|
960
|
-
for thetime in time:
|
|
945
|
+
for thetime in tools._pandas_to_utc(time):
|
|
946
|
+
# older versions of pyephem ignore timezone when converting to its
|
|
947
|
+
# internal datetime format, so convert to UTC here to support
|
|
948
|
+
# all versions. GH #1449
|
|
961
949
|
sun.compute(ephem.Date(thetime))
|
|
962
950
|
earthsun.append(sun.earth_distance)
|
|
963
951
|
|
|
@@ -981,13 +969,11 @@ def nrel_earthsun_distance(time, how='numpy', delta_t=67.0, numthreads=4):
|
|
|
981
969
|
is installed, how='numba' will compile the spa functions
|
|
982
970
|
to machine code and run them multithreaded.
|
|
983
971
|
|
|
984
|
-
delta_t : float, optional, default 67.0
|
|
972
|
+
delta_t : float or array, optional, default 67.0
|
|
985
973
|
Difference between terrestrial time and UT1.
|
|
986
974
|
If delta_t is None, uses spa.calculate_deltat
|
|
987
975
|
using time.year and time.month from pandas.DatetimeIndex.
|
|
988
976
|
For most simulations the default delta_t is sufficient.
|
|
989
|
-
*Note: delta_t = None will break code using nrel_numba,
|
|
990
|
-
this will be fixed in a future version.*
|
|
991
977
|
|
|
992
978
|
numthreads : int, optional, default 4
|
|
993
979
|
Number of threads to use if how == 'numba'.
|
|
@@ -1014,7 +1000,9 @@ def nrel_earthsun_distance(time, how='numpy', delta_t=67.0, numthreads=4):
|
|
|
1014
1000
|
|
|
1015
1001
|
spa = _spa_python_import(how)
|
|
1016
1002
|
|
|
1017
|
-
|
|
1003
|
+
if delta_t is None:
|
|
1004
|
+
time_utc = tools._pandas_to_utc(time)
|
|
1005
|
+
delta_t = spa.calculate_deltat(time_utc.year, time_utc.month)
|
|
1018
1006
|
|
|
1019
1007
|
dist = spa.earthsun_distance(unixtime, delta_t, numthreads)
|
|
1020
1008
|
|
|
@@ -1387,22 +1375,26 @@ def hour_angle(times, longitude, equation_of_time):
|
|
|
1387
1375
|
equation_of_time_spencer71
|
|
1388
1376
|
equation_of_time_pvcdrom
|
|
1389
1377
|
"""
|
|
1378
|
+
|
|
1379
|
+
# times must be localized
|
|
1380
|
+
if not times.tz:
|
|
1381
|
+
raise ValueError('times must be localized')
|
|
1382
|
+
|
|
1390
1383
|
# hours - timezone = (times - normalized_times) - (naive_times - times)
|
|
1391
|
-
if times.tz is None:
|
|
1392
|
-
times = times.tz_localize('utc')
|
|
1393
1384
|
tzs = np.array([ts.utcoffset().total_seconds() for ts in times]) / 3600
|
|
1394
1385
|
|
|
1395
|
-
hrs_minus_tzs = (times
|
|
1386
|
+
hrs_minus_tzs = _times_to_hours_after_local_midnight(times) - tzs
|
|
1396
1387
|
|
|
1397
|
-
|
|
1398
|
-
return np.asarray(
|
|
1399
|
-
15. * (hrs_minus_tzs - 12.) + longitude + equation_of_time / 4.)
|
|
1388
|
+
return 15. * (hrs_minus_tzs - 12.) + longitude + equation_of_time / 4.
|
|
1400
1389
|
|
|
1401
1390
|
|
|
1402
1391
|
def _hour_angle_to_hours(times, hourangle, longitude, equation_of_time):
|
|
1403
1392
|
"""converts hour angles in degrees to hours as a numpy array"""
|
|
1404
|
-
|
|
1405
|
-
|
|
1393
|
+
|
|
1394
|
+
# times must be localized
|
|
1395
|
+
if not times.tz:
|
|
1396
|
+
raise ValueError('times must be localized')
|
|
1397
|
+
|
|
1406
1398
|
tzs = np.array([ts.utcoffset().total_seconds() for ts in times]) / 3600
|
|
1407
1399
|
hours = (hourangle - longitude - equation_of_time / 4.) / 15. + 12. + tzs
|
|
1408
1400
|
return np.asarray(hours)
|
|
@@ -1412,18 +1404,26 @@ def _local_times_from_hours_since_midnight(times, hours):
|
|
|
1412
1404
|
"""
|
|
1413
1405
|
converts hours since midnight from an array of floats to localized times
|
|
1414
1406
|
"""
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1407
|
+
|
|
1408
|
+
# times must be localized
|
|
1409
|
+
if not times.tz:
|
|
1410
|
+
raise ValueError('times must be localized')
|
|
1411
|
+
|
|
1412
|
+
# normalize local times to previous local midnight and add the hours until
|
|
1418
1413
|
# sunrise, sunset, and transit
|
|
1419
|
-
return pd.
|
|
1420
|
-
naive_times.normalize() + pd.to_timedelta(hours, unit='h'), tz=tz_info)
|
|
1414
|
+
return times.normalize() + pd.to_timedelta(hours, unit='h')
|
|
1421
1415
|
|
|
1422
1416
|
|
|
1423
1417
|
def _times_to_hours_after_local_midnight(times):
|
|
1424
1418
|
"""convert local pandas datetime indices to array of hours as floats"""
|
|
1425
|
-
|
|
1419
|
+
|
|
1420
|
+
# times must be localized
|
|
1421
|
+
if not times.tz:
|
|
1422
|
+
raise ValueError('times must be localized')
|
|
1423
|
+
|
|
1426
1424
|
hrs = (times - times.normalize()) / pd.Timedelta('1h')
|
|
1425
|
+
|
|
1426
|
+
# ensure array return instead of a version-dependent pandas <T>Index
|
|
1427
1427
|
return np.array(hrs)
|
|
1428
1428
|
|
|
1429
1429
|
|
|
@@ -1469,6 +1469,11 @@ def sun_rise_set_transit_geometric(times, latitude, longitude, declination,
|
|
|
1469
1469
|
CRC Press (2012)
|
|
1470
1470
|
|
|
1471
1471
|
"""
|
|
1472
|
+
|
|
1473
|
+
# times must be localized
|
|
1474
|
+
if not times.tz:
|
|
1475
|
+
raise ValueError('times must be localized')
|
|
1476
|
+
|
|
1472
1477
|
latitude_rad = np.radians(latitude) # radians
|
|
1473
1478
|
sunset_angle_rad = np.arccos(-np.tan(declination) * np.tan(latitude_rad))
|
|
1474
1479
|
sunset_angle = np.degrees(sunset_angle_rad) # degrees
|
pvlib/spa.py
CHANGED
|
@@ -835,24 +835,24 @@ def equation_of_time(sun_mean_longitude, geocentric_sun_right_ascension,
|
|
|
835
835
|
return E
|
|
836
836
|
|
|
837
837
|
|
|
838
|
-
@jcompile('void(float64[:], float64[:], float64[:,:])',
|
|
839
|
-
nogil=True)
|
|
840
|
-
def solar_position_loop(unixtime, loc_args, out):
|
|
838
|
+
@jcompile('void(float64[:], float64[:], float64[:], float64[:,:])',
|
|
839
|
+
nopython=True, nogil=True)
|
|
840
|
+
def solar_position_loop(unixtime, delta_t, loc_args, out):
|
|
841
841
|
"""Loop through the time array and calculate the solar position"""
|
|
842
842
|
lat = loc_args[0]
|
|
843
843
|
lon = loc_args[1]
|
|
844
844
|
elev = loc_args[2]
|
|
845
845
|
pressure = loc_args[3]
|
|
846
846
|
temp = loc_args[4]
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
esd = loc_args[8]
|
|
847
|
+
atmos_refract = loc_args[5]
|
|
848
|
+
sst = loc_args[6]
|
|
849
|
+
esd = loc_args[7]
|
|
851
850
|
|
|
852
851
|
for i in range(unixtime.shape[0]):
|
|
853
852
|
utime = unixtime[i]
|
|
853
|
+
dT = delta_t[i]
|
|
854
854
|
jd = julian_day(utime)
|
|
855
|
-
jde = julian_ephemeris_day(jd,
|
|
855
|
+
jde = julian_ephemeris_day(jd, dT)
|
|
856
856
|
jc = julian_century(jd)
|
|
857
857
|
jce = julian_ephemeris_century(jde)
|
|
858
858
|
jme = julian_ephemeris_millennium(jce)
|
|
@@ -920,8 +920,11 @@ def solar_position_numba(unixtime, lat, lon, elev, pressure, temp, delta_t,
|
|
|
920
920
|
and multiple threads. Very slow if functions are not numba compiled.
|
|
921
921
|
"""
|
|
922
922
|
# these args are the same for each thread
|
|
923
|
-
loc_args = np.array([lat, lon, elev, pressure, temp,
|
|
924
|
-
atmos_refract, sst, esd])
|
|
923
|
+
loc_args = np.array([lat, lon, elev, pressure, temp,
|
|
924
|
+
atmos_refract, sst, esd], dtype=np.float64)
|
|
925
|
+
|
|
926
|
+
# turn delta_t into an array if it isn't already
|
|
927
|
+
delta_t = np.full_like(unixtime, delta_t, dtype=np.float64)
|
|
925
928
|
|
|
926
929
|
# construct dims x ulength array to put the results in
|
|
927
930
|
ulength = unixtime.shape[0]
|
|
@@ -937,18 +940,20 @@ def solar_position_numba(unixtime, lat, lon, elev, pressure, temp, delta_t,
|
|
|
937
940
|
unixtime = unixtime.astype(np.float64)
|
|
938
941
|
|
|
939
942
|
if ulength < numthreads:
|
|
940
|
-
warnings.warn('The number of threads is more than the length of '
|
|
941
|
-
'the time array. Only using %s threads.'.format(ulength))
|
|
942
943
|
numthreads = ulength
|
|
943
944
|
|
|
944
945
|
if numthreads <= 1:
|
|
945
|
-
solar_position_loop(unixtime, loc_args, result)
|
|
946
|
+
solar_position_loop(unixtime, delta_t, loc_args, result)
|
|
946
947
|
return result
|
|
947
948
|
|
|
948
949
|
# split the input and output arrays into numthreads chunks
|
|
949
950
|
split0 = np.array_split(unixtime, numthreads)
|
|
951
|
+
split1 = np.array_split(delta_t, numthreads)
|
|
950
952
|
split2 = np.array_split(result, numthreads, axis=1)
|
|
951
|
-
chunks = [
|
|
953
|
+
chunks = [
|
|
954
|
+
[a0, a1, loc_args, a2]
|
|
955
|
+
for a0, a1, a2 in zip(split0, split1, split2)
|
|
956
|
+
]
|
|
952
957
|
# Spawn one thread per chunk
|
|
953
958
|
threads = [threading.Thread(target=solar_position_loop, args=chunk)
|
|
954
959
|
for chunk in chunks]
|
|
@@ -1035,7 +1040,7 @@ def solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t,
|
|
|
1035
1040
|
unixtime : numpy array
|
|
1036
1041
|
Array of unix/epoch timestamps to calculate solar position for.
|
|
1037
1042
|
Unixtime is the number of seconds since Jan. 1, 1970 00:00:00 UTC.
|
|
1038
|
-
A pandas.DatetimeIndex is easily converted using .
|
|
1043
|
+
A pandas.DatetimeIndex is easily converted using .view(np.int64)/10**9
|
|
1039
1044
|
lat : float
|
|
1040
1045
|
Latitude to calculate solar position for
|
|
1041
1046
|
lon : float
|
|
@@ -1048,7 +1053,7 @@ def solar_position(unixtime, lat, lon, elev, pressure, temp, delta_t,
|
|
|
1048
1053
|
temp : int or float
|
|
1049
1054
|
avg. yearly temperature at location in
|
|
1050
1055
|
degrees C; used for atmospheric correction
|
|
1051
|
-
delta_t : float
|
|
1056
|
+
delta_t : float or array
|
|
1052
1057
|
Difference between terrestrial time and UT1.
|
|
1053
1058
|
atmos_refrac : float
|
|
1054
1059
|
The approximate atmospheric refraction (in degrees)
|
|
@@ -1113,7 +1118,7 @@ def transit_sunrise_sunset(dates, lat, lon, delta_t, numthreads):
|
|
|
1113
1118
|
Latitude of location to perform calculation for
|
|
1114
1119
|
lon : float
|
|
1115
1120
|
Longitude of location
|
|
1116
|
-
delta_t : float
|
|
1121
|
+
delta_t : float or array
|
|
1117
1122
|
Difference between terrestrial time and UT. USNO has tables.
|
|
1118
1123
|
numthreads : int
|
|
1119
1124
|
Number to threads to use for calculation (if using numba)
|
|
@@ -1214,8 +1219,8 @@ def earthsun_distance(unixtime, delta_t, numthreads):
|
|
|
1214
1219
|
unixtime : numpy array
|
|
1215
1220
|
Array of unix/epoch timestamps to calculate solar position for.
|
|
1216
1221
|
Unixtime is the number of seconds since Jan. 1, 1970 00:00:00 UTC.
|
|
1217
|
-
A pandas.DatetimeIndex is easily converted using .
|
|
1218
|
-
delta_t : float
|
|
1222
|
+
A pandas.DatetimeIndex is easily converted using .view(np.int64)/10**9
|
|
1223
|
+
delta_t : float or array
|
|
1219
1224
|
Difference between terrestrial time and UT. USNO has tables.
|
|
1220
1225
|
numthreads : int
|
|
1221
1226
|
Number to threads to use for calculation (if using numba)
|
|
@@ -1242,9 +1247,6 @@ def calculate_deltat(year, month):
|
|
|
1242
1247
|
"""Calculate the difference between Terrestrial Dynamical Time (TD)
|
|
1243
1248
|
and Universal Time (UT).
|
|
1244
1249
|
|
|
1245
|
-
Note: This function is not yet compatible for calculations using
|
|
1246
|
-
Numba.
|
|
1247
|
-
|
|
1248
1250
|
Equations taken from http://eclipse.gsfc.nasa.gov/SEcat5/deltatpoly.html
|
|
1249
1251
|
"""
|
|
1250
1252
|
|
pvlib/spectrum/__init__.py
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
from pvlib.spectrum.spectrl2 import spectrl2 # noqa: F401
|
|
2
2
|
from pvlib.spectrum.mismatch import ( # noqa: F401
|
|
3
3
|
calc_spectral_mismatch_field,
|
|
4
|
-
get_am15g,
|
|
5
|
-
get_reference_spectra,
|
|
6
|
-
get_example_spectral_response,
|
|
7
4
|
spectral_factor_caballero,
|
|
8
5
|
spectral_factor_firstsolar,
|
|
9
6
|
spectral_factor_sapm,
|
|
10
7
|
spectral_factor_pvspec,
|
|
11
8
|
spectral_factor_jrc,
|
|
9
|
+
)
|
|
10
|
+
from pvlib.spectrum.irradiance import ( # noqa: F401
|
|
11
|
+
get_am15g,
|
|
12
|
+
get_reference_spectra,
|
|
13
|
+
average_photon_energy,
|
|
14
|
+
)
|
|
15
|
+
from pvlib.spectrum.response import ( # noqa: F401
|
|
16
|
+
get_example_spectral_response,
|
|
12
17
|
sr_to_qe,
|
|
13
|
-
qe_to_sr
|
|
18
|
+
qe_to_sr,
|
|
14
19
|
)
|