line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* |
2
|
|
|
|
|
|
|
*+ |
3
|
|
|
|
|
|
|
* Name: |
4
|
|
|
|
|
|
|
* palUe2pv |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
* Purpose: |
7
|
|
|
|
|
|
|
* Heliocentric position and velocity of a planet, asteroid or comet, from universal elements |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
* Language: |
10
|
|
|
|
|
|
|
* Starlink ANSI C |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
* Type of Module: |
13
|
|
|
|
|
|
|
* Library routine |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
* Invocation: |
16
|
|
|
|
|
|
|
* void palUe2pv( double date, double u[13], double pv[6], int *jstat ); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
* Arguments: |
19
|
|
|
|
|
|
|
* date = double (Given) |
20
|
|
|
|
|
|
|
* TT Modified Julian date (JD-2400000.5). |
21
|
|
|
|
|
|
|
* u = double [13] (Given & Returned) |
22
|
|
|
|
|
|
|
* Universal orbital elements (updated, see note 1) |
23
|
|
|
|
|
|
|
* given (0) combined mass (M+m) |
24
|
|
|
|
|
|
|
* " (1) total energy of the orbit (alpha) |
25
|
|
|
|
|
|
|
* " (2) reference (osculating) epoch (t0) |
26
|
|
|
|
|
|
|
* " (3-5) position at reference epoch (r0) |
27
|
|
|
|
|
|
|
* " (6-8) velocity at reference epoch (v0) |
28
|
|
|
|
|
|
|
* " (9) heliocentric distance at reference epoch |
29
|
|
|
|
|
|
|
* " (10) r0.v0 |
30
|
|
|
|
|
|
|
* returned (11) date (t) |
31
|
|
|
|
|
|
|
* " (12) universal eccentric anomaly (psi) of date |
32
|
|
|
|
|
|
|
* pv = double [6] (Returned) |
33
|
|
|
|
|
|
|
* Position (AU) and velocity (AU/s) |
34
|
|
|
|
|
|
|
* jstat = int * (Returned) |
35
|
|
|
|
|
|
|
* status: 0 = OK |
36
|
|
|
|
|
|
|
* -1 = radius vector zero |
37
|
|
|
|
|
|
|
* -2 = failed to converge |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
* Description: |
40
|
|
|
|
|
|
|
* Heliocentric position and velocity of a planet, asteroid or comet, |
41
|
|
|
|
|
|
|
* starting from orbital elements in the "universal variables" form. |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
* Authors: |
44
|
|
|
|
|
|
|
* PTW: Pat Wallace (STFC) |
45
|
|
|
|
|
|
|
* TIMJ: Tim Jenness (JAC, Hawaii) |
46
|
|
|
|
|
|
|
* {enter_new_authors_here} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
* Notes: |
49
|
|
|
|
|
|
|
* - The "universal" elements are those which define the orbit for the |
50
|
|
|
|
|
|
|
* purposes of the method of universal variables (see reference). |
51
|
|
|
|
|
|
|
* They consist of the combined mass of the two bodies, an epoch, |
52
|
|
|
|
|
|
|
* and the position and velocity vectors (arbitrary reference frame) |
53
|
|
|
|
|
|
|
* at that epoch. The parameter set used here includes also various |
54
|
|
|
|
|
|
|
* quantities that can, in fact, be derived from the other |
55
|
|
|
|
|
|
|
* information. This approach is taken to avoiding unnecessary |
56
|
|
|
|
|
|
|
* computation and loss of accuracy. The supplementary quantities |
57
|
|
|
|
|
|
|
* are (i) alpha, which is proportional to the total energy of the |
58
|
|
|
|
|
|
|
* orbit, (ii) the heliocentric distance at epoch, (iii) the |
59
|
|
|
|
|
|
|
* outwards component of the velocity at the given epoch, (iv) an |
60
|
|
|
|
|
|
|
* estimate of psi, the "universal eccentric anomaly" at a given |
61
|
|
|
|
|
|
|
* date and (v) that date. |
62
|
|
|
|
|
|
|
* - The companion routine is palEl2ue. This takes the conventional |
63
|
|
|
|
|
|
|
* orbital elements and transforms them into the set of numbers |
64
|
|
|
|
|
|
|
* needed by the present routine. A single prediction requires one |
65
|
|
|
|
|
|
|
* one call to palEl2ue followed by one call to the present routine; |
66
|
|
|
|
|
|
|
* for convenience, the two calls are packaged as the routine |
67
|
|
|
|
|
|
|
* palPlanel. Multiple predictions may be made by again |
68
|
|
|
|
|
|
|
* calling palEl2ue once, but then calling the present routine |
69
|
|
|
|
|
|
|
* multiple times, which is faster than multiple calls to palPlanel. |
70
|
|
|
|
|
|
|
* - It is not obligatory to use palEl2ue to obtain the parameters. |
71
|
|
|
|
|
|
|
* However, it should be noted that because palEl2ue performs its |
72
|
|
|
|
|
|
|
* own validation, no checks on the contents of the array U are made |
73
|
|
|
|
|
|
|
* by the present routine. |
74
|
|
|
|
|
|
|
* - DATE is the instant for which the prediction is required. It is |
75
|
|
|
|
|
|
|
* in the TT timescale (formerly Ephemeris Time, ET) and is a |
76
|
|
|
|
|
|
|
* Modified Julian Date (JD-2400000.5). |
77
|
|
|
|
|
|
|
* - The universal elements supplied in the array U are in canonical |
78
|
|
|
|
|
|
|
* units (solar masses, AU and canonical days). The position and |
79
|
|
|
|
|
|
|
* velocity are not sensitive to the choice of reference frame. The |
80
|
|
|
|
|
|
|
* palEl2ue routine in fact produces coordinates with respect to the |
81
|
|
|
|
|
|
|
* J2000 equator and equinox. |
82
|
|
|
|
|
|
|
* - The algorithm was originally adapted from the EPHSLA program of |
83
|
|
|
|
|
|
|
* D.H.P.Jones (private communication, 1996). The method is based |
84
|
|
|
|
|
|
|
* on Stumpff's Universal Variables. |
85
|
|
|
|
|
|
|
* - Reference: Everhart, E. & Pitkin, E.T., Am.J.Phys. 51, 712, 1983. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
* History: |
88
|
|
|
|
|
|
|
* 2012-03-09 (TIMJ): |
89
|
|
|
|
|
|
|
* Initial version cloned from SLA/F. |
90
|
|
|
|
|
|
|
* Adapted with permission from the Fortran SLALIB library. |
91
|
|
|
|
|
|
|
* {enter_further_changes_here} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
* Copyright: |
94
|
|
|
|
|
|
|
* Copyright (C) 2005 Rutherford Appleton Laboratory |
95
|
|
|
|
|
|
|
* Copyright (C) 2012 Science and Technology Facilities Council. |
96
|
|
|
|
|
|
|
* All Rights Reserved. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
* Licence: |
99
|
|
|
|
|
|
|
* This program is free software; you can redistribute it and/or |
100
|
|
|
|
|
|
|
* modify it under the terms of the GNU General Public License as |
101
|
|
|
|
|
|
|
* published by the Free Software Foundation; either version 3 of |
102
|
|
|
|
|
|
|
* the License, or (at your option) any later version. |
103
|
|
|
|
|
|
|
* |
104
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be |
105
|
|
|
|
|
|
|
* useful, but WITHOUT ANY WARRANTY; without even the implied |
106
|
|
|
|
|
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
107
|
|
|
|
|
|
|
* PURPOSE. See the GNU General Public License for more details. |
108
|
|
|
|
|
|
|
* |
109
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License |
110
|
|
|
|
|
|
|
* along with this program; if not, write to the Free Software |
111
|
|
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
112
|
|
|
|
|
|
|
* MA 02110-1301, USA. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
* Bugs: |
115
|
|
|
|
|
|
|
* {note_any_bugs_here} |
116
|
|
|
|
|
|
|
*- |
117
|
|
|
|
|
|
|
*/ |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
#include |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
#include "pal.h" |
122
|
|
|
|
|
|
|
#include "palmac.h" |
123
|
|
|
|
|
|
|
|
124
|
2102
|
|
|
|
|
|
void palUe2pv( double date, double u[13], double pv[6], int *jstat ) { |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
/* Canonical days to seconds */ |
127
|
|
|
|
|
|
|
const double CD2S = PAL__GCON / PAL__SPD; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
/* Test value for solution and maximum number of iterations */ |
130
|
|
|
|
|
|
|
const double TEST = 1e-13; |
131
|
|
|
|
|
|
|
const int NITMAX = 25; |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
int I, NIT, N; |
134
|
|
|
|
|
|
|
double CM,ALPHA,T0,P0[3],V0[3],R0,SIGMA0,T,PSI,DT,W, |
135
|
|
|
|
|
|
|
TOL,PSJ,PSJ2,BETA,S0,S1,S2,S3, |
136
|
|
|
|
|
|
|
FF,R,F,G,FD,GD; |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
double PLAST = 0.0; |
139
|
|
|
|
|
|
|
double FLAST = 0.0; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
/* Unpack the parameters. */ |
142
|
2102
|
|
|
|
|
|
CM = u[0]; |
143
|
2102
|
|
|
|
|
|
ALPHA = u[1]; |
144
|
2102
|
|
|
|
|
|
T0 = u[2]; |
145
|
8408
|
100
|
|
|
|
|
for (I=0; I<3; I++) { |
146
|
6306
|
|
|
|
|
|
P0[I] = u[I+3]; |
147
|
6306
|
|
|
|
|
|
V0[I] = u[I+6]; |
148
|
|
|
|
|
|
|
} |
149
|
2102
|
|
|
|
|
|
R0 = u[9]; |
150
|
2102
|
|
|
|
|
|
SIGMA0 = u[10]; |
151
|
2102
|
|
|
|
|
|
T = u[11]; |
152
|
2102
|
|
|
|
|
|
PSI = u[12]; |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
/* Approximately update the universal eccentric anomaly. */ |
155
|
2102
|
|
|
|
|
|
PSI = PSI+(date-T)*PAL__GCON/R0; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
/* Time from reference epoch to date (in Canonical Days: a canonical |
158
|
|
|
|
|
|
|
* day is 58.1324409... days, defined as 1/PAL__GCON). */ |
159
|
2102
|
|
|
|
|
|
DT = (date-T0)*PAL__GCON; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
/* Refine the universal eccentric anomaly, psi. */ |
162
|
|
|
|
|
|
|
NIT = 1; |
163
|
|
|
|
|
|
|
W = 1.0; |
164
|
|
|
|
|
|
|
TOL = 0.0; |
165
|
8402
|
100
|
|
|
|
|
while (fabs(W) >= TOL) { |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
/* Form half angles until BETA small enough. */ |
168
|
|
|
|
|
|
|
N = 0; |
169
|
|
|
|
|
|
|
PSJ = PSI; |
170
|
6300
|
|
|
|
|
|
PSJ2 = PSJ*PSJ; |
171
|
6300
|
|
|
|
|
|
BETA = ALPHA*PSJ2; |
172
|
7836
|
100
|
|
|
|
|
while (fabs(BETA) > 0.7) { |
173
|
1536
|
|
|
|
|
|
N = N+1; |
174
|
1536
|
|
|
|
|
|
BETA = BETA/4.0; |
175
|
1536
|
|
|
|
|
|
PSJ = PSJ/2.0; |
176
|
1536
|
|
|
|
|
|
PSJ2 = PSJ2/4.0; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
/* Calculate Universal Variables S0,S1,S2,S3 by nested series. */ |
180
|
12600
|
|
|
|
|
|
S3 = PSJ*PSJ2*((((((BETA/210.0+1.0) |
181
|
6300
|
|
|
|
|
|
*BETA/156.0+1.0) |
182
|
6300
|
|
|
|
|
|
*BETA/110.0+1.0) |
183
|
6300
|
|
|
|
|
|
*BETA/72.0+1.0) |
184
|
6300
|
|
|
|
|
|
*BETA/42.0+1.0) |
185
|
6300
|
|
|
|
|
|
*BETA/20.0+1.0)/6.0; |
186
|
12600
|
|
|
|
|
|
S2 = PSJ2*((((((BETA/182.0+1.0) |
187
|
6300
|
|
|
|
|
|
*BETA/132.0+1.0) |
188
|
6300
|
|
|
|
|
|
*BETA/90.0+1.0) |
189
|
6300
|
|
|
|
|
|
*BETA/56.0+1.0) |
190
|
6300
|
|
|
|
|
|
*BETA/30.0+1.0) |
191
|
6300
|
|
|
|
|
|
*BETA/12.0+1.0)/2.0; |
192
|
6300
|
|
|
|
|
|
S1 = PSJ+ALPHA*S3; |
193
|
6300
|
|
|
|
|
|
S0 = 1.0+ALPHA*S2; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
/* Undo the angle-halving. */ |
196
|
|
|
|
|
|
|
TOL = TEST; |
197
|
7836
|
100
|
|
|
|
|
while (N > 0) { |
198
|
1536
|
|
|
|
|
|
S3 = 2.0*(S0*S3+PSJ*S2); |
199
|
1536
|
|
|
|
|
|
S2 = 2.0*S1*S1; |
200
|
1536
|
|
|
|
|
|
S1 = 2.0*S0*S1; |
201
|
1536
|
|
|
|
|
|
S0 = 2.0*S0*S0-1.0; |
202
|
1536
|
|
|
|
|
|
PSJ = PSJ+PSJ; |
203
|
1536
|
|
|
|
|
|
TOL += TOL; |
204
|
1536
|
|
|
|
|
|
N--; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
/* Values of F and F' corresponding to the current value of psi. */ |
208
|
6300
|
|
|
|
|
|
FF = R0*S1+SIGMA0*S2+CM*S3-DT; |
209
|
6300
|
|
|
|
|
|
R = R0*S0+SIGMA0*S1+CM*S2; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
/* If first iteration, create dummy "last F". */ |
212
|
6300
|
100
|
|
|
|
|
if ( NIT == 1) FLAST = FF; |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
/* Check for sign change. */ |
215
|
6300
|
100
|
|
|
|
|
if ( FF*FLAST < 0.0 ) { |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
/* Sign change: get psi adjustment using secant method. */ |
218
|
1352
|
|
|
|
|
|
W = FF*(PLAST-PSI)/(FLAST-FF); |
219
|
|
|
|
|
|
|
} else { |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
/* No sign change: use Newton-Raphson method instead. */ |
222
|
4948
|
50
|
|
|
|
|
if (R == 0.0) { |
223
|
|
|
|
|
|
|
/* Null radius vector */ |
224
|
0
|
|
|
|
|
|
*jstat = -1; |
225
|
0
|
|
|
|
|
|
return; |
226
|
|
|
|
|
|
|
} |
227
|
4948
|
|
|
|
|
|
W = FF/R; |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
/* Save the last psi and F values. */ |
231
|
|
|
|
|
|
|
PLAST = PSI; |
232
|
|
|
|
|
|
|
FLAST = FF; |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
/* Apply the Newton-Raphson or secant adjustment to psi. */ |
235
|
6300
|
|
|
|
|
|
PSI = PSI-W; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
/* Next iteration, unless too many already. */ |
238
|
6300
|
50
|
|
|
|
|
if (NIT > NITMAX) { |
239
|
0
|
|
|
|
|
|
*jstat = -2; /* Failed to converge */ |
240
|
0
|
|
|
|
|
|
return; |
241
|
|
|
|
|
|
|
} |
242
|
6300
|
|
|
|
|
|
NIT++; |
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
/* Project the position and velocity vectors (scaling velocity to AU/s). */ |
246
|
2102
|
|
|
|
|
|
W = CM*S2; |
247
|
2102
|
|
|
|
|
|
F = 1.0-W/R0; |
248
|
2102
|
|
|
|
|
|
G = DT-CM*S3; |
249
|
2102
|
|
|
|
|
|
FD = -CM*S1/(R0*R); |
250
|
2102
|
|
|
|
|
|
GD = 1.0-W/R; |
251
|
8408
|
100
|
|
|
|
|
for (I=0; I<3; I++) { |
252
|
6306
|
|
|
|
|
|
pv[I] = P0[I]*F+V0[I]*G; |
253
|
6306
|
|
|
|
|
|
pv[I+3] = CD2S*(P0[I]*FD+V0[I]*GD); |
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
/* Update the parameters to allow speedy prediction of PSI next time. */ |
257
|
2102
|
|
|
|
|
|
u[11] = date; |
258
|
2102
|
|
|
|
|
|
u[12] = PSI; |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
/* OK exit. */ |
261
|
2102
|
|
|
|
|
|
*jstat = 0; |
262
|
2102
|
|
|
|
|
|
return; |
263
|
|
|
|
|
|
|
} |