| 1 | /* heliocentric rectangular equatorial coordinates of Jupiter to Pluto;
 | 
|---|
| 2 |  * from Chapront's expansion of DE200/extension of DE200;  mean equator J2000.0
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  * calculation time (milliseconds) on an HP 715/75, Jupiter to Pluto:
 | 
|---|
| 5 |  * (each coordinate component counted as 1 term,
 | 
|---|
| 6 |  * secular terms included for JD 2448908.5 = 1992 Oct 13.0)
 | 
|---|
| 7 |  *
 | 
|---|
| 8 |  *      prec    terms   rates   no rates
 | 
|---|
| 9 |  *      0.0     2256    5.1     4.6
 | 
|---|
| 10 |  *
 | 
|---|
| 11 |  *      1e-7    792     2.6     2.4     --> nominal precision rel. to DE200
 | 
|---|
| 12 |  *      1e-6    535     2.1     2.0
 | 
|---|
| 13 |  *      1e-5    350     1.8     1.6
 | 
|---|
| 14 |  *      1e-4    199     1.5     1.4
 | 
|---|
| 15 |  *      1e-3    96      1.2     1.1
 | 
|---|
| 16 |  *
 | 
|---|
| 17 |  *      no drop 2256    4.5     3.9     (code without test criterion)
 | 
|---|
| 18 |  */
 | 
|---|
| 19 | 
 | 
|---|
| 20 | #include <math.h>
 | 
|---|
| 21 | 
 | 
|---|
| 22 | #include "astro.h"
 | 
|---|
| 23 | #include "chap95.h"
 | 
|---|
| 24 | 
 | 
|---|
| 25 | #define CHAP_MAXTPOW    2       /* NB: valid for all 5 outer planets */
 | 
|---|
| 26 | 
 | 
|---|
| 27 | /* chap95()
 | 
|---|
| 28 |  *
 | 
|---|
| 29 |  * input:
 | 
|---|
| 30 |  *      m       modified JD; days from J1900.0 = 2415020.0
 | 
|---|
| 31 |  *
 | 
|---|
| 32 |  *      prec    precision level, in radians.
 | 
|---|
| 33 |  *              if (prec = 0.0), you get the full precision, namely
 | 
|---|
| 34 |  *              a deviation of not more than 0.02 arc seconds (1e-7 rad)
 | 
|---|
| 35 |  *              from the JPL DE200 integration, on which this expansion
 | 
|---|
| 36 |  *              is based.
 | 
|---|
| 37 |  *
 | 
|---|
| 38 |  *      obj     object number as in astro.h (jupiter=3, saturn=4, ...)
 | 
|---|
| 39 |  *
 | 
|---|
| 40 |  * output:
 | 
|---|
| 41 |  *      ret[6]  cartesian components of position and velocity
 | 
|---|
| 42 |  *
 | 
|---|
| 43 |  * return:
 | 
|---|
| 44 |  *      0       Ok
 | 
|---|
| 45 |  *      1       time out of range [CHAP_BEGIN .. CHAP_END]
 | 
|---|
| 46 |  *      2       object out of range [JUPITER .. PLUTO]
 | 
|---|
| 47 |  *      3       precision out of range [0.0 .. 1e-3]
 | 
|---|
| 48 |  */
 | 
|---|
| 49 | int
 | 
|---|
| 50 | chap95 (double m, int obj, double prec, double *ret)
 | 
