libTheSky
Routines to compute sky positions of Sun, Moon, planets and more
All Namespaces Files Functions Variables Pages
sun.f90
Go to the documentation of this file.
1!> \file sun.f90 Procedures that calculate a low-accuracy position of the Sun for libTheSky
2
3
4! Copyright (c) 2002-2025 Marc van der Sluys - Nikhef/Utrecht University - marc.vandersluys.nl
5!
6! This file is part of the libTheSky package,
7! see: https://libthesky.sf.net/
8!
9! This is free software: you can redistribute it and/or modify it under the terms of the
10! European Union Public Licence 1.2 (EUPL 1.2).
11!
12! This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13! without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14! See the EU Public Licence for more details.
15!
16! You should have received a copy of the European Union Public Licence along with this code.
17! If not, see <https://www.eupl.eu/1.2/en/>.
18
19
20!***********************************************************************************************************************************
21!> \brief Low-accuracy procedures for the Sun
22
24 implicit none
25 save
26
27contains
28
29
30 !*********************************************************************************************************************************
31 !> \brief Low-accuracy solar coordinates
32 !!
33 !! \param jd Julian Day of computation
34 !! \param calc Calculate: 1: l,b,r, 2: & ra,dec, 3: & gmst,agst, 4: & az,alt, 5: & mag + p.a., 99: & topo alt + refraction
35 !!
36 !! \param lat Latitude of the observer (rad, optional)
37 !! \param lon Longitude of the observer (rad, optional)
38 !!
39 !!
40 !! \note
41 !! - accuracy: ~0.01°; ~0.0033° when comparing ecliptical coordinates to VSOP87 for 1900-2100 (10^5 random instances)
42 !! - for 1900-2100, the terms greater than Tjc^2 can be neglected without loss of accuracy
43 !!
44 !! \note
45 !! - lat0 and lon0 can be provided through the module TheSky_local (rad, rad), or through the optional arguments.
46 !! Note that using the latter will update the former!
47 !! - results are returned in the array planpos() in the module TheSky_planetdata
48 !!
49 !! \see
50 !! - Chapront-Touze, Chapront, A&A, 190, p.342, 1988, Table 6 (CTC88)
51 !! - Explanatory Supplement to the Astronimical Almanac (3rd Ed, 2012)
52 !! - Meeus, Astronomical Algorithms, 1998, Ch.25
53 !! - Simon et al, A&A, 282, p.663 (1994)
54 !!
55 !! \todo odot is off by ~10" (~0.003d) in Meeus, Example 25a. Would need better L0 or C (or M?)
56
57 subroutine sunpos_la(jd, calc, lat,lon)
58 use sufr_kinds, only: double
59 use sufr_constants, only: jd2000, au, earthr,rsun
60 use sufr_angles, only: rev
61
62 use thesky_planetdata, only: planpos
65 use thesky_local, only: lon0,lat0
66
67 implicit none
68 real(double), intent(in) :: jd
69 integer, intent(in) :: calc
70 real(double), intent(in), optional :: lat,lon
71
72 real(double) :: jde,deltat,tjc,tjc2,tjc3,tjc4, Aorb, l0,m,e,c,odot,nu,omg,a1e2,r, aber, lam,b
73 real(double) :: ra,dec,lm,eps,eps0,deps,gmst,agst,lst,dpsi,az,alt,hh, llat,llon
74
75 ! Handle optional variables:
76 llat = lat0
77 llon = lon0
78 if(present(lat)) llat = lat
79 if(present(lon)) llon = lon
80
81 deltat = calc_deltat(jd)
82 jde = jd + deltat/86400.d0
83 !tjc = (jde-jd2000)/36525.d0 ! Julian Centuries after 2000.0 in dynamical time
84 tjc = (jd-jd2000)/36525.d0 ! Julian Centuries after 2000.0; JD compares better to VSOP87 than JDE (~7% for 1900-2100)
85 tjc2 = tjc*tjc ! T^2 In fact JD - DeltaT compares even better(!) (~4%)
86 tjc3 = tjc2*tjc ! T^3
87 tjc4 = tjc2*tjc2 ! T^4
88
89 aorb = 1.0000010178d0 ! Semi-major axis of the Earth's orbit (Simon et al, 1994)
90
91 ! Sun's mean longitude, Simon et al, 5.9.3:
92 l0 = 4.895063113086d0 + 628.331965406500135d0 *tjc + 5.29213354358d-6 *tjc2 + 3.4940522d-10 *tjc3 - &
93 1.1407666d-10 *tjc4 - 8.726646d-14 *tjc4*tjc + 9.696d-16 * tjc4*tjc2
94
95 ! Sun's mean anomaly, l' in CTC88:
96 m = 6.24006012697d0 + 628.3019551680d0*tjc - 2.680535d-6*tjc2 + 7.12676d-10*tjc3
97
98 ! Eccentricity of the Earth's orbit, Simon et al, 5.9.3:
99 e = 0.0167086342d0 - 4.203654d-5 *tjc - 1.26734d-7 *tjc2 + 1.444d-10*tjc3 - 2.d-14*tjc4 + 3.d-15*tjc4*tjc
100
101 ! Sun's equation of the centre := true - mean anomaly - https://en.wikipedia.org/wiki/Equation_of_the_center:
102 c = (2*e - 0.25d0*e**3)*sin(m) + 1.25d0*e**2*sin(2*m) + 13.d0/12.d0*e**3*sin(3*m) ! Brown, 1896, Chap. III, Eq.7, up to e^3,
103 ! and Expl. Supl. t.t. Astronimical Almanac 3rd Ed, Eq.9.1
104 !c = (2*e - 0.25d0*e**3)*sin(m) + (1.25d0*e**2 - 11.d0/24.d0*e**4)*sin(2*m) + 13.d0/12.d0*e**3*sin(3*m) &
105 ! + 103.d0/96.d0*e**4*sin(4*m) ! Brown, 1896, Chap. III, Eq.7, up to e^4
106
107 odot = l0 + c ! True longitude
108 nu = m + c ! True anomaly
109
110 a1e2 = aorb*(1.d0-e**2) ! a(1-e^2)
111 r = a1e2/(1.d0 + e*cos(nu)) ! Heliocentric distance of the Earth / geocentric dist. of the Sun, Eq. 25.5
112
113 ! Longitude of the Moon's mean ascending node, CTC88:
114 omg = 2.18243919722d0 - 33.7570446083d0 *tjc + 3.623594d-5 *tjc2 + 3.734035d-8 *tjc3 - 2.87931d-10 *tjc4
115
116 ! Mean longitude of the Moon, L in CTC88:
117 lm = 3.810344430588d0 + 8399.709113522267d0*tjc - 2.315615585d-5*tjc2 + 3.23904d-8*tjc3 - 2.67714d-10*tjc4
118 !lm = 3.8103408236d0 + 8399.7091116339958d0*tjc - 2.755176757d-5*tjc2 + 3.239043d-8*tjc3 - 2.6771d-10*tjc4 - Meeus, CHECK 3rd term!
119
120 ! Nutation in longitude, 1980 IAU Theory of Nutation, Seidelmann (1982), Table I, lines 1,9,31,2,10 -> rad:
121 dpsi = (-8.338601d-5-7.1365d-8*tjc)*sin(omg) - 6.39324d-6*sin(2*l0) - 1.1025d-6*sin(2*lm) + 9.9969d-7*sin(2*omg) &
122 + 6.9134d-7*sin(m)
123
124 ! Annual abberation = k * a(1-e^2)/r, Kovalevsky and Seidelmann, Fundamentals of Astrometry (2004):
125 aber = -9.9365085d-5 * a1e2/r
126
127 ! Apparent geocentric longitude and latitude, referred to the true equinox of date:
128 lam = rev(odot + aber + dpsi)
129 b = 0.d0
130
131
132 planpos(1) = lam ! Geocentric longitude
133 planpos(2) = b ! Geocentric latitude
134 planpos(3) = r ! Geocentric distance
135 planpos(4) = r ! Geocentric distance
136
137 ! Secondary variables, (almost) for free:
138 planpos(7) = 5.77551830441d-3 * r ! Light time in days
139 planpos(11) = 0.d0 ! Elongation
140 planpos(12) = 2*rsun/(r*au) ! Apparent diameter
141 planpos(13) = -26.73d0 ! Apparent magnitude
142 planpos(14) = 1.d0 ! Illuminated fraction
143 planpos(15) = 0.d0 ! Phase angle
144 planpos(17) = asin(earthr/(r*au)) ! Horizontal parallax
145
146 planpos(40) = jde ! JD
147 planpos(41:43) = planpos(1:3) ! Geocentric, "true" L,B,R of the Sun
148 planpos(46) = tjc ! App. dyn. time in Julian Centuries since 2000.0
149
150 if(calc.eq.1) return
151
152
153
154 ! Obliquity of the ecliptic and nutation:
155 eps0 = 0.409092804222d0 - 2.26965525d-4*tjc - 2.86d-9*tjc2 + 8.78967d-9*tjc3 ! Mean obliq. o.t. eclip (Lieske et al, 1977)
156 deps = 4.46d-5*cos(omg) + 2.76d-6*cos(2*l0) + 4.848d-7*cos(2*lm) - 4.36d-7*cos(2*omg) ! Nutation in obliquity, Meeus, p.144
157 eps = eps0 + deps ! True obliquity of the ecliptic
158
159 ra = atan2(cos(eps)*sin(lam),cos(lam)) ! Geocentric right ascension, Eq. 25.6
160 dec = asin(sin(eps)*sin(lam)) ! Geocentric declination, Eq. 25.7
161
162
163 planpos(5) = ra ! Geocentric right ascension
164 planpos(6) = dec ! Geocentric declination
165 planpos(47) = dpsi ! Nutation in longitude
166 planpos(48) = eps ! True obliquity of the ecliptic; corrected for nutation
167 planpos(50) = eps0 ! Mean obliquity of the ecliptic; without nutation
168
169 if(calc.eq.2) return
170
171
172
173 gmst = calc_gmst(jd) ! Greenwich mean sidereal time
174 agst = rev(gmst + dpsi*cos(eps)) ! Correction for equation of the equinoxes -> Gr. apparent sid. time
175 lst = rev(agst + llon) ! Local apparent sidereal time, llon > 0 for E
176
177 planpos(44) = lst ! Local APPARENT sidereal time
178 planpos(45) = rev(agst) ! Greenwich mean sidereal time
179 planpos(49) = rev(gmst) ! Correction for equation of the equinoxes -> Gr. apparent sid. time
180
181 if(calc.eq.3) return
182
183
184
185 call eq2horiz(ra,dec,agst, hh,az,alt, lat=llat,lon=llon)
186 planpos(8) = rev(hh) ! Geocentric hour angle
187 planpos(9) = rev(az) ! Geocentric azimuth
188 planpos(10) = alt ! Geocentric altitude
189
190 if(calc.eq.4) return
191
192
193 planpos(13) = sunmagn(r) ! Apparent magnitude
194 planpos(16) = atan2(sin(hh),tan(llat)*cos(dec) - sin(dec)*cos(hh)) ! Parallactic angle
195
196 if(calc.eq.5) return
197
198 ! calc = 99:
199 planpos(29) = planpos(9) ! topocentric azimuth ~ geocentric azimuth
200 planpos(30) = alt - asin(sin(planpos(17))*cos(alt)) ! alt' = alt - Hp*cos(alt); topocentric altitude
201 planpos(31) = planpos(30) + refract(planpos(30)) ! Topocentric altitude, corrected for atmospheric refraction
202
203 end subroutine sunpos_la
204 !*********************************************************************************************************************************
205
206
207 !*********************************************************************************************************************************
208 !> Compute the position of the Sun - very low accuracy routine (~0.18 degrees in az/alt)
209 !!
210 !! \param DoY Day of year
211 !! \param hour Hour of day
212 !!
213 !! \param lon Geographic longitunde (radians; >0=east)
214 !! \param lat Geographic latitunde (radians; >0=north)
215 !! \param tz Time zone (hours; >0=east)
216 !!
217 !! \param ha Hour angle of the Sun (radians) (output)
218 !! \param dec Declination of the Sun (radians; >0=north) (output)
219 !!
220 !! \param az Azimuth of the Sun (radians; 0=north, pi/2=east) (output)
221 !! \param alt Altitude of the Sun (radians; >0 = up) (output)
222 !!
223 !! \see Wenham, S.R.: Applied photovoltaics (2012; book), Appendix B
224
225 subroutine sunpos_vla(DoY,hour, lon,lat,tz, ha,dec, az,alt)
226 use sufr_kinds, only: double
227 use sufr_constants, only: pi2, h2r,r2h
228
229 implicit none
230 integer, intent(in) :: DoY
231 real(double), intent(in) :: hour, lon,lat,tz
232 real(double), intent(out) :: dec,ha, alt,az
233 real(double) :: eclon, Teq,Tdif,Tsol
234
235 ! Declination of the Sun:
236 eclon = pi2/365.d0 * doy ! indication of the ecliptic longitude of the Sun (rad)
237
238 dec = 5.80863d-3 - 0.401146d0 * cos(eclon) - 6.1069d-3 * cos(2 * eclon) - 2.43997d-3 * cos(3 * eclon) &
239 + 6.52264d-2 * sin(eclon) + 5.59378d-4 * sin(2 * eclon) + 1.25437d-3 * sin(3 * eclon) ! Declination (rad)
240 ! Note: both 0.066099 and 0.065226 occur in the literature (as 3.7872 and 3.7372 degrees), but without any reference to an
241 ! original paper. 0.065226 gives a ~2% better declination when compared to VSOP87.
242
243
244 ! Equation of time:
245 if(doy .lt. 21) then
246 teq = -2.6d0 - 0.44d0 * doy
247 else if(doy .lt. 136) then
248 teq = -5.2d0 - 9.d0 * cos( (doy - 43) * 0.0357d0 )
249 else if(doy .lt. 241) then
250 teq = -1.4d0 + 5.d0 * cos( (doy - 135) * 0.0449d0 )
251 else if(doy .lt. 336) then
252 teq = 6.3d0 + 10.d0 * cos( (doy - 306) * 0.036d0 )
253 else
254 teq = 0.45d0 * (359 - doy)
255 end if
256
257 ! Time difference with UT:
258 tdif = tz - lon*r2h - teq/60.d0 ! tz = Tmet - Tgmt (hours)
259
260 ! Solar time:
261 tsol = hour - tdif ! (hours)
262
263 ! Hour angle of the Sun:
264 ha = (tsol - 12.d0)*h2r ! (rad)
265
266 ! Azimuth of the Sun:
267 az = atan2(sin(ha), cos(ha)*sin(lat) - tan(dec)*cos(lat)) ! (rad)
268
269 ! Altitude of the Sun:
270 alt = asin( sin(dec) * sin(lat) + cos(dec) * cos(lat) * cos(ha)) ! (rad)
271
272 end subroutine sunpos_vla
273 !*********************************************************************************************************************************
274
275
276 !*********************************************************************************************************************************
277 !> \brief Calculate Sun magnitude
278 !!
279 !! \param dist Distance (AU)
280 !! \retval sunmagn Sun magnitude
281
282 function sunmagn(dist)
283 use sufr_kinds, only: double
284
285 implicit none
286 real(double), intent(in) :: dist
287 real(double) :: sunmagn
288
289 sunmagn = -26.74d0 + 5*log10(dist)
290 end function sunmagn
291 !*********************************************************************************************************************************
292
293
294
295
296
297end module thesky_sun
298!***********************************************************************************************************************************
Procedures for coordinates.
real(double) function refract(alt, press, temp)
Compute the atmospheric refraction for a given true altitude. You should add the result to the uncorr...
subroutine eq2horiz(ra, dec, agst, hh, az, alt, lat, lon)
Convert spherical equatorial coordinates (RA, dec, agst) to spherical horizontal coordinates (hh,...
Date and time procedures.
Definition date_time.f90:49
real(double) function calc_gmst(jd, deltat)
Calculate Greenwich Mean Sidereal Time for any instant, in radians.
real(double) function calc_deltat(jd, force_recompute)
Compute DeltaT for a given JD.
Local parameters for libTheSky: location, date, time.
Definition modules.f90:56
real(double) lon0
Longitude of the observer (rad)
Definition modules.f90:64
real(double) lat0
Latitude of the observer (rad)
Definition modules.f90:63
Planet data, needed to compute planet positions.
Definition modules.f90:85
real(double), dimension(nplanpos) planpos
Planpos[] is an array with many different types of coordinates and related variables:
Definition modules.f90:192
Low-accuracy procedures for the Sun.
Definition sun.f90:23
real(double) function sunmagn(dist)
Calculate Sun magnitude.
Definition sun.f90:283
subroutine sunpos_la(jd, calc, lat, lon)
Low-accuracy solar coordinates.
Definition sun.f90:58
subroutine sunpos_vla(doy, hour, lon, lat, tz, ha, dec, az, alt)
Compute the position of the Sun - very low accuracy routine (~0.18 degrees in az/alt)
Definition sun.f90:226