libTheSky
Routines to compute sky positions of Sun, Moon, planets and more
All Namespaces Files Functions Variables Pages
moon_position.f90
Go to the documentation of this file.
1!> \file moon_position.f90 Core procedures that calculate the position and magnitude of the Moon 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 Procedures for the Moon
22
24 implicit none
25 save
26
27contains
28
29 !*********************************************************************************************************************************
30 !> \brief Calculate the apparent geocentric ecliptical position of the Moon, using the Lunar Solution ELP 2000-82B
31 !!
32 !! \param tjj Time for calculation in Julian millenia after 2000.0
33 !!
34 !! \param ll Apparent geocentric ecliptical longitude (output)
35 !! \param bb Apparent geocentric ecliptical latitude (output)
36 !! \param rr Apparent geocentric distance (output)
37 !!
38 !! \note
39 !! - This is supposed to be the ELP2000-85 version, with the corrections from the 1998 paper (mean arguments up to t^4,
40 !! etc,). However, the accuracy seems to be less than promised for historical calculations (0.1° rather than 0.01°
41 !! for CE 0). The subroutine elp_mpp02_lbr() below is supposed to give better results (but then again, so is this
42 !! one).
43 !! - Differences compared to ELP-MPP02 (ELP82b minus ELP-MPP02):
44 !! - longitude: +0.00001° in CE 1975, ~+0.11° in CE 0/4000 and ~+0.65° in 3000 BCE (systematically drifting to positive values)
45 !! - replacing w(1,2) = -5.8883 with -6.8084 removes the systematic drift to +0.65° @3000 BCE; (see data.f90 / readmoondata())
46 !! the drift now oscillates around +-0.012°;
47 !! - latitude: ~0.00000° in CE 1990, ~+/-0.01° in CE 0/4000 and +/- ~0.06° (now ~0.006°) in 3000 BCE
48 !! - distance: +/-0.03 km in CE 2000, +/- ~30 km in CE 0/4000 and +/- ~300 km (now ~20km) in 3000 BCE
49 !!
50 !! \see
51 !! - Chapront-Touzé & Chapront, A&A, 124, 50 (1983)
52 !! - Chapront-Touzé & Chapront, A&A, 190, 342 (1988)
53 !! - ftp://cdsarc.u-strasbg.fr/pub/cats/VI/79/
54
55 subroutine elp82b_lbr(tjj, ll,bb,rr)
56 use sufr_kinds, only: double, dbl
57 use sufr_constants, only: as2r, au, km !, r2d
58 use sufr_angles, only: rev
59
61
62 implicit none
63 real(double), intent(in) :: tjj
64 real(double), intent(out) :: ll,bb,rr
65
66 integer :: iv,itab,nt,k,j
67 real(double) :: r(3),x,y, pa,t4,t8 !, lon,lat,dist
68
69
70 r = 0.0_dbl
71 x = 0.0_dbl
72 y = 0.0_dbl
73
74 t(1) = tjj*10.0_dbl ! In Julian centuries since 2000.0
75 t(2) = t(1)**2 ! t^2
76 t(3) = t(2)*t(1) ! t^3
77 t(4) = t(2)**2 ! t^4
78
79 t4 = t(4) ! t^4
80 t8 = t4**2 ! t^8
81
82
83 do iv=1,3 ! 3 variables (lon, lat, dist)
84 r(iv) = 0.0_dbl
85
86 do itab = 1,12 ! 12 tables: ELP1,4,7,10,13,16,19,22,25,28,31,34 for lon
87 do nt = 1,nterm(iv,itab)
88
89 select case(iv) ! variable
90
91 case(1) ! lon
92 if(itab.eq.1) then
93 x = pc1(1,nt)
94 y = pc1(2,nt)
95 do k = 1,4
96 y = y + pc1(k+2,nt)*t(k)
97 end do
98 else
99 j = nrang(1,itab-1) + nt
100 x = per1(1,j)
101 y = per1(2,j) + per1(3,j)*t(1)
102 end if
103
104 case(2) ! lat
105 if(itab.eq.1) then
106 x = pc2(1,nt)
107 y = pc2(2,nt)
108 do k = 1,4
109 y = y + pc2(k+2,nt)*t(k)
110 end do
111 else
112 j = nrang(2,itab-1) + nt
113 x = per2(1,j)
114 y = per2(2,j) + per2(3,j)*t(1)
115 end if
116
117 case(3) ! dist
118 if(itab.eq.1) then
119 x = pc3(1,nt)
120 y = pc3(2,nt)
121 do k = 1,4
122 y = y + pc3(k+2,nt)*t(k)
123 end do
124 else
125 j = nrang(3,itab-1) + nt
126 x = per3(1,j)
127 y = per3(2,j) + per3(3,j)*t(1)
128 end if
129 end select
130
131 if(itab.eq.3.or.itab.eq.5 .or. itab.eq.7.or.itab.eq.9) x = x*t(1)
132 if(itab.eq.12) x = x*t(2)
133 r(iv) = r(iv) + x*sin(y)
134 end do ! nt
135 end do ! itab
136 end do ! iv
137
138
139 ! Change of units:
140 r(1) = r(1) * as2r + w(1,0) + w(1,1)*t(1) + w(1,2)*t(2) + w(1,3)*t(3) + w(1,4)*t(4) ! Add mean longitude (see ELP PS-file, p.3)
141 r(2) = r(2) * as2r
142 r(3) = r(3) * a0 / ath
143
144 !lon = r(1)
145 !lat = r(2)
146 !dist = r(3)
147 !write(*,'(A, F15.9,2F14.7,9F14.5)') 'ELP82b: ', t(1), rev(lon)*r2d, lat*r2d, dist, &
148 ! rev(w(1,0) + w(1,1)*t(1) + w(1,2)*t(2) + w(1,3)*t(3) + w(1,4)*t(4))*r2d, &
149 ! rev(w(1,0))*r2d, rev(w(1,1)*t(1))*r2d, rev(w(1,2)*t(2))*r2d, rev(w(1,3)*t(3))*r2d, rev(w(1,4)*t(4))*r2d
150
151 ! Precess from J2000 to EoD, see ELP PS-file, p12; Laskar 1986 - note: longitude only!:
152 pa = 2.438174835301452d-2 * t(1) + 5.391128133938040d-6 * t(2) + 3.733065344543427d-10 * t(3) &
153 - 1.140766591650738d-10 * t4 - 8.753311012432670d-14 * t4*t(1) + 8.460483549042511d-16 * t4*t(2) &
154 + 6.348635154129373d-18 * t4*t(3) + 1.175188363009515e-20 * t8 - 2.307228308400282d-22 * t8*t(1) &
155 - 4.198486478408581d-25 * t8*t(2)
156
157 r(1) = r(1) + pa
158
159 ll = rev(r(1))
160 bb = r(2)
161 rr = r(3)/au*km
162
163 ! The original code converts to rectangular coordinates and applies (more?) precession.
164 ! Since I want spherical coordinates, I don't do that here. This gives similar (though not identical) results.
165
166 !write(98,*) ll,bb,rr
167
168 end subroutine elp82b_lbr
169 !*********************************************************************************************************************************
170
171
172
173 !*********************************************************************************************************************************
174 !> \brief Compute the spherical lunar coordinates using the ELP2000/MPP02 lunar theory in the dynamical mean ecliptic and
175 !! equinox of J2000.
176 !!
177 !! \param jd Julian day to compute Moon position for
178 !! \param mode Index of the corrections to the constants: 0-Fit to LLR observations, 1-Fit to DE405 1950-2060 (historical)
179 !!
180 !! \param lon Ecliptic longitude (rad) (output)
181 !! \param lat Ecliptic latitude (rad) (output)
182 !! \param rad Distance (AU) (output)
183 !!
184 !! \param precess Apply precession (input, optional, default=.true.)
185 !!
186 !! \note See Lunar Solution ELP 2000/MPP02, Chapront & Francou (2002): ftp://cyrano-se.obspm.fr/pub/2_lunar_solutions/2_elpmpp02/
187
188 subroutine elp_mpp02_lbr(jd, mode, lon,lat,rad, precess)
189 use sufr_kinds, only: double
190 use sufr_constants, only: jd2000, au,km
191 use sufr_angles, only: rev
193
194 implicit none
195 real(double), intent(in) :: jd
196 integer, intent(in) :: mode
197 logical, intent(in), optional :: precess
198 real(double), intent(out) :: lon,lat,rad
199
200 integer :: ierr
201 real(double) :: xyz(3),vxyz(3)
202 logical :: lprecess
203
204 ! Handle optional parameters:
205 lprecess = .true.
206 if(present(precess)) lprecess = precess
207
208 call elp_mpp02_xyz(jd, mode, xyz,vxyz, ierr)
209
210 ! Compute ecliptic l,b,r:
211 rad = sqrt(sum(xyz**2))
212 lon = atan2(xyz(2),xyz(1))
213 lat = asin(xyz(3)/rad)
214
215 if(lprecess) call precess_ecl(jd2000,jd, lon,lat)
216 lon = rev(lon)
217
218 rad = rad*km/au ! km -> AU
219
220 end subroutine elp_mpp02_lbr
221 !*********************************************************************************************************************************
222
223
224 !***************************************************************************************************
225 !> \brief Compute the rectangular lunar coordinates using the ELP/MPP02 lunar theory in the dynamical mean ecliptic and equinox of J2000.
226 !!
227 !! \param jd Julian day to compute Moon position for
228 !! \param mode Index of the corrections to the constants: 0-Fit to LLR observations, 1-Fit to DE405 1950-2060 (historical)
229 !!
230 !! \param xyz Geocentric rectangular coordinates: (output)
231 !! - xyz(1) : Position X (km)
232 !! - xyz(2) : Position Y (km)
233 !! - xyz(3) : Position Z (km)
234 !! \param vxyz Geocentric rectangular velocities: (output)
235 !! - vxyz(1) : Velocity X' (km/day)
236 !! - vxyz(2) : Velocity Y' (km/day)
237 !! - vxyz(3) : Velocity Z' (km/day)
238 !! \param ierr File error index - ierr=0: no error, ierr=1: file error (output)
239 !!
240 !! \note
241 !! - The subroutine elp_mpp02() uses two modules:
242 !! - elp_mpp02_constants: Constants of the solution ELP/MPP02 (input),
243 !! - elp_mpp02_series: Series of the solution ELP/MPP02 (input).
244 !!
245 !! - The nominal values of some constants have to be corrected. There are two sets of corrections, which can be selected
246 !! using the parameter 'mode' (used in elp_mpp02_initialise()).
247 !! - mode=0, the constants are fitted to LLR observations provided from 1970 to 2001; it is the default value;
248 !! - mode=1, the constants are fitted to DE405 ephemeris over one century (1950-2060); the lunar angles W1, W2, W3
249 !! receive also additive corrections to the secular coefficients ('historical mode').
250 !! When the mode is changed, the constants will be reinitialised and the data file reread.
251 !!
252 !! - Solutions (discussed) in the paper:
253 !! - ELP (original):
254 !! - ELP2000-82: using VSOP82 (1983)
255 !! - ELP2000-85: new mean lunar arguments, higher truncation level, longer time range (1988)
256 !! - ELP2000-82B, here called "ELP": ELP2000-82, using mean lunar arguments from ELP2000-85 (19??)
257 !! - ELP/MPP01: using latest planetary perturbations from MPP01 and VSOP2000, but simpler than MPP01
258 !! - ELP/MPP02: ELP/MPP01, but for some arguments back to ELP + different selection of perturbations + lower truncation. Good fit with DE 405 in [1950,2060]
259 !! - ELP/MPP02*: improved secular arguments, better long-term comparison to DE 405/406 [-3000,2500]
260 !! - ELP/MPP02(LLR): ELP/MPP02(*?), optimised for lunar ranging since 1970
261 !! - ELPa: ELP + few Poisson terms (tested in the current study only?)
262 !! - ELPa*: ELPa + better secular arguments (as in ELP/MPP02*)
263 !! - It is not entirely clear which version is given below, but we can hope it is ELP/MPP02*. However, the subroutine
264 !! elp82b_lbr() above is known to underperform (by a factor of 10) in accuracy.
265
266 subroutine elp_mpp02_xyz(jd, mode, xyz,vxyz, ierr)
267 use sufr_kinds, only: double
268 use sufr_constants, only: r2as, jd2000 !, r2d!,as2r
269 use sufr_system, only: quit_program_error
270 use sufr_angles, only: rev
272
273 use thesky_elp_mpp02_series, only: cmpb,fmpb,nmpb, cper,fper,nper
274 use thesky_elp_mpp02_constants, only: w, p1,p2,p3,p4,p5, q1,q2,q3,q4,q5
275
276 implicit none
277 integer, intent(in) :: mode
278 real(double), intent(in) :: jd
279 integer, intent(out) :: ierr
280 real(double), intent(out) :: xyz(3),vxyz(3)
281
282
283 real(double), parameter :: a405=384747.9613701725d0, aelp=384747.980674318d0, sc=36525.d0 ! Moon mean distance for DE405 und ELP; Julian century in days
284
285 integer :: it,iLine,iVar, k
286 real(double) :: rjd, t(-1:4),v(6) !, lon,lat,dist
287 real(double) :: cbeta,clamb,cw, ppw,ppw2,ppwqpw,ppwra,pw,pw2,pwqw,pwra, qpw,qpw2,qpwra,qw,qw2,qwra
288 real(double) :: ra,rap,sbeta,slamb,sw, x,x1,x2,x3, xp,xp1,xp2,xp3, y,yp
289
290 ! Initialise data and read files if needed:
292 if(ierr.ne.0) call quit_program_error('Could not read ELP-MPP02 files',0)
293
294
295 ! Initialization of time powers:
296 rjd = jd - jd2000 ! Reduced JD - JD since 2000
297 t(0) = 1.d0
298 t(1) = rjd/sc ! t: time since 2000 in Julian centuries
299 t(2) = t(1)**2 ! t^2
300 t(3) = t(2)*t(1) ! t^3
301 t(4) = t(2)**2 ! t^4
302
303 ! Evaluation of the series: substitution of time in the series
304 v = 0.d0
305 do ivar=1,3 ! iVar=1,2,3: Longitude, Latitude, Distance
306
307 ! Main Problem series:
308 do iline=nmpb(ivar,2),nmpb(ivar,3)
309 x = cmpb(iline)
310 y = fmpb(0,iline)
311 yp = 0.d0
312
313 do k=1,4
314 y = y + fmpb(k,iline)*t(k)
315 yp = yp + k*fmpb(k,iline)*t(k-1)
316 end do ! k
317
318 v(ivar) = v(ivar) + x*sin(y)
319 v(ivar+3) = v(ivar+3) + x*yp*cos(y)
320 end do ! iLine
321
322 ! Perturbations series:
323 do it=0,3
324 do iline=nper(ivar,it,2),nper(ivar,it,3)
325 x = cper(iline)
326 y = fper(0,iline)
327 xp = 0.d0
328 yp = 0.d0
329 if(it.ne.0) xp = it * x * t(it-1)
330
331 do k=1,4
332 y = y + fper(k,iline)*t(k)
333 yp = yp + k*fper(k,iline)*t(k-1)
334 end do ! k
335
336 v(ivar) = v(ivar) + x * t(it) * sin(y)
337 v(ivar+3) = v(ivar+3) + xp*sin(y) + x*t(it)*yp*cos(y)
338 end do ! iLine
339 end do ! it
340
341 end do ! iVar
342
343
344 ! Compute the spherical coordinates for the mean inertial ecliptic and equinox of date:
345 v(1) = v(1)/r2as + w(1,0) + w(1,1)*t(1) + w(1,2)*t(2) + w(1,3)*t(3) + w(1,4)*t(4) ! Longitude + mean longitude (rad)
346 !v(1) = rev(v(1)/r2as) + w(1,0) + rev(w(1,1)*t(1)) + rev(w(1,2)*t(2)) + rev(w(1,3)*t(3)) + rev(w(1,4)*t(4)) ! Longitude + mean longitude (rad)
347 v(2) = v(2)/r2as ! Latitude (rad)
348 v(3) = v(3) * a405 / aelp ! Distance (km)
349
350 !lon = v(1)
351 !lat = v(2)
352 !dist = v(3)
353 !lon = lon + (5029.0966d0*t(1) + 1.1120d0*t(2) + 0.000077d0*t(3) - 0.00002353d0*t(4) - 0.29965d0*t(1)) * as2r ! Precession from J2000 to EoD(?), but only in longitude!
354 !write(*,'(A, F15.9,2F14.7,9F14.5)') 'ELP-MPP02: ', t(1), rev(lon)*r2d, lat*r2d, dist, &
355 ! rev(w(1,0) + w(1,1)*t(1) + w(1,2)*t(2) + w(1,3)*t(3) + w(1,4)*t(4))*r2d, &
356 ! rev(w(1,0))*r2d, rev(w(1,1)*t(1))*r2d, rev(w(1,2)*t(2))*r2d, rev(w(1,3)*t(3))*r2d, rev(w(1,4)*t(4))*r2d
357
358 v(1) = rev(v(1)) ! This adds a bit of CPU time, but also alters the outcome of the cos/sin, similarly to
359 ! taking the 5 rev()s before adding up the terms when computing v(1), which might
360 ! indicate that this gives a better result, especially for dates far from 2000
361
362
363 ! Compute the rectangular coordinates (for the EoD?):
364 clamb = cos(v(1))
365 slamb = sin(v(1))
366 cbeta = cos(v(2))
367 sbeta = sin(v(2))
368 cw = v(3)*cbeta
369 sw = v(3)*sbeta
370
371 x1 = cw*clamb
372 x2 = cw*slamb
373 x3 = sw
374
375 ! Is this simply precession in rectangular coordinates from EoD to J2000?
376 pw = (p1 + p2*t(1) + p3*t(2) + p4*t(3) + p5*t(4)) * t(1)
377 qw = (q1 + q2*t(1) + q3*t(2) + q4*t(3) + q5*t(4)) * t(1)
378
379 ra = 2*sqrt(1.d0 - pw**2 - qw**2)
380 pwqw = 2*pw*qw
381 pw2 = 1.d0 - 2*pw**2
382 qw2 = 1.d0 - 2*qw**2
383 pwra = pw*ra
384 qwra = qw*ra
385
386 xyz(1) = pw2*x1 + pwqw*x2 + pwra*x3
387 xyz(2) = pwqw*x1 + qw2*x2 - qwra*x3
388 xyz(3) = -pwra*x1 + qwra*x2 + (pw2+qw2-1.d0)*x3
389
390 !xyz(1) = x1
391 !xyz(2) = x2
392 !xyz(3) = x3
393
394
395 ! Compute the rectangular velocities for the equinox J2000:
396 v(4) = v(4)/r2as + w(1,1) + 2*w(1,2)*t(1) + 3*w(1,3)*t(2) + 4*w(1,4)*t(3)
397 v(5) = v(5)/r2as
398
399 xp1 = (v(6)*cbeta - v(5)*sw)*clamb - v(4)*x2
400 xp2 = (v(6)*cbeta - v(5)*sw)*slamb + v(4)*x1
401 xp3 = v(6)*sbeta + v(5)*cw
402
403 ppw = p1 + (2*p2 + 3*p3*t(1) + 4*p4*t(2) + 5*p5*t(3)) * t(1)
404 qpw = q1 + (2*q2 + 3*q3*t(1) + 4*q4*t(2) + 5*q5*t(3)) * t(1)
405 ppw2 = -4*pw*ppw
406 qpw2 = -4*qw*qpw
407 ppwqpw = 2*(ppw*qw + pw*qpw)
408 rap = (ppw2+qpw2)/ra
409 ppwra = ppw*ra + pw*rap
410 qpwra = qpw*ra + qw*rap
411
412 vxyz(1) = (pw2*xp1 + pwqw*xp2 + pwra*xp3 + ppw2*x1 + ppwqpw*x2 + ppwra*x3) / sc
413 vxyz(2) = (pwqw*xp1 + qw2*xp2 - qwra*xp3 + ppwqpw*x1 + qpw2*x2 - qpwra*x3) / sc
414 vxyz(3) = (-pwra*xp1 + qwra*xp2 + (pw2+qw2-1.d0)*xp3 - ppwra*x1 + qpwra*x2 + (ppw2+qpw2)*x3) / sc
415
416 end subroutine elp_mpp02_xyz
417 !***************************************************************************************************
418
419
420
421
422
423 !*********************************************************************************************************************************
424 !> \brief Quick, lower-accuracy lunar coordinates; ~600x faster than ELP
425 !!
426 !! \param jd Julian day for computation
427 !! \param calc Calculate: 1: l,b,r, 2: & ra,dec, 3: & gmst,agst, 4: & az,alt, nt: number of terms <=60
428 !! \param nt Number of terms to use
429 !!
430 !! \see
431 !! - Meeus, Astronomical Algorithms, 1998, Ch. 22 and 47
432 !! - Simon et al, A&A, 282, p.663 (1994)
433
434 subroutine moonpos_la(jd, calc,nt)
435 use sufr_kinds, only: double
436 use sufr_constants, only: au, pi,d2r, jd2000, pland,earthr
437 use sufr_angles, only: rev, rev2
438 use sufr_system, only: quit_program_warning
439
440 use thesky_sun, only: sunpos_la
444 use thesky_local, only: lon0,lat0
445
446 implicit none
447 real(double), intent(in) :: jd
448 integer, intent(in) :: calc,nt
449
450 integer :: iLine,iArg, mal(4,60),mab(4,60)
451 real(double) :: jde,deltat, tjc,tjc2,tjc3,tjc4, l,b,r, lm,d,ms,mm,f,e,esl(60),esb(60),a1,a2,a3
452 real(double) :: ls,omg,ra,dec,eps,eps0,deps,gmst,agst,lst,dpsi,az,alt,hh, args(4),argl,argb
453 real(double) :: moondat(nPlanpos), hcl0,hcb0,hcr0, gcl,gcb,delta, elon,pa,illfr
454
455 if(sum(moonla_lrb(1:2,1)) .ne. -14616581) call quit_program_warning('moonpos_la(): moon_la.dat not read', 0)
456
457 deltat = calc_deltat(jd)
458 jde = jd + deltat/86400.d0
459
460 tjc = (jde-jd2000)/36525.d0 ! Julian Centuries after 2000.0 in dynamical time, the T in Meeus, p.163
461 tjc2 = tjc**2
462 tjc3 = tjc*tjc2
463 tjc4 = tjc2**2
464
465 ! Moon's mean longitude, Meeus p.338:
466 lm = rev(3.8103408236d0 + 8399.7091116339958d0*tjc - 2.755176757d-5*tjc2 + 3.239043d-8*tjc3 - 2.6771d-10*tjc4)
467
468 ! Delaunay arguments [d, ms, mm, f] (Meeus p.144) = [D, l', l, F] in Simon et al. 1994, Sect. 3.5:
469 ! d = rev(5.19846946025d0 + 7771.37714617d0*tjc - 3.340909d-5*tjc2 + 9.2114446d-8*tjc3) ! Moon's mean elongation
470 ! ms = rev(6.24003588115d0 + 628.301956024d0*tjc - 2.79776d-6*tjc2 - 5.8177641733d-8*tjc3) ! Sun's mean anomaly
471 ! mm = rev(2.3555483693d0 + 8328.69142288d0*tjc + 1.517947757d-4*tjc2 + 3.102807559d-7*tjc3) ! Moon's mean anomaly
472 ! f = rev(1.62790192912d0 + 8433.46615832d0*tjc - 6.42717497d-5*tjc2 + 5.3329949d-8*tjc3) ! Moon's argument of latitude
473
474 ! Meeus p.338, compares better to ELP-MPP02:
475 d = rev(5.1984665298d0 + 7771.377144834d0*tjc - 3.2845d-5*tjc2 + 3.197347d-8*tjc3 - 1.5436512d-10*tjc4) ! Moon's mean elongation
476 ms = rev(6.240060127d0 + 628.301955167d0*tjc - 2.681d-6*tjc2 + 7.1267017d-10*tjc3) ! Sun's mean anomaly
477 mm = rev(2.355555637d0 + 8328.691424759d0*tjc + 1.52566d-4*tjc2 + 2.5041d-7*tjc3 - 1.18633d-9*tjc4) ! Moon's mean anomaly
478 f = rev(1.627905158d0 + 8433.466158061d0*tjc - 6.3773d-5*tjc2 - 4.94988d-9*tjc3 + 2.02167d-11*tjc4) ! Moon's argument of latitude
479 args = [d,ms,mm,f] ! Delaunay arguments
480
481 e = 1.d0 - 0.002516d0*tjc - 0.0000074d0*tjc2
482
483 l = 0.d0
484 r = 0.d0
485 b = 0.d0
486
487 mal = moonla_arg(1:4,:)
488 mab = moonla_arg(5:8,:)
489 esl = e**abs(moonla_arg(2,:))
490 esb = e**abs(moonla_arg(6,:))
491
492 do iline=1,min(nt,60)
493 argl = 0.d0
494 argb = 0.d0
495 do iarg=1,4
496 argl = argl + mal(iarg,iline)*args(iarg)
497 argb = argb + mab(iarg,iline)*args(iarg)
498 end do
499 l = l + sin(argl) * moonla_lrb(1,iline) * esl(iline)
500 r = r + cos(argl) * moonla_lrb(2,iline) * esl(iline)
501 b = b + sin(argb) * moonla_lrb(3,iline) * esb(iline)
502 end do
503
504
505 ! Perturbations by other planets, and flattening of the Earth:
506 ! Meeus, p.338:
507 a1 = rev(2.090032d0 + 2.301199d0 * tjc) ! Influence from Venus
508 a2 = rev(0.926595d0 + 8364.7398477d0 * tjc) ! Influence from Jupiter
509 a3 = rev(5.4707345d0 + 8399.6847253d0 * tjc)
510
511 ! Meeus, p.342:
512 l = l + 3958*sin(a1) + 1962*sin(lm-f) + 318*sin(a2)
513 b = b - 2235*sin(lm) + 382*sin(a3) + 175*sin(a1-f) + 175*sin(a1+f) + 127*sin(lm-mm) - 115*sin(lm+mm)
514
515
516 ! Compute nutation:
517 omg = 2.18243858558d0 - 33.7570459367d0*tjc + 3.6142278d-5*tjc2 + 3.87850944888d-8*tjc3 ! Moon's mean lon. of asc.node, Meeus p.144
518 ls = 4.89506386655d0 + 62.84528862d0*tjc ! Mean long. Sun, Meeus p.144
519 dpsi = -8.338795d-5*sin(omg) - 6.39954d-6*sin(2*ls) - 1.115d-6*sin(2*lm) + 1.018d-6*sin(2*omg)
520
521 l = rev( dble(l) * 1.d-6*d2r + lm + dpsi)
522 b = rev2(dble(b) * 1.d-6*d2r)
523 r = (dble(r*100) + 3.8500056d10)/au
524
525
526 ! Store results:
527 planpos(1) = l ! Geocentric ecliptic longitude
528 planpos(2) = b ! Geocentric ecliptic latitude
529 planpos(4) = r ! Geocentric distance
530
531 planpos(7) = 5.77551830441d-3 * r ! Light time in days
532 planpos(12) = pland(0)/(r*au) ! Apparent diameter of the Moon
533
534 planpos(40) = jde ! JDE
535 planpos(46) = tjc ! App. dyn. time in Julian Centuries since 2000.0
536 planpos(47) = dpsi ! Nutation in longitude
537
538 if(calc.eq.1) return
539
540
541 ! Obliquity of the ecliptic:
542 eps0 = 0.409092804222d0 - 2.26965525d-4*tjc - 2.86d-9*tjc2 + 8.78967d-9*tjc3 ! Mean obliquity of the ecliptic (Lieske et al, 1977)
543 deps = 4.468d-5*cos(omg) + 2.76d-6*cos(2*ls) + 4.848d-7*cos(2*lm) - 4.36d-7*cos(2*omg) ! Nutation in obliquity
544 eps = eps0 + deps ! True obliquity of the ecliptic
545
546 call ecl_2_eq(l,b,eps, ra,dec) ! Ecliptical -> equatorial coordinates
547
548 ! Store results:
549 planpos(5) = ra ! Geocentric right ascension
550 planpos(6) = dec ! Geocentric declination
551
552 planpos(48) = eps ! True obliquity of the ecliptic; corrected for nutation
553 planpos(50) = eps0 ! Mean obliquity of the ecliptic; without nutation
554
555 if(calc.eq.2) return
556
557
558 ! Sidereal time:
559 gmst = calc_gmst(jd) ! Greenwich mean sidereal time
560 agst = rev(gmst + dpsi*cos(eps)) ! Correction for equation of the equinoxes -> Gr. apparent sid. time
561 lst = rev(agst + lon0) ! Local apparent sidereal time, lon0 > 0 for E
562
563 planpos(44) = lst ! Local APPARENT sidereal time
564 planpos(45) = agst ! Greenwich APPARENT sidereal time (in radians)
565 planpos(49) = gmst ! Greenwich MEAN sidereal time (in radians)
566
567 if(calc.eq.3) return
568
569
570 call eq2horiz(ra,dec,agst, hh,az,alt) ! Equatorial -> horizontal coordinates
571
572 planpos(8) = hh ! Geocentric hour angle
573 planpos(9) = az ! Geocentric azimuth
574 planpos(10) = alt ! Geocentric altitude
575
576 if(calc.eq.4) return
577
578
579 moondat = planpos ! Store Moon data
580
581 ! Get some Sun data:
582 call sunpos_la(jd,1)
583 hcl0 = rev(planpos(1)+pi) ! Heliocentric longitude of the Earth - want geocentric lon of Sun?
584 hcb0 = -planpos(2) ! Heliocentric latitude of the Earth - want geocentric lat of Sun?
585 hcr0 = planpos(3)
586
587 planpos = moondat ! Restore Moon data:
588 gcl = planpos(1) ! l
589 gcb = planpos(2) ! b
590 delta = planpos(4) ! r
591
592
593 elon = acos(cos(gcb)*cos(hcb0)*cos(gcl-rev(hcl0+pi)))
594 pa = atan2( hcr0*sin(elon) , delta - hcr0*cos(elon) ) ! Phase angle
595 illfr = 0.5d0*(1.d0 + cos(pa)) ! Illuminated fraction of the disc
596
597 planpos(11) = rev(elon) ! Elongation
598 planpos(13) = moonmagn(pa,delta) ! Magnitude
599 planpos(14) = illfr ! Illuminated fraction
600 planpos(15) = rev(pa) ! Phase angle
601 planpos(16) = atan2(sin(planpos(8)),tan(lat0)*cos(planpos(6)) - sin(planpos(6))*cos(planpos(8))) ! Parallactic angle
602 planpos(17) = asin(earthr/(planpos(4)*au)) ! Horizontal parallax
603
604 planpos(41) = rev(hcl0+pi) ! Geocentric, true L,B,R for the Sun
605 planpos(42) = rev2(-hcb0)
606 planpos(43) = hcr0
607
608 end subroutine moonpos_la
609 !*********************************************************************************************************************************
610
611
612
613
614
615
616
617 !*********************************************************************************************************************************
618 !> \brief Calculate the magnitude of the Moon
619 !!
620 !! \param pa Phase angle (rad)
621 !! \param delta Geocentric(?) distance (AU)
622 !!
623 !! \retval moonmagn The magnitude of the Moon
624 !!
625 !! \see
626 !! - Allen, 1976, par.66
627 !! - http://cleardarksky.com/others/BenSugerman/star.htm
628
629 function moonmagn(pa, delta)
630 use sufr_kinds, only: double
631
632 implicit none
633 real(double), intent(in) :: pa,delta
634 real(double) :: moonmagn
635
636 moonmagn = -12.73d0 + 1.489690267d0*abs(pa) + 0.04310727d0*pa**4 ! Allen, 1976, par.66 (d2r)
637
638 ! Correct for variable distance and the 'opposition effect' or 'opposition surge' which occurs when pa < 7d:
639 ! Not sure what the original reference is. See e.g.:
640 ! - Whitaker, E. A. 1969, in Analysis of Apollo 8 Photography and Visual Observations, NASA SP-201, 38, p.39
641 ! - Schaefer, PASP 102 212 (1990)
642 ! - Krisciunas & Schaefer, PASP 103, 1033 (1991): ""
643 moonmagn = moonmagn - 2.5*log10( (2.5696d-3/delta)**2 * max(1.d0, 1.35d0 - 2.864789d0*abs(pa) ) ) ! (1-1.35)/2.865 ~ 7deg
644
645 end function moonmagn
646 !*********************************************************************************************************************************
647
648
649
650end module thesky_moon
651!***********************************************************************************************************************************
Procedures for coordinates.
subroutine eq2horiz(ra, dec, agst, hh, az, alt, lat, lon)
Convert spherical equatorial coordinates (RA, dec, agst) to spherical horizontal coordinates (hh,...
subroutine ecl_2_eq(l, b, eps, ra, dec)
Convert (geocentric) spherical ecliptical coordinates l,b (and eps) to spherical equatorial coordinat...
subroutine precess_ecl(jd1, jd2, l, b)
Compute the precession of the equinoxes in geocentric ecliptical coordinates.
Procedures to set constants and read data files.
Definition data.f90:23
subroutine elp_mpp02_initialise_and_read_files(mode, ierr)
Initialise ELP-MPP02 data and read the data files.
Definition data.f90:736
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
Procedures for the Moon.
subroutine elp82b_lbr(tjj, ll, bb, rr)
Calculate the apparent geocentric ecliptical position of the Moon, using the Lunar Solution ELP 2000-...
real(double) function moonmagn(pa, delta)
Calculate the magnitude of the Moon.
subroutine elp_mpp02_lbr(jd, mode, lon, lat, rad, precess)
Compute the spherical lunar coordinates using the ELP2000/MPP02 lunar theory in the dynamical mean ec...
subroutine elp_mpp02_xyz(jd, mode, xyz, vxyz, ierr)
Compute the rectangular lunar coordinates using the ELP/MPP02 lunar theory in the dynamical mean ecli...
subroutine moonpos_la(jd, calc, nt)
Quick, lower-accuracy lunar coordinates; ~600x faster than ELP.
ELP 2000-82B Moon data, needed to compute Moon positions.
Definition modules.f90:202
real(double), parameter a0
Constant for ELP 2000-82B theory (orbital separation?)
Definition modules.f90:211
real(double), dimension(3, 0:4) w
Constants for mean longitude.
Definition modules.f90:225
integer, dimension(3, 0:12) nrang
CHECK: Number of terms? in ELP 2000-82B data file.
Definition modules.f90:247
real(double), dimension(6, 704) pc3
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:239
real(double), dimension(6, 918) pc2
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:238
real(double), dimension(6, 1023) pc1
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:237
real(double), dimension(3, 19537) per1
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:240
real(double), parameter ath
Constant for ELP 2000-82B theory (orbital separation?)
Definition modules.f90:210
real(double), dimension(0:4) t
Array for time^0, ..., time^4.
Definition modules.f90:232
integer, dimension(3, 12) nterm
CHECK: Number of terms? in ELP 2000-82B data file.
Definition modules.f90:246
real(double), dimension(3, 6766) per2
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:241
real(double), dimension(3, 8924) per3
CHECK: Something in ELP 2000-82B theory.
Definition modules.f90:242
Planet data, needed to compute planet positions.
Definition modules.f90:85
integer(long), dimension(3, 60) moonla_lrb
L,B,R data for the low-accuracy (la) Moon position.
Definition modules.f90:94
integer, parameter nplanpos
Number of entries in the planpos array.
Definition modules.f90:116
real(double), dimension(nplanpos) planpos
Planpos[] is an array with many different types of coordinates and related variables:
Definition modules.f90:192
integer, dimension(8, 60) moonla_arg
Arguments for the low-accuracy (la) Moon position.
Definition modules.f90:93
Low-accuracy procedures for the Sun.
Definition sun.f90:23
subroutine sunpos_la(jd, calc, lat, lon)
Low-accuracy solar coordinates.
Definition sun.f90:58