@@ -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
11121122def solar_zenith_analytical (latitude , hour_angle , declination ):
0 commit comments