elp-mpp02 0.0.3__py3-none-any.whl → 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- elp_mpp02/__init__.py +27 -0
- elp_mpp02/mpp02.py +649 -0
- elp_mpp02-0.0.5.dist-info/LICENCE +287 -0
- {elp_mpp02-0.0.3.dist-info → elp_mpp02-0.0.5.dist-info}/METADATA +9 -9
- elp_mpp02-0.0.5.dist-info/RECORD +7 -0
- {elp_mpp02-0.0.3.dist-info → elp_mpp02-0.0.5.dist-info}/WHEEL +1 -1
- elp_mpp02-0.0.5.dist-info/top_level.txt +1 -0
- elp_mpp02-0.0.3.dist-info/LICENCE +0 -674
- elp_mpp02-0.0.3.dist-info/RECORD +0 -5
- elp_mpp02-0.0.3.dist-info/top_level.txt +0 -1
elp_mpp02/__init__.py
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# SPDX-License-Identifier: EUPL-1.2
|
3
|
+
#
|
4
|
+
# Copyright (c) 2019-2025 Marc van der Sluys - Nikhef/Utrecht University - marc.vandersluys.nl
|
5
|
+
#
|
6
|
+
# This file is part of the evTool Python package:
|
7
|
+
# Analyse and display output from the binary stellar-evolution code ev (a.k.a. STARS or TWIN).
|
8
|
+
# See: https://github.com/MarcvdSluys/evTool
|
9
|
+
#
|
10
|
+
# This is free software: you can redistribute it and/or modify it under the terms of the European Union
|
11
|
+
# Public Licence 1.2 (EUPL 1.2). This software is distributed in the hope that it will be useful, but
|
12
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
13
|
+
# PURPOSE. See the EU Public Licence for more details. You should have received a copy of the European
|
14
|
+
# Union Public Licence along with this code. If not, see <https://www.eupl.eu/1.2/en/>.
|
15
|
+
|
16
|
+
|
17
|
+
"""Accurate Moon positions using the Lunar solution ELP/MPP02
|
18
|
+
|
19
|
+
This module uses the semi-analytical Lunar solution ELP2000/MPP02 to compute the geocentric position of the
|
20
|
+
Moon in the dynamical mean ecliptic and equinox of J2000. This Python code has been adapted from the Fortran
|
21
|
+
version in libTheSky.
|
22
|
+
|
23
|
+
"""
|
24
|
+
|
25
|
+
|
26
|
+
name = "elp-mpp02"
|
27
|
+
__author__ = 'Marc van der Sluys - Nikhef/Utrecht University - marc.vandersluys.nl'
|
elp_mpp02/mpp02.py
ADDED
@@ -0,0 +1,649 @@
|
|
1
|
+
"""Accurate Moon positions using the Lunar solution ELP/MPP02
|
2
|
+
|
3
|
+
This module uses the semi-analytical Lunar solution ELP2000/MPP02 to compute the geocentric position of the
|
4
|
+
Moon in the dynamical mean ecliptic and equinox of J2000. This Python code has been adapted from the Fortran
|
5
|
+
version in libTheSky.
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
Remarks:
|
10
|
+
|
11
|
+
The nominal values of some constants have to be corrected. There are two sets of corrections, one of which
|
12
|
+
can be chosen using the parameter 'mode' (used in e.g. initialise()):
|
13
|
+
|
14
|
+
- mode=0, the constants are fitted to LLR observations provided from 1970 to 2001 (default);
|
15
|
+
|
16
|
+
- mode=1, the constants are fitted to DE405 ephemeris over one century (1950-2060); the lunar angles W1, W2,
|
17
|
+
W3 receive also additive corrections to the secular coefficients. This is known as the 'historical mode'.
|
18
|
+
|
19
|
+
When the mode is changed, the constants will be reinitialised and the data file reread.
|
20
|
+
|
21
|
+
|
22
|
+
References:
|
23
|
+
|
24
|
+
- ELPdoc: Lunar solution ELP, version ELP/MPP02, Jean Chapront and Gerard Francou, October 2002
|
25
|
+
|
26
|
+
- Data files and Fortran code: ftp://cyrano-se.obspm.fr/pub/2_lunar_solutions/2_elpmpp02/
|
27
|
+
|
28
|
+
- Refereed article: Chapront J., Francou G., A&A 404, 735 (2003)
|
29
|
+
|
30
|
+
- libTheSky: https://libthesky.sourceforge.net/
|
31
|
+
|
32
|
+
|
33
|
+
Dependencies:
|
34
|
+
|
35
|
+
Apart from the standard Python modules math and sys, numpy and fortranformat must be installed.
|
36
|
+
|
37
|
+
|
38
|
+
Copyright:
|
39
|
+
|
40
|
+
Copyright (c) 2019-2025 Marc van der Sluys, Department of Physics, Utrecht University, The Netherlands
|
41
|
+
and Nikhef (Netherlands institute for high-energy physics and gravitational waves), Amsterdam, The Netherlands -
|
42
|
+
https://www.nikhef.nl/~sluys/ (this Python code)
|
43
|
+
|
44
|
+
This file is part of the ELP/MPP02 Python package,
|
45
|
+
see: https://pypi.org/project/elp_mpp02/ / https://github.com/MarcvdSluys/ELP-MPP02
|
46
|
+
|
47
|
+
This is free software: you can redistribute it and/or modify it under the terms of the European Union Public
|
48
|
+
Licence 1.2 (EUPL 1.2). This software is distributed in the hope that it will be useful, but WITHOUT ANY
|
49
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
50
|
+
EU Public Licence for more details. You should have received a copy of the European Union Public Licence
|
51
|
+
along with this code. If not, see <https://www.eupl.eu/1.2/en/>.
|
52
|
+
|
53
|
+
|
54
|
+
Acknowledgements:
|
55
|
+
- Thanks to A. Vähäkangas for bug reports.
|
56
|
+
|
57
|
+
"""
|
58
|
+
|
59
|
+
|
60
|
+
import math as m
|
61
|
+
import numpy.core as np
|
62
|
+
import sys
|
63
|
+
|
64
|
+
|
65
|
+
# Global constants:
|
66
|
+
d2r = m.radians(1) # Degrees to radians
|
67
|
+
r2d = m.degrees(1) # Radians to degrees
|
68
|
+
r2as = r2d*3600 # Radians to arcseconds
|
69
|
+
pi = m.pi
|
70
|
+
pi2 = pi*2
|
71
|
+
pio2 = pi/2
|
72
|
+
jd2000 = 2451545
|
73
|
+
|
74
|
+
|
75
|
+
# Global variables:
|
76
|
+
modeInit = 999 # := uninitialised
|
77
|
+
dataDir = '.' # Directory where the data files are located (default '.': the current directory)
|
78
|
+
|
79
|
+
nmpb = np.zeros((3,3))
|
80
|
+
cmpb = np.zeros(2645)
|
81
|
+
fmpb = np.zeros((5,2645))
|
82
|
+
nper = np.zeros((3,4,3))
|
83
|
+
cper = np.zeros(33256)
|
84
|
+
fper = np.zeros((5,33256))
|
85
|
+
|
86
|
+
w = np.zeros((3,5))
|
87
|
+
p1=0.;p2=0.;p3=0.;p4=0.;p5=0.; q1=0.;q2=0.;q3=0.;q4=0.;q5=0.
|
88
|
+
|
89
|
+
eart = np.zeros(5)
|
90
|
+
peri = np.zeros(5)
|
91
|
+
dela = np.zeros((4,5))
|
92
|
+
zeta = np.zeros(5)
|
93
|
+
p = np.zeros((8,5))
|
94
|
+
delnu=0.; dele=0.; delg=0.; delnp=0.; delep=0.; dtasm=0.; am=0.
|
95
|
+
|
96
|
+
|
97
|
+
def initialise_and_read_files(mode=0):
|
98
|
+
"""Initialise ELP/MPP02 constants and read the data files if necessary
|
99
|
+
|
100
|
+
Input parameters:
|
101
|
+
|
102
|
+
- mode: Index of the corrections to the constants: 0-Fit to LLR observations (default), 1-Fit to DE405
|
103
|
+
1950-2060 (historical)
|
104
|
+
|
105
|
+
"""
|
106
|
+
|
107
|
+
global modeInit
|
108
|
+
# print("Initialise and read files:", modeInit)
|
109
|
+
|
110
|
+
# Initializing of constants and reading the files:
|
111
|
+
ierr = 0
|
112
|
+
if mode!=modeInit:
|
113
|
+
initialise(mode)
|
114
|
+
ierr = read_files()
|
115
|
+
if ierr!=0: return ierr
|
116
|
+
|
117
|
+
modeInit = mode # Indicate that the data have been initialised
|
118
|
+
# print("modeInit:", modeInit)
|
119
|
+
return ierr
|
120
|
+
|
121
|
+
return ierr
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
def initialise(mode=0):
|
126
|
+
"""Initialization of the constants and parameters used for the evaluation of the ELP/MPP02 series
|
127
|
+
|
128
|
+
Input parameters:
|
129
|
+
|
130
|
+
- mode: Index of the corrections to the constants: 0-Fit to LLR observations (default), 1-Fit to DE405
|
131
|
+
1950-2060 (historical)
|
132
|
+
|
133
|
+
"""
|
134
|
+
|
135
|
+
|
136
|
+
global modeInit, w,eart,peri, dela,zeta, p,delnu,dele,delg,delnp,delep,dtasm,am
|
137
|
+
global p1,p2,p3,p4,p5, q1,q2,q3,q4,q5
|
138
|
+
# print("Initialise:", modeInit)
|
139
|
+
|
140
|
+
Dprec = -0.29965 # Constant for the correction to the constant of precession - source: IAU 2000A
|
141
|
+
|
142
|
+
bp = np.array([
|
143
|
+
[ 0.311079095, -0.103837907 ],
|
144
|
+
[ -0.4482398e-2, 0.668287e-3 ],
|
145
|
+
[ -0.1102485e-2, -0.1298072e-2 ],
|
146
|
+
[ 0.1056062e-2, -0.178028e-3 ],
|
147
|
+
[ 0.50928e-4, -0.37342e-4 ]
|
148
|
+
]) # (2,5)
|
149
|
+
|
150
|
+
if mode<0 or mode>1: sys.exit('elp_mpp02.mpp02.initialise(): mode must have value 0 or 1, not %i' % mode)
|
151
|
+
|
152
|
+
# Constants for the evaluation of the partial derivatives:
|
153
|
+
am = 0.074801329 # Ratio of the mean motions (EMB / Moon)
|
154
|
+
alpha = 0.002571881 # Ratio of the semi-major axis (Moon / EMB)
|
155
|
+
dtasm = (2*alpha)/(3*am) # (2*alpha) / (3*am)
|
156
|
+
xa = (2*alpha)/3
|
157
|
+
|
158
|
+
|
159
|
+
# Corrections to constants:
|
160
|
+
if mode==0: # LLR
|
161
|
+
# Values of the corrections to the constants fitted to LLR. Fit 13-05-02 (2 iterations) except Phi
|
162
|
+
# and eps w2_1 and w3_1. See ELPdoc, Table 3 and paper, Table 1
|
163
|
+
Dw1_0 = -0.10525
|
164
|
+
Dw2_0 = 0.16826
|
165
|
+
Dw3_0 = -0.10760
|
166
|
+
Deart_0 = -0.04012
|
167
|
+
Dperi = -0.04854
|
168
|
+
Dw1_1 = -0.32311
|
169
|
+
Dgam = 0.00069
|
170
|
+
De = 0.00005
|
171
|
+
Deart_1 = 0.01442
|
172
|
+
Dep = 0.00226
|
173
|
+
Dw2_1 = 0.08017
|
174
|
+
Dw3_1 = -0.04317
|
175
|
+
Dw1_2 = -0.03794
|
176
|
+
else: # DE 405 ('historical')
|
177
|
+
# Values of the corrections to the constants fitted to DE405 over the time interval (1950-2060)
|
178
|
+
Dw1_0 = -0.07008
|
179
|
+
Dw2_0 = 0.20794
|
180
|
+
Dw3_0 = -0.07215
|
181
|
+
Deart_0 = -0.00033
|
182
|
+
Dperi = -0.00749
|
183
|
+
Dw1_1 = -0.35106
|
184
|
+
Dgam = 0.00085
|
185
|
+
De = -0.00006
|
186
|
+
Deart_1 = 0.00732
|
187
|
+
Dep = 0.00224
|
188
|
+
Dw2_1 = 0.08017
|
189
|
+
Dw3_1 = -0.04317
|
190
|
+
Dw1_2 = -0.03743
|
191
|
+
|
192
|
+
# Fundamental arguments (Moon and EMB - ELPdoc, Table 1):
|
193
|
+
# W1: mean longitude of the Moon:
|
194
|
+
w[0,0] = elp_dms2rad(218,18,59.95571+Dw1_0) # Source: ELP - mean motion of the Moon (nu)
|
195
|
+
w[0,1] = (1732559343.73604+Dw1_1)/r2as # Source: ELP
|
196
|
+
w[0,2] = ( -6.8084 +Dw1_2)/r2as # Source: DE405
|
197
|
+
w[0,3] = 0.66040e-2/r2as # Source: ELP
|
198
|
+
w[0,4] = -0.31690e-4/r2as # Source: ELP
|
199
|
+
|
200
|
+
# W2: mean longitude of the lunar perigee:
|
201
|
+
w[1,0] = elp_dms2rad( 83,21,11.67475+Dw2_0) # Source: ELP
|
202
|
+
w[1,1] = ( 14643420.3171 +Dw2_1)/r2as # Source: DE405
|
203
|
+
w[1,2] = ( -38.2631)/r2as # Source: DE405
|
204
|
+
w[1,3] = -0.45047e-1/r2as # Source: ELP
|
205
|
+
w[1,4] = 0.21301e-3/r2as # Source: ELP
|
206
|
+
|
207
|
+
# W3: mean longitude of the lunar ascending node:
|
208
|
+
w[2,0] = elp_dms2rad(125, 2,40.39816+Dw3_0) # Source: ELP
|
209
|
+
w[2,1] = ( -6967919.5383 +Dw3_1)/r2as # Source: DE405
|
210
|
+
w[2,2] = 6.3590/r2as # Source: DE405
|
211
|
+
w[2,3] = 0.76250e-2/r2as # Source: ELP
|
212
|
+
w[2,4] = -0.35860e-4/r2as # Source: ELP
|
213
|
+
|
214
|
+
# Earth-Moon (EMB) elements:
|
215
|
+
# Te: mean longitude of EMB:
|
216
|
+
eart[0] = elp_dms2rad(100,27,59.13885+Deart_0) # Source: VSOP2000 - mean motion of EMB (n')
|
217
|
+
eart[1] = (129597742.29300 +Deart_1)/r2as # Source: VSOP2000
|
218
|
+
eart[2] = -0.020200/r2as # Source: ELP
|
219
|
+
eart[3] = 0.90000e-5/r2as # Source: ELP
|
220
|
+
eart[4] = 0.15000e-6/r2as # Source: ELP
|
221
|
+
|
222
|
+
# Pip: mean longitude of the perihelion of EMB:
|
223
|
+
peri[0] = elp_dms2rad(102,56,14.45766+Dperi) # Source: VSOP2000
|
224
|
+
peri[1] = 1161.24342/r2as # Source: VSOP2000
|
225
|
+
peri[2] = 0.529265/r2as # Source: VSOP2000
|
226
|
+
peri[3] = -0.11814e-3/r2as # Source: VSOP2000
|
227
|
+
peri[4] = 0.11379e-4/r2as # Source: VSOP2000
|
228
|
+
|
229
|
+
# Corrections to the secular terms of Moon angles. This gives a better (long-term?) fit
|
230
|
+
# to DE 406. See ELPdoc, Table 6/paper, Table 4, line 2:
|
231
|
+
if mode==1: # DE 405 / DE 406
|
232
|
+
w[0,3] -= 0.00018865/r2as
|
233
|
+
w[0,4] -= 0.00001024/r2as
|
234
|
+
|
235
|
+
w[1,2] += 0.00470602/r2as
|
236
|
+
w[1,3] -= 0.00025213/r2as
|
237
|
+
|
238
|
+
w[2,2] -= 0.00261070/r2as
|
239
|
+
w[2,3] -= 0.00010712/r2as
|
240
|
+
|
241
|
+
|
242
|
+
# Corrections to the mean motions of the Moon angles W2 and W3, infered from the modifications of the
|
243
|
+
# constants:
|
244
|
+
x2 = w[1,1] / w[0,1]
|
245
|
+
x3 = w[2,1] / w[0,1]
|
246
|
+
y2 = am*bp[0,0] + xa*bp[4,0]
|
247
|
+
y3 = am*bp[0,1] + xa*bp[4,1]
|
248
|
+
|
249
|
+
d21 = x2 - y2
|
250
|
+
d22 = w[0,1] * bp[1,0]
|
251
|
+
d23 = w[0,1] * bp[2,0]
|
252
|
+
d24 = w[0,1] * bp[3,0]
|
253
|
+
d25 = y2/am
|
254
|
+
|
255
|
+
d31 = x3 - y3
|
256
|
+
d32 = w[0,1] * bp[1,1]
|
257
|
+
d33 = w[0,1] * bp[2,1]
|
258
|
+
d34 = w[0,1] * bp[3,1]
|
259
|
+
d35 = y3/am
|
260
|
+
|
261
|
+
Cw2_1 = d21*Dw1_1+d25*Deart_1+d22*Dgam+d23*De+d24*Dep
|
262
|
+
Cw3_1 = d31*Dw1_1+d35*Deart_1+d32*Dgam+d33*De+d34*Dep
|
263
|
+
|
264
|
+
w[1,1] += Cw2_1/r2as
|
265
|
+
w[2,1] += Cw3_1/r2as
|
266
|
+
|
267
|
+
# Arguments of Delaunay:
|
268
|
+
for iD in range(5):
|
269
|
+
dela[0,iD] = w[0,iD] - eart[iD] # D = W1 - Te + 180 degrees
|
270
|
+
dela[1,iD] = w[0,iD] - w[2,iD] # F = W1 - W3
|
271
|
+
dela[2,iD] = w[0,iD] - w[1,iD] # l = W1 - W2 mean anomaly of the Moon
|
272
|
+
dela[3,iD] = eart[iD] - peri[iD] # l' = Te - Pip mean anomaly of EMB
|
273
|
+
|
274
|
+
dela[0,0] += pi
|
275
|
+
|
276
|
+
# Planetary arguments: mean longitudes for J2000 (from VSOP2000):
|
277
|
+
p[0,0] = elp_dms2rad(252, 15, 3.216919) # Mercury
|
278
|
+
p[1,0] = elp_dms2rad(181, 58, 44.758419) # Venus
|
279
|
+
p[2,0] = elp_dms2rad(100, 27, 59.138850) # EMB (eart(0))
|
280
|
+
p[3,0] = elp_dms2rad(355, 26, 3.642778) # Mars
|
281
|
+
p[4,0] = elp_dms2rad( 34, 21, 5.379392) # Jupiter
|
282
|
+
p[5,0] = elp_dms2rad( 50, 4, 38.902495) # Saturn
|
283
|
+
p[6,0] = elp_dms2rad(314, 3, 4.354234) # Uranus
|
284
|
+
p[7,0] = elp_dms2rad(304, 20, 56.808371) # Neptune
|
285
|
+
|
286
|
+
# Planetary arguments: mean motions (from VSOP2000):
|
287
|
+
p[0,1] = 538101628.66888/r2as # Mercury
|
288
|
+
p[1,1] = 210664136.45777/r2as # Venus
|
289
|
+
p[2,1] = 129597742.29300/r2as # EMB (eart(1))
|
290
|
+
p[3,1] = 68905077.65936/r2as # Mars
|
291
|
+
p[4,1] = 10925660.57335/r2as # Jupiter
|
292
|
+
p[5,1] = 4399609.33632/r2as # Saturn
|
293
|
+
p[6,1] = 1542482.57845/r2as # Uranus
|
294
|
+
p[7,1] = 786547.89700/r2as # Neptune
|
295
|
+
|
296
|
+
p[0:8,2:5] = 0
|
297
|
+
|
298
|
+
|
299
|
+
# Mean longitude of the Moon W1 + Rate of precession (pt):
|
300
|
+
zeta[0] = w[0,0]
|
301
|
+
zeta[1] = w[0,1] + (5029.0966+Dprec)/r2as
|
302
|
+
zeta[2] = w[0,2]
|
303
|
+
zeta[3] = w[0,3]
|
304
|
+
zeta[4] = w[0,4]
|
305
|
+
|
306
|
+
# Corrections to the parameters: Nu, E, Gamma, n' et e' (Source: ELP):
|
307
|
+
delnu = (+0.55604+Dw1_1)/r2as/w[0,1] # Correction to the mean motion of the Moon
|
308
|
+
dele = (+0.01789+De)/r2as # Correction to the half coefficient of sin(l) in longitude
|
309
|
+
delg = (-0.08066+Dgam)/r2as # Correction to the half coefficient of sin(F) in latitude
|
310
|
+
delnp = (-0.06424+Deart_1)/r2as/w[0,1] # Correction to the mean motion of EMB
|
311
|
+
delep = (-0.12879+Dep)/r2as # Correction to the eccentricity of EMB
|
312
|
+
|
313
|
+
# Precession of the longitude of the ascending node of the mean ecliptic of date on fixed ecliptic J2000
|
314
|
+
# (Laskar, 1986):
|
315
|
+
# P: sine coefficients:
|
316
|
+
p1 = 0.10180391e-4
|
317
|
+
p2 = 0.47020439e-6
|
318
|
+
p3 = -0.5417367e-9
|
319
|
+
p4 = -0.2507948e-11
|
320
|
+
p5 = 0.463486e-14
|
321
|
+
|
322
|
+
# Q: cosine coefficients:
|
323
|
+
q1 = -0.113469002e-3
|
324
|
+
q2 = 0.12372674e-6
|
325
|
+
q3 = 0.1265417e-8
|
326
|
+
q4 = -0.1371808e-11
|
327
|
+
q5 = -0.320334e-14
|
328
|
+
|
329
|
+
return
|
330
|
+
|
331
|
+
|
332
|
+
def read_files():
|
333
|
+
"""Read the six data files containing the ELP/MPP02 series
|
334
|
+
|
335
|
+
Return values:
|
336
|
+
|
337
|
+
- ierr: File error index: ierr=0: no error, ierr=1: file error
|
338
|
+
|
339
|
+
"""
|
340
|
+
|
341
|
+
# print("Read files:")
|
342
|
+
global nmpb,cmpb,fmpb, nper,cper,fper
|
343
|
+
global w,eart,peri, dela,zeta, p,delnu,dele,delg,delnp,delep,dtasm,am
|
344
|
+
|
345
|
+
# Read the Main Problem series:
|
346
|
+
ir = 0
|
347
|
+
ilu = np.zeros(4) # will contain ints
|
348
|
+
a = 0.
|
349
|
+
b = np.zeros(5)
|
350
|
+
# ierr=1
|
351
|
+
# nerr=0
|
352
|
+
|
353
|
+
import fortranformat as ff
|
354
|
+
formatMainHeader = ff.FortranRecordReader('(25x,I10)') # Block header format
|
355
|
+
formatMainBody = ff.FortranRecordReader('(4I3,2x,F13.5,5F12.2)') # Block body format
|
356
|
+
|
357
|
+
|
358
|
+
for iFile in range(3): # Main-problem files 1-3
|
359
|
+
fileName = dataDir+'/ELP_MAIN.S'+str(iFile+1)
|
360
|
+
try:
|
361
|
+
inFile = open(fileName,'r')
|
362
|
+
except Exception as err:
|
363
|
+
sys.stderr.write(str(err)+'\n\n')
|
364
|
+
sys.stderr.write('Please ensure that:\n')
|
365
|
+
sys.stderr.write(' 1) you downloaded the data files ELP_*.S[123] from '+
|
366
|
+
'ftp://cyrano-se.obspm.fr/pub/2_lunar_solutions/2_elpmpp02/\n')
|
367
|
+
sys.stderr.write(' 2) you set the variable mpp.dataDir to the correct value\n')
|
368
|
+
exit(1)
|
369
|
+
|
370
|
+
line = inFile.readline()
|
371
|
+
nmpb[iFile,0] = formatMainHeader.read(line)[0]
|
372
|
+
# if nerr!=0: return 3
|
373
|
+
|
374
|
+
nmpb[iFile,1] = ir+1
|
375
|
+
nmpb[iFile,2] = nmpb[iFile,0] + nmpb[iFile,1] - 1
|
376
|
+
|
377
|
+
nLines = int(round(nmpb[iFile,0]))
|
378
|
+
for iLine in range(nLines):
|
379
|
+
line = inFile.readline()
|
380
|
+
ilu[0],ilu[1],ilu[2],ilu[3], a, b[0],b[1],b[2],b[3],b[4] = formatMainBody.read(line)
|
381
|
+
# if nerr!=0: return 4
|
382
|
+
|
383
|
+
tgv = b[0] + dtasm*b[4]
|
384
|
+
if iFile==2: a -= 2*a*delnu/3
|
385
|
+
cmpb[ir] = a + tgv*(delnp-am*delnu) + b[1]*delg + b[2]*dele + b[3]*delep
|
386
|
+
|
387
|
+
for k in range(5):
|
388
|
+
fmpb[k,ir] = 0
|
389
|
+
for i in range(4):
|
390
|
+
fmpb[k,ir] += ilu[i] * dela[i,k]
|
391
|
+
|
392
|
+
if iFile==2: fmpb[0,ir] += pio2
|
393
|
+
ir += 1
|
394
|
+
|
395
|
+
inFile.close()
|
396
|
+
|
397
|
+
|
398
|
+
# Read the Perturbations series:
|
399
|
+
ir = 0
|
400
|
+
ipt = 0
|
401
|
+
icount = 0
|
402
|
+
s = 0.0
|
403
|
+
c = 0.0
|
404
|
+
ifi = np.zeros(16) # will contain ints
|
405
|
+
|
406
|
+
formatPertHeader = ff.FortranRecordReader('(25x,2I10)') # Perturbation header format
|
407
|
+
formatPertBody = ff.FortranRecordReader('(I5,2D20.13,16I3)') # Perturbation body format
|
408
|
+
|
409
|
+
for iFile in range(3): # Perturbation files 1-3
|
410
|
+
fileName = dataDir+'/ELP_PERT.S'+str(iFile+1)
|
411
|
+
try:
|
412
|
+
inFile = open(fileName,'r')
|
413
|
+
except Exception as err:
|
414
|
+
sys.stderr.write(str(err)+'\n')
|
415
|
+
exit(1)
|
416
|
+
|
417
|
+
for it in range(4):
|
418
|
+
# if nerr!=0: return 6
|
419
|
+
line = inFile.readline()
|
420
|
+
nper[iFile,it,0],ipt = formatPertHeader.read(line)
|
421
|
+
|
422
|
+
nper[iFile,it,1] = ir+1
|
423
|
+
nper[iFile,it,2] = nper[iFile,it,0] + nper[iFile,it,1] - 1
|
424
|
+
if nper[iFile,it,0]==0: continue # cycle to next it
|
425
|
+
|
426
|
+
nLines = int(round(nper[iFile,it,0]))
|
427
|
+
for iLine in range(nLines):
|
428
|
+
line = inFile.readline()
|
429
|
+
( icount,s,c,ifi[0],ifi[1],ifi[2],ifi[3],ifi[4],ifi[5],ifi[6],ifi[7],ifi[8],ifi[9],ifi[10],
|
430
|
+
ifi[11],ifi[12],ifi[13],ifi[14],ifi[15] ) = formatPertBody.read(line)
|
431
|
+
# if nerr!=0: return 7
|
432
|
+
|
433
|
+
cper[ir] = m.sqrt(c**2+s**2)
|
434
|
+
pha = m.atan2(c,s)
|
435
|
+
if pha<0: pha = pha+pi2
|
436
|
+
|
437
|
+
for k in range(5):
|
438
|
+
fper[k,ir] = 0
|
439
|
+
if k==0: fper[k,ir] = pha
|
440
|
+
for i in range(4):
|
441
|
+
fper[k,ir] += ifi[i] * dela[i,k]
|
442
|
+
|
443
|
+
for i in range(4,12):
|
444
|
+
fper[k,ir] += ifi[i] * p[i-4,k]
|
445
|
+
|
446
|
+
fper[k,ir] += ifi[12] * zeta[k]
|
447
|
+
ir = ir+1
|
448
|
+
|
449
|
+
inFile.close()
|
450
|
+
|
451
|
+
return 0
|
452
|
+
|
453
|
+
|
454
|
+
|
455
|
+
def elp_dms2rad(deg,min,sec):
|
456
|
+
"""Function for the conversion sexagesimal degrees -> radians in initialise()"""
|
457
|
+
|
458
|
+
return (deg+min/60+sec/3600) * d2r
|
459
|
+
|
460
|
+
|
461
|
+
|
462
|
+
def compute_lbr(jd, mode=0):
|
463
|
+
"""Compute the spherical lunar coordinates using the ELP2000/MPP02 lunar theory in the dynamical mean ecliptic
|
464
|
+
and equinox of J2000.
|
465
|
+
|
466
|
+
Input parameters:
|
467
|
+
|
468
|
+
- jd: Julian day to compute Moon position for
|
469
|
+
|
470
|
+
- mode: Index of the corrections to the constants: 0-Fit to LLR observations (default), 1-Fit to DE405
|
471
|
+
1950-2060 (historical)
|
472
|
+
|
473
|
+
Return values:
|
474
|
+
|
475
|
+
- lon: Ecliptic longitude (rad)
|
476
|
+
|
477
|
+
- lat: Ecliptic latitude (rad)
|
478
|
+
|
479
|
+
- rad: Distance (km)
|
480
|
+
|
481
|
+
"""
|
482
|
+
|
483
|
+
# print("Compute lbr:")
|
484
|
+
|
485
|
+
xyz,vxyz, ierr = compute_xyz(jd, mode)
|
486
|
+
|
487
|
+
# Compute ecliptic l,b,r:
|
488
|
+
rad = m.sqrt(sum(xyz**2))
|
489
|
+
lon = m.atan2(xyz[1], xyz[0])
|
490
|
+
lat = m.asin(xyz[2]/rad)
|
491
|
+
|
492
|
+
# rad = rad/1.49597870700e8 # km -> AU
|
493
|
+
|
494
|
+
# print('jd, xyz: ', jd, xyz[0:3])
|
495
|
+
# print(jd, (lon%pi2)*r2d, lat*r2d, rad)
|
496
|
+
|
497
|
+
return lon,lat,rad
|
498
|
+
|
499
|
+
|
500
|
+
|
501
|
+
def compute_xyz(jd, mode=0):
|
502
|
+
"""Compute the rectangular lunar coordinates using the ELP/MPP02 lunar theory in the dynamical mean ecliptic
|
503
|
+
and equinox of J2000.
|
504
|
+
|
505
|
+
Input parameters:
|
506
|
+
|
507
|
+
- jd: Julian day to compute Moon position for
|
508
|
+
|
509
|
+
- mode: Index of the corrections to the constants: 0-Fit to LLR observations, 1-Fit to DE405 1950-2060
|
510
|
+
(historical)
|
511
|
+
|
512
|
+
Return value:
|
513
|
+
|
514
|
+
- xyz(3): Geocentric rectangular coordinates (km)
|
515
|
+
|
516
|
+
- vxyz(3): Geocentric rectangular velocities (km/day):
|
517
|
+
|
518
|
+
- ierr: File error index - ierr=0: no error, ierr=1: file error
|
519
|
+
|
520
|
+
"""
|
521
|
+
|
522
|
+
# print("Compute xyz:")
|
523
|
+
global nmpb,cmpb,fmpb, nper,cper,fper
|
524
|
+
global w, p1,p2,p3,p4,p5, q1,q2,q3,q4,q5
|
525
|
+
|
526
|
+
# Constants:
|
527
|
+
a405 = 384747.9613701725 # Moon mean distance for DE405
|
528
|
+
aelp = 384747.980674318 # Moon mean distance for ELP
|
529
|
+
sc = 36525 # Julian century in days
|
530
|
+
|
531
|
+
# Initialise data and read files if needed:
|
532
|
+
ierr = initialise_and_read_files(mode)
|
533
|
+
if ierr!=0: sys.exit('Could not read ELP-MPP02 files')
|
534
|
+
|
535
|
+
|
536
|
+
# Initialization of time powers:
|
537
|
+
rjd = jd - jd2000 # Reduced JD - JD since 2000
|
538
|
+
t = np.zeros(5)
|
539
|
+
t[0] = 1
|
540
|
+
t[1] = rjd/sc # t: time since 2000 in Julian centuries
|
541
|
+
t[2] = t[1]**2 # t^2
|
542
|
+
t[3] = t[2]*t[1] # t^3
|
543
|
+
t[4] = t[2]**2 # t^4
|
544
|
+
|
545
|
+
# Evaluation of the series: substitution of time in the series
|
546
|
+
v = np.zeros(6)
|
547
|
+
for iVar in range(3): # iVar=0,1,2: Longitude, Latitude, Distance
|
548
|
+
|
549
|
+
# Main Problem series:
|
550
|
+
nLineStart = int(round(nmpb[iVar,1]))
|
551
|
+
nLineEnd = int(round(nmpb[iVar,2]))
|
552
|
+
for iLine in range(nLineStart-1, nLineEnd):
|
553
|
+
x = cmpb[iLine]
|
554
|
+
y = fmpb[0,iLine]
|
555
|
+
yp = 0
|
556
|
+
|
557
|
+
for k in range(1,5): # k=1,4
|
558
|
+
y += fmpb[k,iLine] * t[k]
|
559
|
+
yp += k*fmpb[k,iLine] * t[k-1]
|
560
|
+
|
561
|
+
v[iVar] += x * m.sin(y)
|
562
|
+
v[iVar+3] += x * yp * m.cos(y)
|
563
|
+
|
564
|
+
|
565
|
+
# Perturbations series:
|
566
|
+
for it in range(4):
|
567
|
+
nLineStart = int(round(nper[iVar,it,1]))
|
568
|
+
nLineEnd = int(round(nper[iVar,it,2]))
|
569
|
+
for iLine in range(nLineStart-1, nLineEnd):
|
570
|
+
x = cper[iLine]
|
571
|
+
y = fper[0,iLine]
|
572
|
+
xp = 0
|
573
|
+
yp = 0
|
574
|
+
if it!=0: xp = it * x * t[it-1]
|
575
|
+
|
576
|
+
for k in range(1,5): # k=1,4
|
577
|
+
y += fper[k,iLine] * t[k]
|
578
|
+
yp += k * fper[k,iLine] * t[k-1]
|
579
|
+
|
580
|
+
v[iVar] += x * t[it] * m.sin(y)
|
581
|
+
v[iVar+3] += xp * m.sin(y) + x * t[it] * yp * m.cos(y)
|
582
|
+
|
583
|
+
|
584
|
+
# Compute the spherical coordinates for the mean inertial ecliptic and equinox of date:
|
585
|
+
v[0] = v[0]/r2as + w[0,0] + w[0,1]*t[1] + w[0,2]*t[2] + w[0,3]*t[3] + w[0,4]*t[4] # Longitude + mean lon. (rad)
|
586
|
+
v[1] = v[1]/r2as # Latitude (rad)
|
587
|
+
v[2] = v[2] * a405 / aelp # Distance (km)
|
588
|
+
|
589
|
+
# v[0] = v[0] % pi2
|
590
|
+
|
591
|
+
# print('t: ', t[0],t[1],t[2],t[3],t[4])
|
592
|
+
# print('v: ', v[0]*r2d,v[1]*r2d,v[2], v[3],v[4],v[5])
|
593
|
+
|
594
|
+
# compute the rectangular coordinates (for the EoD?):
|
595
|
+
clamb = m.cos(v[0])
|
596
|
+
slamb = m.sin(v[0])
|
597
|
+
cbeta = m.cos(v[1])
|
598
|
+
sbeta = m.sin(v[1])
|
599
|
+
cw = v[2]*cbeta
|
600
|
+
sw = v[2]*sbeta
|
601
|
+
# print("c/s l/b: ", clamb,slamb, cbeta,sbeta)
|
602
|
+
|
603
|
+
x0 = cw*clamb
|
604
|
+
x1 = cw*slamb
|
605
|
+
x2 = sw
|
606
|
+
# print("x1,x2,x3: ", x0,x1,x2)
|
607
|
+
# print("p,q: ", p1,p2,p3,p4,p5, q1,q2,q3,q4,q5)
|
608
|
+
|
609
|
+
# Is this simply precession in rectangular coordinates to J2000? From?
|
610
|
+
pw = (p1 + p2*t[1] + p3*t[2] + p4*t[3] + p5*t[4]) * t[1]
|
611
|
+
qw = (q1 + q2*t[1] + q3*t[2] + q4*t[3] + q5*t[4]) * t[1]
|
612
|
+
|
613
|
+
ra = 2*m.sqrt(1 - pw**2 - qw**2)
|
614
|
+
pwqw = 2*pw*qw
|
615
|
+
pw2 = 1 - 2*pw**2
|
616
|
+
qw2 = 1 - 2*qw**2
|
617
|
+
pwra = pw*ra
|
618
|
+
qwra = qw*ra
|
619
|
+
|
620
|
+
xyz = np.zeros(3)
|
621
|
+
xyz[0] = pw2*x0 + pwqw*x1 + pwra*x2
|
622
|
+
xyz[1] = pwqw*x0 + qw2*x1 - qwra*x2
|
623
|
+
xyz[2] = -pwra*x0 + qwra*x1 + (pw2+qw2-1)*x2
|
624
|
+
|
625
|
+
|
626
|
+
# Compute the rectangular velocities for the equinox J2000:
|
627
|
+
v[3] = v[3]/r2as + w[0,1] + 2*w[0,2]*t[1] + 3*w[0,3]*t[2] + 4*w[0,4]*t[3]
|
628
|
+
v[4] = v[4]/r2as
|
629
|
+
|
630
|
+
xp1 = (v[5]*cbeta - v[4]*sw)*clamb - v[3]*x1
|
631
|
+
xp2 = (v[5]*cbeta - v[4]*sw)*slamb + v[3]*x0
|
632
|
+
xp3 = v[5]*sbeta + v[4]*cw
|
633
|
+
|
634
|
+
ppw = p1 + (2*p2 + 3*p3*t[1] + 4*p4*t[2] + 5*p5*t[3]) * t[1]
|
635
|
+
qpw = q1 + (2*q2 + 3*q3*t[1] + 4*q4*t[2] + 5*q5*t[3]) * t[1]
|
636
|
+
ppw2 = -4*pw*ppw
|
637
|
+
qpw2 = -4*qw*qpw
|
638
|
+
ppwqpw = 2*(ppw*qw + pw*qpw)
|
639
|
+
rap = (ppw2+qpw2)/ra
|
640
|
+
ppwra = ppw*ra + pw*rap
|
641
|
+
qpwra = qpw*ra + qw*rap
|
642
|
+
|
643
|
+
vxyz = np.zeros(3)
|
644
|
+
vxyz[0] = (pw2*xp1 + pwqw*xp2 + pwra*xp3 + ppw2*x0 + ppwqpw*x1 + ppwra*x2) / sc
|
645
|
+
vxyz[1] = (pwqw*xp1 + qw2*xp2 - qwra*xp3 + ppwqpw*x0 + qpw2*x1 - qpwra*x2) / sc
|
646
|
+
vxyz[2] = (-pwra*xp1 + qwra*xp2 + (pw2+qw2-1)*xp3 - ppwra*x0 + qpwra*x1 + (ppw2+qpw2)*x2) / sc
|
647
|
+
|
648
|
+
return xyz,vxyz, ierr
|
649
|
+
|