|---|
| 51 | {
 | 
|---|
| 52 |         static double a0[] = {          /* semimajor axes for precision ctrl */
 | 
|---|
| 53 |             0.39, 0.72, 1.5, 5.2, 9.6, 19.2, 30.1, 39.5, 1.0
 | 
|---|
| 54 |         };
 | 
|---|
| 55 |         double sum[CHAP_MAXTPOW+1][6];  /* [T^0, ..][X,Y,Z,X',Y',Z'] */
 | 
|---|
| 56 |         double T, t;                    /* time in centuries and years */
 | 
|---|
| 57 |         double ca, sa, Nu;              /* aux vars for terms */
 | 
|---|
| 58 |         double precT[CHAP_MAXTPOW+1];   /* T-augmented precision threshold */
 | 
|---|
| 59 |         chap95_rec *rec;                /* term coeffs */
 | 
|---|
| 60 |         int cooidx;
 | 
|---|
| 61 | 
 | 
|---|
| 62 |         /* check parameters */
 | 
|---|
| 63 |         if (m < CHAP_BEGIN || m > CHAP_END)
 | 
|---|
| 64 |                 return (1);
 | 
|---|
| 65 | 
 | 
|---|
| 66 |         if (obj < JUPITER || obj > PLUTO)
 | 
|---|
| 67 |                 return (2);
 | 
|---|
| 68 | 
 | 
|---|
| 69 |         if (prec < 0.0 || prec > 1e-3)
 | 
|---|
| 70 |                 return (3);
 | 
|---|
| 71 | 
 | 
|---|
| 72 |         /* init the sums */
 | 
|---|
| 73 |         zero_mem ((void *)sum, sizeof(sum));
 | 
|---|
| 74 | 
 | 
|---|
| 75 |         T = (m - J2000)/36525.0;        /* centuries since J2000.0 */
 | 
|---|
| 76 | 
 | 
|---|
| 77 |         /* modify precision treshold for
 | 
|---|
| 78 |          * a) term storing scale
 | 
|---|
| 79 |          * b) convert radians to au
 | 
|---|
| 80 |          * c) account for skipped terms (more terms needed for better prec)
 | 
|---|
| 81 |          *    threshold empirically established similar to VSOP; stern
 | 
|---|
| 82 |          * d) augment for secular terms
 | 
|---|
| 83 |          */
 | 
|---|
| 84 |         precT[0] = prec * CHAP_SCALE                            /* a) */
 | 
|---|
| 85 |                         * a0[obj]                               /* b) */
 | 
|---|
| 86 |                         / (10. * (-log10(prec + 1e-35) - 2));   /* c) */
 | 
|---|
| 87 |         t = 1./(fabs(T) + 1e-35);                               /* d) */
 | 
|---|
| 88 |         precT[1] = precT[0]*t;
 | 
|---|
| 89 |         precT[2] = precT[1]*t;
 | 
|---|
| 90 | 
 | 
|---|
| 91 |         t = T * 100.0;          /* YEARS since J2000.0 */
 | 
|---|
| 92 | 
 | 
|---|
| 93 |         ca = sa = Nu = 0.;      /* shut up compiler warning 'uninitialised' */
 | 
|---|
| 94 | 
 | 
|---|
| 95 |         switch (obj) {          /* set initial term record pointer */
 | 
|---|
| 96 |             case JUPITER:       rec = chap95_jupiter;   break;
 | 
|---|
| 97 |             case SATURN:        rec = chap95_saturn;    break;
 | 
|---|
| 98 |             case URANUS:        rec = chap95_uranus;    break;
 | 
|---|
| 99 |             case NEPTUNE:       rec = chap95_neptune;   break;
 | 
|---|
| 100 |             case PLUTO:         rec = chap95_pluto;     break;
 | 
|---|
| 101 |             default:
 | 
|---|
| 102 |                 return (2);     /* wrong object: severe internal trouble */
 | 
|---|
| 103 |         }
 | 
|---|
| 104 | 
 | 
|---|
| 105 |         /* do the term summation into sum[T^n] slots */
 | 
|---|
| 106 |         for (; rec->n >= 0; ++rec) {
 | 
|---|
| 107 |             double *amp;
 | 
|---|
| 108 | 
 | 
|---|
| 109 |             /* NOTE:  The formula
 | 
|---|
| 110 |              * X = SUM[i=1,Records] T**n_i*(CX_i*cos(Nu_k*t)+SX_i*sin(Nu_k*t))
 | 
|---|
| 111 |              * could be rewritten as  SUM( ... A sin (B + C*t) )
 | 
|---|
| 112 |              * "saving" trigonometric calls.  However, e.g. for Pluto,
 | 
|---|
| 113 |              * there are only 65 distinct angles NU_k (130 trig calls).
 | 
|---|
| 114 |              * With that manipulation, EVERY arg_i would be different for X,
 | 
|---|
| 115 |              * Y and Z, which is 3*96 terms.  Hence, the formulation as
 | 
|---|
| 116 |              * given is good (optimal?).
 | 
|---|
| 117 |              */
 | 
|---|
| 118 | 
 | 
|---|
| 119 |             for (cooidx = 0, amp = rec->amp; cooidx < 3; ++cooidx) {
 | 
|---|
| 120 |                 double C, S, term, termdot;
 | 
|---|
| 121 |                 short n;                /* fast access */
 | 
|---|
| 122 | 
 | 
|---|
| 123 |                 C = *amp++;
 | 
|---|
| 124 |                 S = *amp++;
 | 
|---|
| 125 |                 n = rec->n;
 | 
|---|
| 126 | 
 | 
|---|
| 127 |                 /* drop term if too small
 | 
|---|
| 128 |                  * this is quite expensive:  17% of loop time
 | 
|---|
| 129 |                  */
 | 
|---|
| 130 |                 if (fabs(C) + fabs(S) < precT[n])
 | 
|---|
| 131 |                         continue;
 | 
|---|
| 132 | 
 | 
|---|
| 133 |                 if (n == 0 && cooidx == 0) {    /* new Nu only here */
 | 
|---|
| 134 |                     double arg;
 | 
|---|
| 135 | 
 | 
|---|
| 136 |                     Nu = rec->Nu;
 | 
|---|
| 137 |                     arg = Nu * t;
 | 
|---|
| 138 |                     arg -= floor(arg/(2.*PI))*(2.*PI);
 | 
|---|
| 139 |                     ca = cos(arg);      /* blast it - even for Nu = 0.0 */
 | 
|---|
| 140 |                     sa = sin(arg);
 | 
|---|
| 141 |                 }
 | 
|---|
| 142 | 
 | 
|---|
| 143 |                 term = C * ca + S * sa;
 | 
|---|
| 144 |                 sum[n][cooidx] += term;
 | 
|---|
| 145 | #if CHAP_GETRATE
 | 
|---|
| 146 |                 termdot = (-C * sa + S * ca) * Nu;
 | 
|---|
| 147 |                 sum[n][cooidx+3] += termdot;
 | 
|---|
| 148 |                 if (n > 0) sum[n - 1][cooidx+3] += n/100.0 * term;
 | 
|---|
| 149 | #endif
 | 
|---|
| 150 |             } /* cooidx */
 | 
|---|
| 151 |         } /* records */
 | 
|---|
| 152 | 
 | 
|---|
| 153 |         /* apply powers of time and sum up */
 | 
|---|
| 154 |         for (cooidx = 0; cooidx < 6; ++cooidx) {
 | 
|---|
| 155 |             ret[cooidx] = (sum[0][cooidx] +
 | 
|---|
| 156 |                         T * (sum[1][cooidx] +
 | 
|---|
| 157 |                         T * (sum[2][cooidx] )) )/CHAP_SCALE;
 | 
|---|
| 158 |         }
 | 
|---|
| 159 | 
 | 
|---|
| 160 |         /* TEST: if the MAIN terms are dropped, get angular residue
 | 
|---|
| 161 |         ret[0] = sqrt(ret[0]*ret[0] + ret[1]*ret[1] + ret[2]*ret[2])/a0[obj];
 | 
|---|
| 162 |         */
 | 
|---|
| 163 | 
 | 
|---|
| 164 | #if CHAP_GETRATE
 | 
|---|
| 165 |         for (cooidx = 3; cooidx < 6; ++cooidx) {
 | 
|---|
| 166 |             ret[cooidx] /= 365.25;      /* yearly to daily rate */
 | 
|---|
| 167 |         }
 | 
|---|
| 168 | #endif
 | 
|---|
| 169 | 
 | 
|---|
| 170 |     return (0);
 | 
|---|
| 171 | }
 | 
|---|
| 172 | 
 | 
|---|
| 173 | /* For RCS Only -- Do Not Edit */
 | 
|---|
| 174 | static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: chap95.c,v $ $Date: 2008-03-25 17:45:11 $ $Revision: 1.7 $ $Name: not supported by cvs2svn $"};
 | 
|---|