source: Sophya/trunk/SophyaExt/XephemAstroLib/jupmoon.c@ 3111

Last change on this file since 3111 was 3111, checked in by cmv, 19 years ago

mise en conformite xephem 3.7.2 cmv 22/11/2006

File size: 9.9 KB
RevLine 
[2551]1/* jupiter moon info */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
[3111]6#include <errno.h>
[2551]7#include <math.h>
8
9#include "astro.h"
10#include "bdl.h"
11
12static int use_bdl (double jd, char *dir, MoonData md[J_NMOONS]);
13static void meeus_jupiter (double d, double *cmlI, double *cmlII,
14 MoonData md[J_NMOONS]);
15static void moonradec (double jupsize, MoonData md[J_NMOONS]);
[2643]16static void moonSVis (Obj *sop, Obj *jop, MoonData md[J_NMOONS]);
[2551]17static void moonEVis (MoonData md[J_NMOONS]);
[2643]18static void moonPShad (Obj *sop, Obj *jop, MoonData md[J_NMOONS]);
19static void moonTrans (MoonData md[J_NMOONS]);
[2551]20
21/* moon table and a few other goodies and when it was last computed */
22static double mdmjd = -123456;
23static MoonData jmd[J_NMOONS] = {
24 {"Jupiter", NULL},
25 {"Io", "I"},
26 {"Europa", "II"},
27 {"Ganymede", "III"},
28 {"Callisto", "IV"}
29};
30static double sizemjd; /* size at last mjd */
31static double cmlImjd; /* central meridian long sys I, at last mjd */
32static double cmlIImjd; /* " II " */
33
[2643]34/* These values are from the Explanatory Supplement.
35 * Precession degrades them gradually over time.
36 */
37#define POLE_RA degrad(268.05) /* RA of Jupiter's north pole */
38#define POLE_DEC degrad(64.50) /* Dec of Jupiter's north pole */
39
40
[2551]41/* get jupiter info in md[0], moon info in md[1..J_NMOONS-1].
42 * if !dir always use meeus model.
43 * if !jop caller just wants md[] for names
[2643]44 * N.B. we assume sop and jop are updated.
[2551]45 */
46void
47jupiter_data (
48double Mjd, /* mjd */
49char dir[], /* dir in which to look for helper files */
[2643]50Obj *sop, /* Sun */
[2551]51Obj *jop, /* jupiter */
52double *sizep, /* jup angular diam, rads */
[2643]53double *cmlI, double *cmlII, /* central meridian longitude, rads */
54double *polera, double *poledec, /* pole location */
[2551]55MoonData md[J_NMOONS]) /* return info */
56{
57 double JD;
58
59 /* always copy back at least for name */
60 memcpy (md, jmd, sizeof(jmd));
61
[2643]62 /* pole */
63 if (polera) *polera = POLE_RA;
64 if (poledec) *poledec = POLE_DEC;
65
[2551]66 /* nothing else if repeat call or just want names */
67 if (Mjd == mdmjd || !jop) {
68 if (jop) {
69 *sizep = sizemjd;
70 *cmlI = cmlImjd;
71 *cmlII = cmlIImjd;
72 }
73 return;
74 }
75 JD = Mjd + MJD0;
76
77 /* planet in [0] */
78 md[0].ra = jop->s_ra;
79 md[0].dec = jop->s_dec;
80 md[0].mag = get_mag(jop);
81 md[0].x = 0;
82 md[0].y = 0;
83 md[0].z = 0;
84 md[0].evis = 1;
85 md[0].svis = 1;
86
87 /* size is straight from jop */
88 *sizep = degrad(jop->s_size/3600.0);
89
90 /* mags from JPL ephemeris */
91 md[1].mag = 5.7;
92 md[2].mag = 5.8;
93 md[3].mag = 5.3;
94 md[4].mag = 6.7;
95
96 /* get moon data from BDL if possible, else Meeus' model.
97 * always use Meeus for cml
98 */
99 if (dir && use_bdl (JD, dir, md) == 0)
100 meeus_jupiter (Mjd, cmlI, cmlII, NULL);
101 else
102 meeus_jupiter (Mjd, cmlI, cmlII, md);
103
104 /* set visibilities */
[2643]105 moonSVis (sop, jop, md);
106 moonPShad (sop, jop, md);
[2551]107 moonEVis (md);
[2643]108 moonTrans (md);
[2551]109
110 /* fill in moon ra and dec */
111 moonradec (*sizep, md);
112
113 /* save */
114 mdmjd = Mjd;
115 sizemjd = *sizep;
116 cmlImjd = *cmlI;
117 cmlIImjd = *cmlII;
118 memcpy (jmd, md, sizeof(jmd));
119}
120
121/* hunt for BDL file in dir[] and use if possible
122 * return 0 if ok, else -1
123 */
124static int
125use_bdl (
126double JD, /* julian date */
127char dir[], /* directory */
128MoonData md[J_NMOONS]) /* fill md[1..NM-1].x/y/z for each moon */
129{
130#define JUPRAU .0004769108 /* jupiter radius, AU */
131 double x[J_NMOONS], y[J_NMOONS], z[J_NMOONS];
132 char buf[1024];
133 FILE *fp;
[3111]134 char *fn;
[2551]135 int i;
136
[3111]137 /* check ranges and appropriate data file */
138 if (JD < 2451179.50000) /* Jan 1 1999 UTC */
[2551]139 return (-1);
[3111]140 if (JD < 2455562.5) /* Jan 1 2011 UTC */
141 fn = "jupiter.9910";
142 else if (JD < 2459215.5) /* Jan 1 2021 UTC */
143 fn = "jupiter.1020";
144 else
145 return (-1);
[2551]146
147 /* open */
[3111]148 (void) sprintf (buf, "%s/%s", dir, fn);
[2551]149 fp = fopen (buf, "r");
[3111]150 if (!fp) {
151 fprintf (stderr, "%s: %s\n", fn, strerror(errno));
[2551]152 return (-1);
[3111]153 }
[2551]154
155 /* use it */
156 if ((i = read_bdl (fp, JD, x, y, z, buf)) < 0) {
[3111]157 fprintf (stderr, "%s: %s\n", fn, buf);
[2551]158 fclose (fp);
159 return (-1);
160 }
161 if (i != J_NMOONS-1) {
[3111]162 fprintf (stderr, "%s: BDL says %d moons, code expects %d", fn,
[2551]163 i, J_NMOONS-1);
164 fclose (fp);
165 return (-1);
166 }
167
168 /* copy into md[1..NM-1] with our scale and sign conventions */
169 for (i = 1; i < J_NMOONS; i++) {
170 md[i].x = x[i-1]/JUPRAU; /* we want jup radii +E */
171 md[i].y = -y[i-1]/JUPRAU; /* we want jup radii +S */
172 md[i].z = -z[i-1]/JUPRAU; /* we want jup radii +front */
173 }
174
175 /* ok */
176 fclose (fp);
177 return (0);
178}
179
180/* compute location of GRS and Galilean moons.
181 * if md == NULL, just to cml.
182 * from "Astronomical Formulae for Calculators", 2nd ed, by Jean Meeus,
183 * Willmann-Bell, Richmond, Va., U.S.A. (c) 1982, chapters 35 and 36.
184 */
185static void
186meeus_jupiter(
187double d,
188double *cmlI, double *cmlII, /* central meridian longitude, rads */
189MoonData md[J_NMOONS]) /* fill in md[1..NM-1].x/y/z for each moon.
190 * N.B. md[0].ra/dec must already be set
191 */
192{
193#define dsin(x) sin(degrad(x))
194#define dcos(x) cos(degrad(x))
195 double A, B, Del, J, K, M, N, R, V;
196 double cor_u1, cor_u2, cor_u3, cor_u4;
197 double solc, tmp, G, H, psi, r, r1, r2, r3, r4;
198 double u1, u2, u3, u4;
199 double lam, Ds;
200 double z1, z2, z3, z4;
201 double De, dsinDe;
202 double theta, phi;
203 double tvc, pvc;
204 double salpha, calpha;
205 int i;
206
207 V = 134.63 + 0.00111587 * d;
208
209 M = (358.47583 + 0.98560003*d);
210 N = (225.32833 + 0.0830853*d) + 0.33 * dsin (V);
211
212 J = 221.647 + 0.9025179*d - 0.33 * dsin(V);
213
214 A = 1.916*dsin(M) + 0.02*dsin(2*M);
215 B = 5.552*dsin(N) + 0.167*dsin(2*N);
216 K = (J+A-B);
217 R = 1.00014 - 0.01672 * dcos(M) - 0.00014 * dcos(2*M);
218 r = 5.20867 - 0.25192 * dcos(N) - 0.00610 * dcos(2*N);
219 Del = sqrt (R*R + r*r - 2*R*r*dcos(K));
220 psi = raddeg (asin (R/Del*dsin(K)));
221
222 *cmlI = degrad(268.28 + 877.8169088*(d - Del/173) + psi - B);
223 range (cmlI, 2*PI);
224 *cmlII = degrad(290.28 + 870.1869088*(d - Del/173) + psi - B);
225 range (cmlII, 2*PI);
226
227 /* that's it if don't want moon info too */
228 if (!md)
229 return;
230
231 solc = (d - Del/173.); /* speed of light correction */
232 tmp = psi - B;
233
234 u1 = 84.5506 + 203.4058630 * solc + tmp;
235 u2 = 41.5015 + 101.2916323 * solc + tmp;
236 u3 = 109.9770 + 50.2345169 * solc + tmp;
237 u4 = 176.3586 + 21.4879802 * solc + tmp;
238
239 G = 187.3 + 50.310674 * solc;
240 H = 311.1 + 21.569229 * solc;
241
242 cor_u1 = 0.472 * dsin (2*(u1-u2));
243 cor_u2 = 1.073 * dsin (2*(u2-u3));
244 cor_u3 = 0.174 * dsin (G);
245 cor_u4 = 0.845 * dsin (H);
246
247 r1 = 5.9061 - 0.0244 * dcos (2*(u1-u2));
248 r2 = 9.3972 - 0.0889 * dcos (2*(u2-u3));
249 r3 = 14.9894 - 0.0227 * dcos (G);
250 r4 = 26.3649 - 0.1944 * dcos (H);
251
252 md[1].x = -r1 * dsin (u1+cor_u1);
253 md[2].x = -r2 * dsin (u2+cor_u2);
254 md[3].x = -r3 * dsin (u3+cor_u3);
255 md[4].x = -r4 * dsin (u4+cor_u4);
256
257 lam = 238.05 + 0.083091*d + 0.33*dsin(V) + B;
258 Ds = 3.07*dsin(lam + 44.5);
259 De = Ds - 2.15*dsin(psi)*dcos(lam+24.)
260 - 1.31*(r-Del)/Del*dsin(lam-99.4);
261 dsinDe = dsin(De);
262
263 z1 = r1 * dcos(u1+cor_u1);
264 z2 = r2 * dcos(u2+cor_u2);
265 z3 = r3 * dcos(u3+cor_u3);
266 z4 = r4 * dcos(u4+cor_u4);
267
268 md[1].y = z1*dsinDe;
269 md[2].y = z2*dsinDe;
270 md[3].y = z3*dsinDe;
271 md[4].y = z4*dsinDe;
272
273 /* compute sky transformation angle as triple vector product */
274 tvc = PI/2.0 - md[0].dec;
275 pvc = md[0].ra;
276 theta = PI/2.0 - POLE_DEC;
277 phi = POLE_RA;
278 salpha = -sin(tvc)*sin(theta)*(cos(pvc)*sin(phi) - sin(pvc)*cos(phi));
279 calpha = sqrt (1.0 - salpha*salpha);
280
281 for (i = 0; i < J_NMOONS; i++) {
282 double tx = md[i].x*calpha + md[i].y*salpha;
283 double ty = -md[i].x*salpha + md[i].y*calpha;
284 md[i].x = tx;
285 md[i].y = ty;
286 }
287
288 md[1].z = z1;
289 md[2].z = z2;
290 md[3].z = z3;
291 md[4].z = z4;
292}
293
294
295/* given jupiter loc in md[0].ra/dec and size, and location of each moon in
296 * md[1..NM-1].x/y in jup radii, find ra/dec of each moon in md[1..NM-1].ra/dec.
297 */
298static void
299moonradec (
300double jupsize, /* jup diameter, rads */
301MoonData md[J_NMOONS]) /* fill in RA and Dec */
302{
303 double juprad = jupsize/2;
304 double jupra = md[0].ra;
305 double jupdec = md[0].dec;
306 int i;
307
308 for (i = 1; i < J_NMOONS; i++) {
309 double dra = juprad * md[i].x;
310 double ddec = juprad * md[i].y;
311 md[i].ra = jupra + dra;
312 md[i].dec = jupdec - ddec;
313 }
314}
315
316/* set svis according to whether moon is in sun light */
317static void
318moonSVis(
[2643]319Obj *sop, /* SUN */
[2551]320Obj *jop, /* jupiter */
321MoonData md[J_NMOONS])
322{
[2643]323 double esd = sop->s_edist;
[2551]324 double eod = jop->s_edist;
325 double sod = jop->s_sdist;
326 double soa = degrad(jop->s_elong);
327 double esa = asin(esd*sin(soa)/sod);
328 double h = sod*jop->s_hlat;
329 double nod = h*(1./eod - 1./sod);
330 double sca = cos(esa), ssa = sin(esa);
331 int i;
332
333 for (i = 1; i < J_NMOONS; i++) {
334 MoonData *mdp = &md[i];
335 double xp = sca*mdp->x + ssa*mdp->z;
336 double yp = mdp->y;
337 double zp = -ssa*mdp->x + sca*mdp->z;
338 double ca = cos(nod), sa = sin(nod);
339 double xpp = xp;
340 double ypp = ca*yp - sa*zp;
341 double zpp = sa*yp + ca*zp;
342 int outside = xpp*xpp + ypp*ypp > 1.0;
343 int infront = zpp > 0.0;
344 mdp->svis = outside || infront;
345 }
346}
347
348/* set evis according to whether moon is geometrically visible from earth */
349static void
350moonEVis (MoonData md[J_NMOONS])
351{
352 int i;
353
354 for (i = 1; i < J_NMOONS; i++) {
355 MoonData *mdp = &md[i];
356 int outside = mdp->x*mdp->x + mdp->y*mdp->y > 1.0;
357 int infront = mdp->z > 0.0;
358 mdp->evis = outside || infront;
359 }
360}
361
[2643]362/* set pshad and sx,sy shadow info */
363static void
364moonPShad(
365Obj *sop, /* SUN */
366Obj *jop, /* jupiter */
367MoonData md[J_NMOONS])
368{
369 int i;
370
371 for (i = 1; i < J_NMOONS; i++) {
372 MoonData *mdp = &md[i];
373 mdp->pshad = !plshadow (jop, sop, POLE_RA, POLE_DEC, mdp->x,
374 mdp->y, mdp->z, &mdp->sx, &mdp->sy);
375 }
376}
377
378/* set whether moons are transiting */
379static void
380moonTrans (MoonData md[J_NMOONS])
381{
382 int i;
383
384 for (i = 1; i < J_NMOONS; i++) {
385 MoonData *mdp = &md[i];
386 mdp->trans = mdp->z > 0 && mdp->x*mdp->x + mdp->y*mdp->y < 1;
387 }
388}
389
[2551]390/* For RCS Only -- Do Not Edit */
[3111]391static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: jupmoon.c,v $ $Date: 2006-11-22 13:53:29 $ $Revision: 1.4 $ $Name: not supported by cvs2svn $"};
Note: See TracBrowser for help on using the repository browser.