FACT++  1.0
void palUe2pv ( double  date,
double  u[13],
double  pv[6],
int *  jstat 
)

Definition at line 124 of file palUe2pv.c.

References PAL__GCON, and PAL__SPD.

124  {
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  CM = u[0];
143  ALPHA = u[1];
144  T0 = u[2];
145  for (I=0; I<3; I++) {
146  P0[I] = u[I+3];
147  V0[I] = u[I+6];
148  }
149  R0 = u[9];
150  SIGMA0 = u[10];
151  T = u[11];
152  PSI = u[12];
153 
154  /* Approximately update the universal eccentric anomaly. */
155  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  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  while (fabs(W) >= TOL) {
166 
167  /* Form half angles until BETA small enough. */
168  N = 0;
169  PSJ = PSI;
170  PSJ2 = PSJ*PSJ;
171  BETA = ALPHA*PSJ2;
172  while (fabs(BETA) > 0.7) {
173  N = N+1;
174  BETA = BETA/4.0;
175  PSJ = PSJ/2.0;
176  PSJ2 = PSJ2/4.0;
177  }
178 
179  /* Calculate Universal Variables S0,S1,S2,S3 by nested series. */
180  S3 = PSJ*PSJ2*((((((BETA/210.0+1.0)
181  *BETA/156.0+1.0)
182  *BETA/110.0+1.0)
183  *BETA/72.0+1.0)
184  *BETA/42.0+1.0)
185  *BETA/20.0+1.0)/6.0;
186  S2 = PSJ2*((((((BETA/182.0+1.0)
187  *BETA/132.0+1.0)
188  *BETA/90.0+1.0)
189  *BETA/56.0+1.0)
190  *BETA/30.0+1.0)
191  *BETA/12.0+1.0)/2.0;
192  S1 = PSJ+ALPHA*S3;
193  S0 = 1.0+ALPHA*S2;
194 
195  /* Undo the angle-halving. */
196  TOL = TEST;
197  while (N > 0) {
198  S3 = 2.0*(S0*S3+PSJ*S2);
199  S2 = 2.0*S1*S1;
200  S1 = 2.0*S0*S1;
201  S0 = 2.0*S0*S0-1.0;
202  PSJ = PSJ+PSJ;
203  TOL += TOL;
204  N--;
205  }
206 
207  /* Values of F and F' corresponding to the current value of psi. */
208  FF = R0*S1+SIGMA0*S2+CM*S3-DT;
209  R = R0*S0+SIGMA0*S1+CM*S2;
210 
211  /* If first iteration, create dummy "last F". */
212  if ( NIT == 1) FLAST = FF;
213 
214  /* Check for sign change. */
215  if ( FF*FLAST < 0.0 ) {
216 
217  /* Sign change: get psi adjustment using secant method. */
218  W = FF*(PLAST-PSI)/(FLAST-FF);
219  } else {
220 
221  /* No sign change: use Newton-Raphson method instead. */
222  if (R == 0.0) {
223  /* Null radius vector */
224  *jstat = -1;
225  return;
226  }
227  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  PSI = PSI-W;
236 
237  /* Next iteration, unless too many already. */
238  if (NIT > NITMAX) {
239  *jstat = -2; /* Failed to converge */
240  return;
241  }
242  NIT++;
243  }
244 
245  /* Project the position and velocity vectors (scaling velocity to AU/s). */
246  W = CM*S2;
247  F = 1.0-W/R0;
248  G = DT-CM*S3;
249  FD = -CM*S1/(R0*R);
250  GD = 1.0-W/R;
251  for (I=0; I<3; I++) {
252  pv[I] = P0[I]*F+V0[I]*G;
253  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  u[11] = date;
258  u[12] = PSI;
259 
260  /* OK exit. */
261  *jstat = 0;
262  return;
263 }
static const double PAL__GCON
Definition: palmac.h:117
static const double PAL__SPD
Definition: palmac.h:102