10000 Refine the repairs and add test · benbenboben/pvlib-python@bcdf626 · GitHub
[go: up one dir, main page]

Skip to content

Commit bcdf626

Browse files
committed
Refine the repairs and add test
1 parent 8ffea2b commit bcdf626

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

pvlib/solarposition.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,17 +1096,27 @@ def solar_azimuth_analytical(latitude, hour_angle, declination, zenith):
10961096
hour_angle
10971097
solar_zenith_analytical
10981098
"""
1099+
1100+
numer = (np.cos(zenith) * np.sin(latitude) - np.sin(declination))
1101+
denom = (np.sin(zenith) * np.cos(latitude))
1102+
1103+
# cases that would generate new NaN values are safely ignored here
1104+
# since they are dealt with further below
10991105
with np.errstate(invalid='ignore', divide='ignore'):
1106+
cos_azi = numer / denom
1107+
1108+
# when zero division occurs, use the limit value of the analytical expression
1109+
cos_azi = np.where(np.isclose(denom, 0.0, rtol=0.0, atol=1e-8), 1.0, cos_azi)
11001110

1101-
cos_azi = ((np.cos(zenith) * np.sin(latitude) - np.sin(declination)) /
1102-
(np.sin(zenith) * np.cos(latitude)))
1111+
# when too many round-ups in floating point math take cos_azi beyond 1.0, use 1.0
1112+
cos_azi = np.where(np.isclose(cos_azi, 1.0, rtol=0.0, atol=1e-8), 1.0, cos_azi)
1113+
cos_azi = np.where(np.isclose(cos_azi, -1.0, rtol=0.0, atol=1e-8), -1.0, cos_azi)
11031114

1104-
cos_azi = np.where(np.isclose(zenith, 0.0), 1.0, cos_azi)
1105-
cos_azi = np.where(np.isclose(latitude, 0.0), 1.0, cos_azi)
1106-
cos_azi = np.where(np.isclose(cos_azi, 1.0), 1.0, cos_azi)
1107-
cos_azi = np.where(np.isclose(cos_azi, -1.0), -1.0, cos_azi)
1115+
# when NaN values occur in input, ignore and pass to output
1116+
with np.errstate(invalid='ignore'):
1117+
sign_ha = np.sign(hour_angle)
11081118

1109-
return (np.sign(hour_angle) * np.arccos(cos_azi) + np.pi)
1119+
return (sign_ha * np.arccos(cos_azi) + np.pi)
11101120

11111121

11121122
def solar_zenith_analytical(latitude, hour_angle, declination):

pvlib/test/test_solarposition.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def test_get_solarposition_deltat(delta_t, method, expected):
341341
this_expected = np.round(this_expected, 5)
342342
ephem_data = np.round(ephem_data, 5)
343343
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
344-
344+
345345

346346
def test_get_solarposition_no_kwargs(expected_solpos):
347347
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
@@ -463,3 +463,27 @@ def test_analytical_azimuth():
463463
atol=0.01)
464464
assert np.allclose(azimuth_2[idx], solar_azimuth.as_matrix()[idx],
465465
atol=0.017)
466+
467+
# test for NaN values at boundary conditions (PR #431)
468+
# use degrees rather than radians for clarity
469+
test_angles = np.radians(np.array(
470+
[[ 0., -180., -20.],
471+
[ 0., 0., -5.],
472+
[ 0., 0., 0.],
473+
[ 0., 0., 15.],
474+
[ 0., 180., 20.],
475+
[ 30., 0., -20.],
476+
[ 30., 0., -5.],
477+
[ 30., 0., 0.],
478+
[ 30., 180., 5.],
479+
[ 30., 0., 10.],
480+
[ -30., 0., -20.],
481+
[ -30., 0., -15.],
482+
[ -30., 0., 0.],
483+
[ -30., -180. 55A7 , 5.],
484+
[ -30., 180., 10.]]))
485+
486+
zeniths = solarposition.solar_zenith_analytical(*test_angles.T)
487+
azimuths = solarposition.solar_azimuth_analytical(*test_angles.T, zeniths)
488+
489+
assert not np.isnan(azimuths).any()

0 commit comments

Comments
 (0)
0