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