Skip to content

Commit 923dc0e

Browse files
authored
Merge pull request #431 from adriesse/master
Repair solar_azimuth_analytical
2 parents 04bd753 + 7bfd05c commit 923dc0e

File tree

3 files changed

+50
-4
lines changed

3 files changed

+50
-4
lines changed

docs/sphinx/source/whatsnew/v0.5.2.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@ Bug fixes
1717
* physicaliam now returns a Series if called with a Series as an
1818
argument. (:issue:`397`)
1919
* corrected docstring for irradiance.total_irrad (:issue: '423')
20+
* modified solar_azimuth_analytical to handle some borderline cases, thereby
21+
avoiding the NaN values and/or warnings that were previously produced
22+
(:issue: '420')
2023
* removed RuntimeWarnings due to divide by 0 or nans in input data within
2124
irradiance.perez, clearsky.simplified_solis, pvsystem.adrinverter,
2225
pvsystem.ashraeiam, pvsystem.physicaliam, pvsystem.sapm_aoi_loss,
2326
pvsystem.v_from_i. (:issue:`428`)
2427

28+
2529
Documentation
2630
~~~~~~~~~~~~~
2731
* Improve physicaliam doc string. (:issue:`397`)
@@ -37,5 +41,6 @@ Contributors
3741
* Cliff Hansen
3842
* Will Holmgren
3943
* KonstantinTr
44+
* Anton Driesse
4045

4146

pvlib/solarposition.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,9 +1096,27 @@ def solar_azimuth_analytical(latitude, hour_angle, declination, zenith):
10961096
hour_angle
10971097
solar_zenith_analytical
10981098
"""
1099-
return np.sign(hour_angle) * np.abs(np.arccos((np.cos(zenith) * np.sin(
1100-
latitude) - np.sin(declination)) / (np.sin(zenith) * np.cos(
1101-
latitude)))) + np.pi
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
1105+
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)
1110+
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)
1114+
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)
1118+
1119+
return (sign_ha * np.arccos(cos_azi) + np.pi)
11021120

11031121

11041122
def solar_zenith_analytical(latitude, hour_angle, declination):

pvlib/test/test_solarposition.py

Lines changed: 24 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,26 @@ 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+
test_angles = np.radians(np.array(
469+
[[ 0., -180., -20.],
470+
[ 0., 0., -5.],
471+
[ 0., 0., 0.],
472+
[ 0., 0., 15.],
473+
[ 0., 180., 20.],
474+
[ 30., 0., -20.],
475+
[ 30., 0., -5.],
476+
[ 30., 0., 0.],
477+
[ 30., 180., 5.],
478+
[ 30., 0., 10.],
479+
[ -30., 0., -20.],
480+
[ -30., 0., -15.],
481+
[ -30., 0., 0.],
482+
[ -30., -180., 5.],
483+
[ -30., 180., 10.]]))
484+
485+
zeniths = solarposition.solar_zenith_analytical(*test_angles.T)
486+
azimuths = solarposition.solar_azimuth_analytical(*test_angles.T, zenith=zeniths)
487+
488+
assert not np.isnan(azimuths).any()

0 commit comments

Comments
 (0)