/* fill in all of op->s_* stuff except s_size and s_mag. * this is used for sol system objects (except sun and moon); never FIXED. */ static void cir_sky ( Now *np, double lpd, /* heliocentric ecliptic longitude */ double psi, /* heliocentric ecliptic lat */ double rp, /* dist from sun */ double *rho, /* dist from earth: in as geo, back as geo or topo */ double lam, /* true geocentric ecliptic long */ double bet, /* true geocentric ecliptic lat */ double lsn, /* true geoc lng of sun */ double rsn, /* dist from sn to earth*/ Obj *op) { double el; /* elongation */ double f; /* fractional phase from earth */ printf("\nDEBUG1: *rho=%f\n", *rho); /* compute elongation and phase */ elongation (lam, bet, lsn, &el); el = raddeg(el); op->s_elong = (float)el; f = 0.25 * ((rp+ *rho)*(rp+ *rho) - rsn*rsn)/(rp* *rho); op->s_phase = (float)(f*100.0); /* percent */ /* set heliocentric long/lat; mean ecliptic and EOD */ op->s_hlong = (float)lpd; op->s_hlat = (float)psi; /* fill solar sys body's ra/dec, alt/az in op */ cir_pos (np, bet, lam, rho, op); /* updates rho */ /* set earth/planet and sun/planet distance */ op->s_edist = (float)(*rho); op->s_sdist = (float)rp; }
/* find moon's circumstances now. */ static int moon_cir (Now *np, Obj *op) { double lsn, rsn; /* true geoc lng of sun; dist from sn to earth*/ double lam; /* geocentric ecliptic longitude */ double bet; /* geocentric ecliptic latitude */ double edistau; /* earth-moon dist, in au */ double el; /* elongation, rads east */ double ms; /* sun's mean anomaly */ double md; /* moon's mean anomaly */ double i; moon (mjed, &lam, &bet, &edistau, &ms, &md); /* mean ecliptic & EOD*/ sunpos (mjed, &lsn, &rsn, NULL); /* mean ecliptic & EOD*/ op->s_hlong = (float)lam; /* save geo in helio fields */ op->s_hlat = (float)bet; /* find angular separation from sun */ elongation (lam, bet, lsn, &el); op->s_elong = (float)raddeg(el); /* want degrees */ /* solve triangle of earth, sun, and elongation for moon-sun dist */ op->s_sdist = (float) sqrt (edistau*edistau + rsn*rsn - 2.0*edistau*rsn*cos(el)); /* TODO: improve mag; this is based on a flat moon model. */ i = -12.7 + 2.5*(log10(PI) - log10(PI/2*(1+1.e-6-cos(el)))) + 5*log10(edistau/.0025) /* dist */; set_smag (op, i); /* find phase -- allow for projection effects */ i = 0.1468*sin(el)*(1 - 0.0549*sin(md))/(1 - 0.0167*sin(ms)); op->s_phase = (float)((1+cos(PI-el-degrad(i)))/2*100); /* fill moon's ra/dec, alt/az in op and update for topo dist */ cir_pos (np, bet, lam, &edistau, op); op->s_edist = (float)edistau; op->s_size = (float)(3600*2.0*raddeg(asin(MRAD/MAU/edistau))); /* moon angular dia, seconds */ return (0); }
int main() { caas::Matrix a { "test_data/hw05/matrix1_t04.txt" }; caas::Matrix x0{ "test_data/hw05/matrix2_t04.txt" }; caas::Matrix b { "test_data/hw05/matrix3_t04.txt" }; auto step{ 0.1 }; auto tMax{ 10 }; auto states{ caas::numerical::trapeze( a, x0, b, step, tMax ) }; std::vector< double > x( std::size( states ) ); std::vector< double > elongation( std::size( states ) ); std::vector< double > speed( std::size( states ) ); std::size_t i{ 0 }; for ( double t{ 0 }; t < tMax; t += step ) { x[ i ] = t; elongation[ i ] = states[ i ]( 0, 0 ); speed[ i ] = states[ i ]( 1, 0 ); std::cout << "t = " << t << "; elongation = " << elongation[ i ] << "; speed = " << speed[ i ] << '\n'; ++i; } sciplot::plot plot; plot.draw( x, elongation ).title("elongation"); plot.draw( x, speed ).title("speed"); plot.show(); return 0; }
/* apply relativistic light bending correction to ra/dec; stern * * The algorithm is from: * Mean and apparent place computations in the new IAU * system. III - Apparent, topocentric, and astrometric * places of planets and stars * KAPLAN, G. H.; HUGHES, J. A.; SEIDELMANN, P. K.; * SMITH, C. A.; YALLOP, B. D. * Astronomical Journal (ISSN 0004-6256), vol. 97, April 1989, p. 1197-1210. * * This article is a very good collection of formulea for geocentric and * topocentric place calculation in general. The apparent and * astrometric place calculation in this file currently does not follow * the strict algorithm from this paper and hence is not fully correct. * The entire calculation is currently based on the rotating EOD frame and * not the "inertial" J2000 frame. */ static void deflect ( double mjd1, /* equinox */ double lpd, double psi, /* heliocentric ecliptical long / lat */ double rsn, double lsn, /* distance and longitude of sun */ double rho, /* geocentric distance */ double *ra, double *dec)/* geocentric equatoreal */ { double hra, hdec; /* object heliocentric equatoreal */ double el; /* HELIOCENTRIC elongation object--earth */ double g1, g2; /* relativistic weights */ double u[3]; /* object geocentric cartesian */ double q[3]; /* object heliocentric cartesian unit vect */ double e[3]; /* earth heliocentric cartesian unit vect */ double qe, uq, eu; /* scalar products */ int i; /* counter */ #define G 1.32712438e20 /* heliocentric grav const; in m^3*s^-2 */ #define c 299792458.0 /* speed of light in m/s */ elongation(lpd, psi, lsn-PI, &el); el = fabs(el); /* only continue if object is within about 10 deg around the sun, * not obscured by the sun's disc (radius 0.25 deg) and farther away * than the sun. * * precise geocentric deflection is: g1 * tan(el/2) * radially outwards from sun; the vector munching below * just applys this component-wise * Note: el = HELIOCENTRIC elongation. * g1 is always about 0.004 arc seconds * g2 varies from 0 (highest contribution) to 2 */ if (el<degrad(170) || el>degrad(179.75) || rho<rsn) return; /* get cartesian vectors */ sphcart(*ra, *dec, rho, u, u+1, u+2); ecl_eq(mjd1, psi, lpd, &hra, &hdec); sphcart(hra, hdec, 1.0, q, q+1, q+2); ecl_eq(mjd1, 0.0, lsn-PI, &hra, &hdec); sphcart(hra, hdec, 1.0, e, e+1, e+2); /* evaluate scalar products */ qe = uq = eu = 0.0; for(i=0; i<=2; ++i) { qe += q[i]*e[i]; uq += u[i]*q[i]; eu += e[i]*u[i]; } g1 = 2*G/(c*c*MAU)/rsn; g2 = 1 + qe; /* now deflect geocentric vector */ g1 /= g2; for(i=0; i<=2; ++i) u[i] += g1*(uq*e[i] - eu*q[i]); /* back to spherical */ cartsph(u[0], u[1], u[2], ra, dec, &rho); /* rho thrown away */ }
static int obj_fixed (Now *np, Obj *op) { double lsn, rsn; /* true geoc lng of sun, dist from sn to earth*/ double lam, bet; /* geocentric ecliptic long and lat */ double ha; /* local hour angle */ double el; /* elongation */ double alt, az; /* current alt, az */ double ra, dec; /* ra and dec at equinox of date */ double rpm, dpm; /* astrometric ra and dec with PM to now */ double lst; /* on the assumption that the user will stick with their chosen display * epoch for a while, we move the defining values to match and avoid * precession for every call until it is changed again. * N.B. only compare and store jd's to lowest precission (f_epoch). * N.B. maintaining J2k ref (which is arbitrary) helps avoid accum err */ if (0 /* disabled in PyEphem */ && epoch != EOD && epoch != op->f_epoch) { double pr = op->f_RA, pd = op->f_dec, fe = epoch; /* first bring back to 2k */ precess (op->f_epoch, J2000, &pr, &pd); pr += op->f_pmRA*(J2000-op->f_epoch); pd += op->f_pmdec*(J2000-op->f_epoch); /* then to epoch */ pr += op->f_pmRA*(fe-J2000); pd += op->f_pmdec*(fe-J2000); precess (J2000, fe, &pr, &pd); op->f_RA = pr; op->f_dec = pd; op->f_epoch = fe; } /* apply proper motion .. assume pm epoch reference equals equinox */ rpm = op->f_RA + op->f_pmRA*(mjd-op->f_epoch); dpm = op->f_dec + op->f_pmdec*(mjd-op->f_epoch); /* set ra/dec to astrometric @ equinox of date */ ra = rpm; dec = dpm; if (op->f_epoch != mjed) precess (op->f_epoch, mjed, &ra, &dec); /* compute astrometric @ requested equinox */ op->s_astrora = rpm; op->s_astrodec = dpm; if (op->f_epoch != epoch) precess (op->f_epoch, epoch, &op->s_astrora, &op->s_astrodec); /* convert equatoreal ra/dec to mean geocentric ecliptic lat/long */ eq_ecl (mjed, ra, dec, &bet, &lam); /* find solar ecliptical long.(mean equinox) and distance from earth */ sunpos (mjed, &lsn, &rsn, NULL); /* allow for relativistic light bending near the sun */ deflect (mjed, lam, bet, lsn, rsn, 1e10, &ra, &dec); /* TODO: correction for annual parallax would go here */ /* correct EOD equatoreal for nutation/aberation to form apparent * geocentric */ nut_eq(mjed, &ra, &dec); ab_eq(mjed, lsn, &ra, &dec); op->s_gaera = ra; op->s_gaedec = dec; /* set s_ra/dec -- apparent */ op->s_ra = ra; op->s_dec = dec; /* compute elongation from ecliptic long/lat and sun geocentric long */ elongation (lam, bet, lsn, &el); el = raddeg(el); op->s_elong = (float)el; /* these are really the same fields ... op->s_mag = op->f_mag; op->s_size = op->f_size; */ /* alt, az: correct for refraction; use eod ra/dec. */ now_lst (np, &lst); ha = hrrad(lst) - ra; hadec_aa (lat, ha, dec, &alt, &az); refract (pressure, temp, alt, &alt); op->s_alt = alt; op->s_az = az; return (0); }
int main(int argc, char *argv[]) { PBASIS ptrue, pfit, ptry; OBSERVATION futobs, obsarray[MAXOBS], *obs; int nobs; double tt; ORBIT orbit; XVBASIS xv; double **covar, **covar_aei, **covar_xyz; double chisq; int dof; char inbuff[256]; double **sigxy,a,b,PA,**derivs; double lat,lon,**covecl; double ra,dec, **coveq; double xx,yy,xy,bovasqrd,det; double now, threshold, timestart, timespan, timeend; double besttime, bestvara, elong; int i, refit; if (argc!=4 || *argv[1]=='^') print_help(); /* echo the command line to output */ printf("#"); for (i=0; i<argc; i++) printf(" %s",argv[i]); { #include <time.h> time_t timettt; time(&timettt); /* note that ctime returns string with newline at end */ printf("\n#---%s",ctime(&timettt)); } sigxy = dmatrix(1,2,1,2); derivs = dmatrix(1,6,1,6); covar = dmatrix(1,6,1,6); covar_xyz = dmatrix(1,6,1,6); covar_aei = dmatrix(1,6,1,6); covecl = dmatrix(1,2,1,2); coveq = dmatrix(1,2,1,2); if (read_abg(argv[1],&ptrue,covar)) { fprintf(stderr, "Error input alpha/beta/gamma file %s\n",argv[1]); exit(1); } if ((threshold = atof(argv[2]))<=0.) { fprintf(stderr,"Bad observation threshold %s\n",argv[2]); print_help(); } if ((timespan = atof(argv[3]))<=0.) { fprintf(stderr,"Bad time span %s\n",argv[3]); print_help(); } /* Read in the initial observation times */ nobs = 0; while (fgets_nocomment(inbuff, 255, stdin, stdout)!=NULL) { obs = &(obsarray[nobs]); if (scan_observation(inbuff, obs)) exit(1); /* Set time to years after jd0, don't care about coordinates here*/ obs->obstime = (obs->obstime-jd0)*DAY; if (nobs==0) timestart = obs->obstime; /* Calculate the position of Earth at this time to avoid doing * it many times later: */ earth3d(obs->obstime, obs->obscode, &(obs->xe),&(obs->ye),&(obs->ze)); /* replace with faked position */ fake_observation(&ptrue, obs); print_radec(obs,stdout); printf("Reobserve time %.4f opp. angle %.2f\n", obs->obstime-timestart, opposition_angle(obs)/DTOR); nobs++; } /* Get an orbit fit*/ fit_observations(obsarray, nobs, &pfit, covar, &chisq, &dof, NULL); /*Save site and error limits to use in future */ obsarray[nobs].obscode = obsarray[nobs-1].obscode; obsarray[nobs].dthetax = obsarray[nobs-1].dthetax; obsarray[nobs].dthetay = obsarray[nobs-1].dthetay; timeend = timestart + timespan; bestvara = 1e10; besttime = 0.; for (now = obsarray[nobs-1].obstime; now <= timeend; ) { /*Advance observing time */ if ( now-timestart < 2*MONTH) now+= DAY; else now+=MONTH; /*Get position and x uncertainty*/ /* Predict position & examine uncertainty */ obsarray[nobs].obstime = now; obsarray[nobs].xe = -999.; /* Force evaluation of earth3d */ predict_posn(&pfit,covar,&obsarray[nobs],sigxy); /* Compute a, b, theta of error ellipse for output */ xx = sigxy[1][1]; yy = sigxy[2][2]; xy = sigxy[1][2]; PA = 0.5 * atan2(2.*xy,(xx-yy)) * 180./PI; /*go right to degrees*/ /* Adjust for PA to be N through E, */ PA = PA-90; if (PA<-90.) PA += 180.; bovasqrd = (xx+yy-sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) / (xx+yy+sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) ; det = xx*yy-xy*xy; b = pow(det*bovasqrd,0.25); a = pow(det/bovasqrd,0.25); /* See what uncertainty in a results from this obs.*/ fit_observations(obsarray, nobs+1, &ptry, covar_aei, &chisq, &dof, NULL); pbasis_to_bary(&ptry, &xv, derivs); covar_map(covar_aei, derivs, covar_xyz,6,6); orbitElements(&xv, &orbit); aei_derivs(&xv, derivs); covar_map(covar_xyz, derivs, covar_aei,6,6); /* Report results of this test to output */ printf("%7.4f %.2f %.2f %.2f %9.6f %.3g %5.1f %5.1f %d\n", now-timestart, obsarray[nobs].thetax/ARCSEC, obsarray[nobs].thetay/ARCSEC, a/ARCSEC, sqrt(covar_aei[1][1]), sqrt(covar_aei[2][2]), elong/DTOR, opposition_angle(&obsarray[nobs])/DTOR, nobs); /* Go to next date if Sun is too close */ elong = elongation(&obsarray[nobs]); if (elong < MIN_ELONG) continue; if (a > threshold*ARCSEC) { /* object is lost. See what prior observation was best * for constraining a, then add it and refit orbit, continue */ if (besttime<=0) { fprintf(stderr,"Object is lost before observation\n"); exit(1); } obsarray[nobs].obstime = besttime; obsarray[nobs].xe = -999.; fake_observation(&ptrue, &obsarray[nobs]); printf("Reobserve time %.4f opp. angle %.2f\n", besttime-timestart, opposition_angle(&obsarray[nobs])/DTOR); print_radec(&obsarray[nobs],stdout); nobs++; fit_observations(obsarray, nobs, &pfit, covar, &chisq, &dof, NULL); now = besttime; besttime = 0.; bestvara = 1e10; obsarray[nobs].obscode = obsarray[nobs-1].obscode; obsarray[nobs].dthetax = obsarray[nobs-1].dthetax; obsarray[nobs].dthetay = obsarray[nobs-1].dthetay; } else { /* Is this the best observation so far? */ if (covar_aei[1][1] < bestvara) { bestvara = covar_aei[1][1]; besttime = now; } } } /*Do a final observation*/ obsarray[nobs].obstime = besttime; obsarray[nobs].xe = -999.; fake_observation(&ptrue, &obsarray[nobs]); printf("Reobserve time %.4f opp. angle %.2f\n", besttime-timestart, opposition_angle(&obsarray[nobs])/DTOR); print_radec(&obsarray[nobs],stdout); nobs++; fit_observations(obsarray, nobs, &pfit, covar_aei, &chisq, &dof, NULL); pbasis_to_bary(&pfit, &xv, derivs); covar_map(covar_aei, derivs, covar_xyz,6,6); orbitElements(&xv, &orbit); aei_derivs(&xv, derivs); covar_map(covar_xyz, derivs, covar_aei,6,6); printf("Final uncertainty in a: %.3g\n", sqrt(covar_aei[1][1])); free_dmatrix(covar,1,6,1,6); free_dmatrix(covar_xyz,1,6,1,6); free_dmatrix(covar_aei,1,6,1,6); free_dmatrix(derivs,1,6,1,6); exit(0); }
int main(int argc, char *argv[]) { PBASIS p; OBSERVATION futobs; struct date_time dt; char inbuff[256],rastring[20],decstring[20]; double **covar,**sigxy,a,b,PA,**derivs; double lat,lon,**covecl; double ra,dec, **coveq; double yr,mo,day,hr,mn,ss; double xx,yy,xy,bovasqrd,det; int i,nfields; int iarg=1; if (argc>1 && *argv[1]=='^') print_help(); if (read_options(&iarg, argc, argv)) print_help(); if (iarg>=argc) print_help(); /* echo the command line to output */ printf("#"); for (i=0; i<argc; i++) printf(" %s",argv[i]); { #include <time.h> time_t timettt; time(&timettt); /* note that ctime returns string with newline at end */ printf("\n#---%s",ctime(&timettt)); } sigxy = dmatrix(1,2,1,2); derivs = dmatrix(1,2,1,2); covar = dmatrix(1,6,1,6); covecl = dmatrix(1,2,1,2); coveq = dmatrix(1,2,1,2); if (read_abg(argv[iarg],&p,covar)) { fprintf(stderr, "Error input alpha/beta/gamma file %s\n",argv[iarg]); exit(1); } /* get observatory code */ fprintf (stderr,"Enter observatory code:\n"); if (fgets_nocomment(inbuff,255,stdin,NULL)==NULL || sscanf(inbuff,"%d",&futobs.obscode)!=1) { fprintf(stderr,"Error reading observatory code\n"); exit(1); } printf("# For observations at site %d\n" "# x/RA y/DEC " "err_a err_b err_pa\n",futobs.obscode); fprintf (stderr,"Enter JD's or Y M D ... of observations, -1 to quit:\n"); while ( fgets_nocomment(inbuff,255,stdin,NULL)!=NULL) { nfields=sscanf(inbuff,"%lf %lf %lf %lf %lf %lf", &yr,&mo,&day,&hr,&mn,&ss); if (nfields==0 ) { fprintf(stderr,"Error on time spec:\n->%s\n",inbuff); exit(1); } else if (yr<0.) { /*done*/ exit(0); } else if (nfields==1 || nfields==2) { /* Got a JD. (probably...)*/ futobs.obstime = (yr-jd0)*DAY; } else { dt.y = yr; dt.mo = mo; dt.d = day; if (nfields>=4) dt.h = hr; else dt.h=0.; if (nfields>=5) dt.mn = mn; else dt.mn=0.; if (nfields>=6) dt.s = ss; else dt.s=0.; futobs.obstime = (date_to_jd(dt)-jd0)*DAY; } futobs.xe = -999.; /* Force evaluation of earth3d */ printf("At time= %s",inbuff); predict_posn(&p,covar,&futobs,sigxy); printf("# Solar Elongation = %.2f Opp angle = %.2f\n", elongation(&futobs)/DTOR,opposition_angle(&futobs)/DTOR); /* Compute a, b, theta of error ellipse for output */ xx = sigxy[1][1]; yy = sigxy[2][2]; xy = sigxy[1][2]; PA = 0.5 * atan2(2.*xy,(xx-yy)) * 180./PI; /*go right to degrees*/ /* Adjust for PA to be N through E, */ PA = PA-90; if (PA<-90.) PA += 180.; bovasqrd = (xx+yy-sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) / (xx+yy+sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) ; det = xx*yy-xy*xy; b = pow(det*bovasqrd,0.25); a = pow(det/bovasqrd,0.25); printf("Cum. ecliptic posn: %10.4f %10.4f %8.2f %8.2f %7.2f\n", futobs.thetax/ARCSEC, futobs.thetay/ARCSEC, a/ARCSEC,b/ARCSEC,PA); /* Now transform to RA/DEC, via ecliptic*/ proj_to_ec(futobs.thetax,futobs.thetay, &lat, &lon, lat0, lon0, derivs); /* map the covariance */ covar_map(sigxy, derivs, covecl, 2, 2); /* Now to ICRS: */ ec_to_eq(lat, lon, &ra, &dec, derivs); /* map the covariance */ covar_map(covecl, derivs, coveq, 2, 2); /* Compute a, b, theta of error ellipse for output */ xx = coveq[1][1]*cos(dec)*cos(dec); xy = coveq[1][2]*cos(dec); yy = coveq[2][2]; PA = 0.5 * atan2(2.*xy,(xx-yy)) * 180./PI; /*go right to degrees*/ /* Put PA N through E */ PA = 90.-PA; bovasqrd = (xx+yy-sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) / (xx+yy+sqrt(pow(xx-yy,2.)+pow(2.*xy,2.))) ; det = xx*yy-xy*xy; b = pow(det*bovasqrd,0.25); a = pow(det/bovasqrd,0.25); ra /= DTOR; if (ra<0.) ra+= 360.; dec /= DTOR; deghms(ra,rastring); degdms(dec,decstring); printf("ICRS position: %s %s %10.4f %10.4f %7.2f\n", rastring,decstring,a/ARCSEC,b/ARCSEC,PA); } exit(0); }