Elp MPP 02
Elp MPP 02
ELP/MPP02 is a semi-analytic solution for the lunar motion developed by J. Chapront and
G. Francou in 2002. It is an improvement of the ELP2000-82B lunar theory. The major paper
about the ELP/MPP02 theory is The lunar theory ELP revisited. Introduction of new planetary
perturbations by J. Chapront and G. Francou, Astronomy and Astrophysics, v.404, p.735-742
(2003), which you can also find references to the ELP2000-82B theory. The authors provide data
files, a FORTRAN code and a pdf documentation on this ftp site. ELP/MPP02 theory provides
two sets of parameters adjusted to fit either the lunar laser ranging (LLR) observation data or
JPL’s DE405/DE406 ephemerides.
I have written C++ functions to compute the lunar positions based on the information on
that ftp site. The full ELP/MPP02 theory contains series involving 35901 terms. High accuracy
of lunar positions may not be necessary for some applications. It is therefore useful to create a
truncated series to speed up computation. I have written routines that create a truncated series
using 4 parameters. I also wrote a function to estimate the accuracy of the truncated series.
JavaScript is convenient for HTML-based applications, such as my local star charts and equa-
torial star charts pages. I wrote C++ routines that generate JavaScript functions to compute a
truncated ELP/MPP02 series.
This document describes my implementation of the ELP/MPP02 series, the creation of a
truncated series, and the estimation of the accuracy of the truncated series. I do not explain the
ELP/MPP02 theory in this document. Readers who are interested in the theory can read the
paper and the pdf document on the ftp site mentioned above.
1 Implementation of ELP/MPP02
The equations for computing the ELP/MPP02 are given in the pdf document on this ftp site. In
this section, I rewrite the equations in a form that is more convenient for code development.
1
Variable Name in the code LLR DE405/DE406
(0)
∆W1 Dw1 0 −0.1052500 −0.0700800
(0)
∆W2 Dw2 0 +0.1682600 +0.2079400
(0)
∆W3 Dw3 0 −0.1076000 −0.0721500
(1)
∆W1 Dw1 1 −0.3231100 /cy −0.3510600 /cy
(1)
∆W2 Dw2 1 +0.0801700 /cy +0.0801700 /cy
(1)
∆W3 Dw3 1 −0.0431700 /cy −0.0431700 /cy
(2)
∆W1 Dw1 2 −0.0379400 /cy2 −0.0374300 /cy2
∆Γ Dgam +0.0006900 +0.0008500
∆E De +0.0000500 −0.0000600
∆T (0) Deart 0 −0.0401200 −0.0003300
∆T (1) Deart 1 +0.0144200 /cy +0.0073200 /cy
0
∆$ (0) Dperi −0.0485400 −0.0074900
∆e0 Dep +0.0022600 +0.0022400
(3)
∆W1 Dw1 3 0 −0.0001886500 /cy3
(4)
∆W1 Dw1 4 0 −0.0000102400 /cy4
(2)
∆W2 Dw2 2 0 +0.0047060200 /cy2
(3)
∆W2 Dw2 3 0 −0.0002521300 /cy3
(2)
∆W3 Dw3 2 0 −0.0026107000 /cy2
(3)
∆W3 Dw3 3 0 −0.0001071200 /cy3
Here cy denotes Julian century. Note that the last 6 variables in the DE405/DE406 column
are used to make ELP/MPP02 approaches closely the JPL Ephemeris DE406 on a long range (a
few seconds over 6 millennia), whereas the rest are fitted to DE405 only.
There are 8 more parameters needed. To calculate them, the following constants are calculated
first.
0 0
j B2,j B3,j
1 0.311079095 -0.103837907
2 -0.004482398 0.000668287
3 -0.001102485 -0.001298072
4 0.001056062 -0.000178028
5 0.000050928 -0.000037342
m = n0 /ν = 0.074801329,
α = a0 /a0 = 0.002571881,
(1) (1)
W1 = 1732559343.7360400 /cy + ∆W1 ,
(1) (1)
W2 = 14643420.317100 /cy + ∆W2 ,
(1) (1)
W3 = −6967919.538300 /cy + ∆W3 ,
(1)
δν = 0.5560400 /cy + ∆W1 ,
δΓ = −0.0806600 + ∆Γ,
δE = 0.0178900 + ∆E,
δe0 = −0.1287900 + ∆e0 ,
δn0 = −0.064200 /cy + ∆T (1) .
2
The following are the equations for the 8 remaining parameters.
(1)
W 2α 0 2α 0
(1) 2 0 (1) 0
δW2 = (1)
− m B2,1 + B2,5 ∆W1 + B2,1 + B2,5 ∆T (1)
W1 3m 3m
(1)
0 0 0
+W1 (B2,2 ∆Γ + B2,3 ∆E + B2,4 ∆e0 )
(1)
W 2α 0 2α 0
(1) 3 0 (1) 0
δW3 = − m B3,1 + B3,5 ∆W1 + B3,1 + B ∆T (1)
(1)
W1 3m 3m 3,5
(1)
0 0 0
+W1 (B3,2 ∆Γ + B3,3 ∆E + B3,4 ∆e0 )
2δν
fA = 1 − (1)
3W1
0
δn − mδν
fB1 = (1)
W1
fB2 = δΓ (in radians)
fB3 = δE (in radians)
fB4 = δe0 (in radians)
2α
fB5 = (1)
(δn0 − mδν).
3mW1
(0) (0) (0) (1) (1) (1) (2)
The first 21 parameters ∆W1 , ∆W2 , ∆W3 , ∆W1 , ∆W2 , ∆W3 , ∆W1 , ∆Γ, ∆E,
(3) (4) (2) (3) (2) (3) (1) (1)
∆T (0) , ∆T (1) , ∆$0(0) , ∆e0 , ∆W1 , ∆W1 , ∆W2 , ∆W2 , ∆W3 , ∆W3 , δW2 , and δW3 are
grouped together in the struct Elp paras in the C++ file ElpMpp02.h. The last 6 parameters
fA , fB1 , fB2 , fB3 , fB4 , and fB5 are grouped in the struct Elp facs in ElpMpp02.h. These 27
parameters are fixed once LLR or DE405/DE406 are specified. They only need to be computed
once.
These parameters are calculated in the subroutine
setup parameters(int corr, Elp paras ¶s, Elp facs &facs)
Parameters fitted to LLR are computed if corr is 0 and parameters fitted to DE405/DE406 are
computed if corr is 1. These groupings are convenient if one wants to construct other sets of
parameters fitted to other data (e.g. DE431).
3
The series is calculated by the equation
( )
sin
(i1 D + i2 F + i3 l + i4 l0 ) {i} = {i1 , i2 , i3 , i4 }.
X
Ã{i} (1)
{i}
cos
Longitude and latitude are sine series and distance is cosine series. The 4 variables D, F , l and
l0 are the Delaunay arguments (see the next subsection). The coefficients Ã{i} are calculated
according to
5
P
A{i} + fBj Bj{i} for longitude and latitude
j=1
Ã{i} = , (2)
5
P
fA A{i} + fBj Bj{i} for distance
j=1
where fA and fBj (j = 1, 2, 3, 4, 5) are the paremeters described in the previous subsection. They
are grouped together in the struct Elp facs in ElpMpp02.h. Note that B6{i} are not used in the
calculation. In additional, the amplitudes A{i} for longitude and latitude are in arcseconds in the
original data files. I converted them to radians in the files elp main.long and elp main.lat.
The remaining 11 files contain the Poisson series for perturbations. Each file has 15 columns
containing i1 , i2 , ..., i13 , A and φ0 . The series is summed according to the equation
X
A{i} sin φ {i} = {i1 , i2 , ..., i13 }, (3)
{i}
φ = φ0 +i1 D+i2 F +i3 l+i4 l0 +i5 M e+i6 V e+i7 EM +i8 M a+i9 Ju+i10 Sa+i11 U r+i12 N e+i13 ζ, (4)
where the 13 arguments D, F , ... will be described in the next subsection. In the longitude and
latitude files, the amplitudes A{i} are in radians/cyn . In all perturbation files, The initial phase
φ0{i} are in radians.
The amplitudes Ã{i} in the main problem are fixed once the adjustable parameters fitted to
LLR or DE405/DE406 are determined. The amplitudes A{i} in the Poisson series for perturbations
are the same for the LLR and DE405/DE406 parameters. Hence, all coefficients are determined
once LLR or DE405/DE406 are specified. The coefficients are calculated after the parameters
in the previous subsection are calculated. They are grouped together in the struct Elp coefs in
ElpMpp02.h.
The coefficients are calculated in the subroutine
setup Elp coefs(Elp coefs &coefs, Elp facs facs)
4
(2) (3)
+(−38.263100 /cy2 + ∆W2 )T 2 + (−0.04504700 /cy3 + ∆W2 )T 3
+(0.0002130100 /cy4 )T 4 (6)
(0) (1) (1)
W3 = (125 2 40.39816 + ∆W3 ) + (−6967919.538300 /cy + ∆W3
◦ 0 00
+ δW3 )T
(2) (3)
+(6.35900 /cy2 + ∆W3 )T 2 + (0.00762500 /cy3 + ∆W3 )T 3
00 4 4
+(−0.00003586 /cy )T (7)
Ea = (100◦ 270 59.1388500 + ∆T (0) ) + (129597742.29300 /cy + ∆T (1) )T
+(−0.020200 /cy2 )T 2 + (900 × 10−6 /cy3 )T 3
+(1.500 × 10−7 /cy4 )T 4 (8)
$0 = (102◦ 560 14.4576600 + ∆$0(0) ) + (1161.2434200 /cy)T + (0.52926500 /cy2 )T 2
−(1.181400 × 10−4 /cy3 )T 3 + (1.137900 × 10−5 /cy4 )T 4 , (9)
where T = (JD − 2451545)/36525 is the barycentric dynamical time (TDB) in Julian centuries
from J2000.0
Delaunay arguments D, F , l and l0 are given by
D = W1 − Ea + 180◦ (10)
F = W1 − W3 (11)
l = W1 − W2 (12)
l0 = Ea − $0 . (13)
These are the 4 arguments appearing in the ELP/MPP02 series for the main problem, and also
the first 4 arguments appearing in the ELP/MPP02 series for perturbations. The remaining 9
arguments in the ELP/MPP02 series for perturbations are given by
These 13 arguments are grouped together in the struct Elp args in ElpMpp02.h. They are
calculated in the subroutine
compute Elp arguments(double T, Elp paras paras, Elp args &args)
5
+series(elp pert.longT2) · T 2 + series(elp pert.longT3) · T 3 (23)
U = series(elp main.lat) + series(elp pert.latT0) + series(elp pert.latT1) · T
+series(elp pert.latT2) · T 2 (24)
r = ra0 · [series(elp main.dist) + series(elp pert.distT0) + series(elp pert.distT1) · T
+series(elp pert.distT2) · T 2 + series(elp pert.distT3) · T 3 ], (25)
Lunar geocentric rectangular coordinates (ecliptic and equinox of J2000.0) using parameters
fitted to LLR.
TDB Date, Time
TDB JD X (km) Y (km) Z (km)
(YYYY-MM-DD, HH:MM:SS)
2444269.5 1980-01-31, 00:00:00 -186813.01288 349310.13512 -19003.33883
2446269.7 1985-07-23, 04:48:00 -367970.07950 -45234.88375 20221.87153
2448269.9 1991-01-13, 09:36:00 -38942.82455 -403238.94206 -20800.77410
2450270.1 1996-07-05, 14:24:00 357372.04971 -89978.49535 14501.18831
2452270.3 2001-12-26, 19:12:00 252208.00739 294433.40162 -21940.36333
Lunar geocentric rectangular coordinates (ecliptic and equinox of J2000.0) using parameters
fitted to DE405/DE406.
TDB Date, Time
TDB JD X (km) Y (km) Z (km)
(YYYY-MM-DD, HH:MM:SS)
2521835.67 2192-06-13, 04:04:48 -184108.21468 345893.25529 30395.06868
2265621.33 1490-12-07, 19:55:12 -298024.37832 -213909.67132 -23263.21426
2009406.99 0789-06-16, 11:45:36 350041.24745 -201093.28987 1643.33539
1753192.65 0087-12-25, 03:36:00 90272.39894 351997.39617 13417.01712
1496978.31 -0614-07-03, 19:26:24 -403018.01560 -2639.93889 -28463.89733
6
More test cases can be generated by modifying the C++ code example.cpp or using this
JavaScript calculator.
(U ) (V ) (r)
where Aij , Aij , Aij are constant amplitudes once the adjustable parameters are chosen. The
(U ) (V ) (r)
phase angles φij , φij , φij are linear functions of 13 arguments (see Section 1.2).
I construct a truncated series by the following procedure:
(U ) (V ) (r)
• Choose four parameters Ath , Ath , Ath and τ .
(U ) (U ) (V ) (V ) (r) (r)
• Drop the terms in the series with Aij < Ath /τ i , Aij < Ath /τ i , and Aij < Ath /τ i .
(U ) (V ) (r)
It is clear that the smaller the parameters Ath , Ath , and Ath , the closer the truncated series
is to the original series. The parameter τ has a unit of time and should be chosen to cover the
time span of interest.
The truncation is implemented in the file ElpMpp trim.h by the subroutine
trim Elp coefs(Elp coefs &coefs, Elp coefs &coefs trim, double AthU, double AthV, double
AthR, double tau)
where coefs is a struct containing the coefficients of the full series. Coefficients of the truncated
series will be written to the struct coefs trim. This new struct can be passed to the function
getX2000() to compute the Moon’s position using the truncated series.
7
2
X
i
X (U )
∆Umax = Tmax |Aij | (33)
i=0 dropped
(U)
Aij
3
X
i
X (r)
∆rmax = Tmax |Aij |, (34)
i=0 dropped Aij
(r)
where Tmax = max(|T1 |, |T2 |). These estimated deviations are very conservative because in general
the phases in the terms are difference and the terms do not have the same sign. Root mean square
deviations may provide better estimates of typical deviations at any given time between T1 and
T2 :
v*
q u 3 3 +
u XX X X (q) (q) (q) (q)
rms(∆q) = h∆q 2 (T )i = u
t T i+j Aik Ajm sin φik (T ) sin φjm (T ) ,
i=0 j=0 dropped
(q)
Aik dropped
(q)
Ajm
(35)
where q = U, V, r and hi denotes time average. Assume that the time average of the cross terms
are small, which might not be true, the expression may be simplified to
v
T22i+1 − T12i+1
u 3
(q) 2
uX X
rms(∆q) ≈ u Aij , (36)
i=0 2(2i + 1)(T2 − T1 )
t
(q)
dropped Aij
where
3
(q) (q)
Tik
X X
∆qi = qfull series (Ti ) − qtruncated series (Ti ) = Akj sin φkj (Ti ). (40)
k=0 dropped
(q)
Akj
The crude error estimates from equations (32), (33), (34) and (36) are implemented in ElpMpp trim.h
in subroutine
trim Elp coefs errorEst(Elp coefs &coefs, Elp coefs &coefs trim, Elp coefs &coefs drop,
8
double AthU, double AthV, double AthR, double tau, double T1, double T2, devStats
&stats)
where coefs drop stores the dropped coefficients and devStats is a struct grouping the variables
for ∆qmax and rms(∆q).
The error estimate based on a Monte Carlo (MC) simulation is implemented in ElpMpp trim.h
in subroutine
error est(Elp coefs &coefs drop, Elp paras ¶s, int n, double T1, double T2, devStats
&errStats)
I set n = 10000 for a typical run to obtain decent statistics. It may take a while to complete
the simulation, depending on your processor speed. I use the rand() function in <cstdlib> to
generate random numbers. In my Linux g++ compiler, rand() generates pseudo random integers
between 0 and 2147483647. A seed is currently set using srand(4852618) in the code to ensure
reproducibility. It is not clear to me that rand()/2147483647 will produce random numbers
uniformly distributed between 0 and 1, but the result I get from using rand() seems to agree with
that obtained from pseudo random numbers generated by R’s runif() function, which generates
pseudo random numbers uniformly distributed between 0 and 1.
The following are examples of error estimates computed from the two subroutines.
In all cases, τ = 50, T1 = −50, T2 = 10 and parameters fitted to DE405/DE406 are used. N
is the number of terms in the truncated Elp/MPP02 series. ∆qmax and rms(∆q) (q = V, U, r) are
computed from equations (32), (33), (34) and (36).
(U ) (V ) (r)
Ath Ath Ath N ∆Vmax rms(∆V ) ∆Umax rms(∆U ) ∆rmax rms(∆r)
00 00
30 30 100 km 42 42200 45.400 20900 32.500 462 km 84.0 km
00 00 00 00 00
10 10 20 km 69 242 20.5 137 17.600 282 km 30.5 km
00 00 00 00 00 00
1 1 2 km 187 74 2.95 38.6 3.34 60.2 km 3.96 km
00 00 00 00 00 00
0.001 0.001 0.1 km 3759 1.47 0.016 0.80 0.015 16.3 km 0.42 km
Same as above, but ∆qmax and rms(∆q) are estimated by Monte Carlo simulations using
equations (38) and (39) with n = 10000. All ∆qmax and rms(∆q) are rounded to two significant
figures, which is about the accuracy of the estimates using n = 10000.
(U ) (V ) (r)
Ath Ath Ath N ∆Vmax rms(∆V ) ∆Umax rms(∆U ) ∆rmax rms(∆r)
00 00
30 30 100 km 42 23000 4800 15000 3400 340 km 86 km
00 00 00 00 00
10 10 20 km 69 100 21 98 1900 150 km 31 km
00 00 00 00 00 00
1 1 2 km 187 17 3.0 18 2.4 17 km 4.3 km
00 00 00 00 00 00
0.001 0.001 0.1 km 3759 0.093 0.016 0.058 0.012 2.0 km 0.42 km
Not surprisingly, ∆qmax calculated by (32), (33), (34) are always larger than those estimated
by MC, but the estimates for rms(∆q) by both methods turn out to be quite close for the cases
considered.
Note that the accuracy is estimated by comparing the truncated series to the full series. One
might want to compare the truncated series to other data such as JPL’s ephemerides. The Monte
Carlo subroutine can be modified to make that comparison. In the following, I show results
of comparison between the truncated series and JPL’s DE406 and DE431 in the time intervals
−50 < T < 10.
In all cases, τ = 50, T1 = −50, T2 = 10 and parameters fitted to DE405/DE406 are used. The
9
series is now compared to JPL’s DE406 using Monte Carlo method with n = 10000. The case
(U ) (V ) (r)
with Ath = Ath = Ath = 0 is the untruncated series.
(U ) (V ) (r)
Ath Ath Ath N ∆Vmax rms(∆V ) ∆Umax rms(∆U ) ∆rmax rms(∆r)
3000 3000 100 km 42 23000 4700 15000 3400 370 km 86 km
1000 1000 20 km 69 9700 2100 10000 1900 150 km 31 km
00 00 00 00 00
1 1 2 km 187 15 2.9 14 2.400 17 km 4.3 km
0.00100 0.00100 0.1 km 3759 3.500 0.5600 0.5900 0.1000 2.6 km 0.46 km
0 0 0 35901 3.500 0.5600 0.5900 0.1000 1.3 km 0.19 km
10
3 JavaScript Code Generation
JavaScript is convenient for HTML-based applications, such as my local star charts and equatorial
star charts pages. The file ElpMpp JavaScript.h contains C++ subroutines that can generate
JavaScript functions to compute a truncated ELP/MPP02 series. Instruction for the use of this
code is at the beginning of the file. The two main subroutines are
generate javascript code(const char* outfile, int corr, double AthU, double AthV, double
AthR, double tau, Elp paras ¶s, Elp coefs &coefs, const char* funSuffix)
and
generate javascript code min(const char* outfile, int corr, double AthU, double AthV,
double AthR, double tau, Elp paras ¶s, Elp coefs &coefs, const char *funSuffix)
outfile is file name of the js file that will be outputted. Characters in funSuffix will be
added to every JavaScript function. This is useful to prevent conflicts with code that imple-
ments other versions of the truncated series. The subroutine generate javascript code()
generates a human-readable js file. It is intended for your reference only. The subroutine
generate javascript code min() generates a minified version of the js file, in which comments
and unnecessary white spaces are stripped to optimize performance. The js files generated by the
two subroutines provide identical functions.
Unlike the C++ code generator, no data files will be outputted. The ELP/MPP02 series
are written expliticly in the outputted js file instead of using loops. JavaScript is an interpreted
language, not a compiled language. So it cannot take advantage of any loop parallization that may
be available through compilers. In addition, in the computation of phases such as in equation (4),
many of the i’s are zeros. When writing out the series explicitly, all the zero i’s are removed to
speed up computation. In fact, writing out the series explicitly may also benefit a C++ code,
especially when the truncated series contains less than 1000 terms. The subroutines above can be
modified easily to turn into a C++ code generator.
This JavaScript calculator uses two js files ElpMpp02LLR min.js and ElpMpp02DE min.js to
compute the ELP/MPP02 series. They are minified Javascript files generated using subroutines
(V ) (U ) (r)
in ElpMpp JavaScript.h by setting Ath = Ath = Ath = 0 and using parameters fitted to LLR
and DE405/DE406.
The C++ file example usingElpMpp JavaScript.cpp provides an example of using
ElpMpp JavaScript.h to generate JavaScript functions to compute a truncated ELP/MPP02
series.
11