38 #include <cxstrutils.h>
40 #include <cpl_matrix.h>
42 #include "girvcorrection.h"
58 static const cxdouble dct0 = 2415020.0;
59 static const cxdouble dcjul = 36525.0;
60 static const cxdouble dc1900 = 1900.0;
61 static const cxdouble dctrop = 365.24219572;
62 static const cxdouble dcbes = 0.313;
64 static const cxdouble RV_DPI =
65 3.1415926535897932384626433832795028841971693993751;
67 static const cxdouble RV_D2PI =
68 6.2831853071795864769252867665590057683943387987502;
70 static const cxdouble RV_D4PI =
71 12.566370614359172953850573533118011536788677597500;
73 static const cxdouble RV_DPIBY2 =
74 1.5707963267948966192313216916397514420985846996876;
76 static const cxdouble RV_DD2R =
77 0.017453292519943295769236907684886127134428718885417;
79 static const cxdouble RV_DAS2R =
80 4.8481368110953599358991410235794797595635330237270e-6;
111 inline static cpl_matrix *
112 _giraffe_create_rotation(
const cxchar *mode, cxdouble phi, cxdouble theta,
116 cxint nrotations = strlen(mode);
118 cpl_matrix *
self = cpl_matrix_new(3, 3);
121 nrotations = nrotations <= 3 ? nrotations : 3;
128 cpl_matrix_fill_diagonal(
self, 1., 0);
136 if (nrotations > 0) {
138 const cxchar *_mode = cx_strlower(cx_strdup(mode));
140 register cxint i = 0;
142 cpl_matrix *R = cpl_matrix_new(3, 3);
144 cxdouble angle[3] = {phi, theta, psi};
145 cxdouble *_R = cpl_matrix_get_data(R);
148 for (i = 0; i < nrotations; ++i) {
150 cxdouble sa = sin(angle[i]);
151 cxdouble ca = cos(angle[i]);
153 cpl_matrix *mt = NULL;
156 cpl_matrix_fill(R, 0.);
193 cpl_matrix_delete(R);
194 cpl_matrix_delete(
self);
196 cx_free((cxchar*)_mode);
204 mt = cpl_matrix_product_create(R,
self);
206 cpl_matrix_delete(
self);
211 cpl_matrix_delete(R);
212 cx_free((cxchar *)_mode);
243 inline static cpl_matrix *
244 _giraffe_precession_matrix(cxdouble epoch0, cxdouble epoch1)
251 const cxdouble sigma0 = 2000.;
252 const cxdouble sigmaF = epoch0;
253 const cxdouble sigmaD = epoch1;
262 const cxdouble T = (sigmaF - sigma0) / 1000.;
263 const cxdouble t = (sigmaD - sigmaF) / 1000.;
266 cpl_matrix *mprc = NULL;
268 cxdouble thetaA = RV_DAS2R;
269 cxdouble zetaA = RV_DAS2R;
270 cxdouble zA = RV_DAS2R;
273 cxdouble T3 = T2 * T;
274 cxdouble T4 = T3 * T;
275 cxdouble T5 = T4 * T;
278 cxdouble t3 = t2 * t;
279 cxdouble t4 = t3 * t;
280 cxdouble t5 = t4 * t;
281 cxdouble t6 = t5 * t;
293 thetaA *= (20042.0207 - 85.3131 * T - 0.2111 * T2 + 0.3642 * T3 +
294 0.0008 * T4 -0.0005 * T5) * t +
295 (-42.6566 - 0.2111 * T + 0.5463 * T2 + 0.0017 * T3 -
297 (-41.8238 + 0.0359 * T + 0.0027 * T2 - 0.0001 * T3) * t3 +
298 (-0.0731 + 0.0019 * T + 0.0009 * T2) * t4 +
299 (-0.0127 + 0.0011 * T) * t5 +
302 zetaA *= (23060.9097 + 139.7495 * T - 0.0038 * T2 - 0.5918 * T3 -
303 0.0037 * T4 + 0.0007 * T5) * t +
304 (30.2226 - 0.2523 * T - 0.3840 * T2 - 0.0014 * T3 +
306 (18.0183 - 0.1326 * T + 0.0006 * T2 + 0.0005 * T3) * t3 +
307 (-0.0583 - 0.0001 * T + 0.0007 * T2) * t4 +
311 zA *= (23060.9097 + 139.7495 * T - 0.0038 * T2 - 0.5918 * T3 -
312 0.0037 * T4 + 0.0007 * T5) * t +
313 (109.5270 + 0.2446 * T - 1.3913 * T2 - 0.0134 * T3 +
315 (18.2667 - 1.1400 * T - 0.0173 * T2 + 0.0044 * T3) * t3 +
316 (-0.2821 - 0.0093 * T + 0.0032 * T2) * t4 +
317 (-0.0301 + 0.0006 * T) * t5 +
325 mprc = _giraffe_create_rotation(
"zyz", -zetaA, thetaA, -zA);
347 inline static cxdouble
348 sideral_time(cxdouble djd, cxdouble dlong)
356 const cxdouble d1 = 1.739935934667999;
357 const cxdouble d2 = 6.283319509909095e02;
358 const cxdouble d3 = 6.755878646261384e-06;
360 const cxdouble df = 1.00273790934;
366 cxdouble djd0 = floor(djd) + 0.5;
372 dut = (djd - djd0) * RV_D2PI;
374 dt = (djd0 - dct0) / dcjul;
375 dst0 = d1 + d2 * dt + d3 * dt * dt;
376 dst0 = fmod(dst0, RV_D2PI);
377 dst = df * dut + dst0 - dlong;
378 dst = fmod(dst + RV_D4PI, RV_D2PI);
415 inline static cxdouble
416 geo_correction(cxdouble dlat, cxdouble dalt, cxdouble dec, cxdouble dha)
423 const cxdouble da = 6378.137;
429 const cxdouble df = 1./298.257222;
435 const cxdouble dw = RV_D2PI/86164.;
438 const cxdouble de2 = df * (2.0 - df);
439 const cxdouble dsdlats = sin (dlat) * sin (dlat);
453 d1 = 1.0 - de2 * (2.0 - de2) * dsdlats;
454 d2 = 1.0 - de2 * dsdlats;
455 dr0 = da * sqrt(d1 / d2);
462 d1 = de2 * sin(2.0 * dlat);
464 dlatg = dlat - atan(d1 / d2);
471 drh = dr0 * cos(dlatg) + (dalt / 1000.) * cos(dlat);
479 dvelg = dw * drh * cos(dec) * sin(dha);
521 earth_velocity(cxdouble dje, cxdouble deq, cxdouble*
const hvel,
522 cxdouble*
const bvel)
532 const cxdouble dcfel[][3] = {
533 {1.7400353e+00, 6.2833195099091e+02, 5.2796e-06},
534 {6.2565836e+00, 6.2830194572674e+02, -2.6180e-06},
535 {4.7199666e+00, 8.3997091449254e+03, -1.9780e-05},
536 {1.9636505e-01, 8.4334662911720e+03, -5.6044e-05},
537 {4.1547339e+00, 5.2993466764997e+01, 5.8845e-06},
538 {4.6524223e+00, 2.1354275911213e+01, 5.6797e-06},
539 {4.2620486e+00, 7.5025342197656e+00, 5.5317e-06},
540 {1.4740694e+00, 3.8377331909193e+00, 5.6093e-06}
550 const cxdouble dceps[3] = {
556 const cxdouble ccsel[][3] = {
557 {1.675104e-02, -4.179579e-05, -1.260516e-07},
558 {2.220221e-01, 2.809917e-02, 1.852532e-05},
559 {1.589963e+00, 3.418075e-02, 1.430200e-05},
560 {2.994089e+00, 2.590824e-02, 4.155840e-06},
561 {8.155457e-01, 2.486352e-02, 6.836840e-06},
562 {1.735614e+00, 1.763719e-02, 6.370440e-06},
563 {1.968564e+00, 1.524020e-02, -2.517152e-06},
564 {1.282417e+00, 8.703393e-03, 2.289292e-05},
565 {2.280820e+00, 1.918010e-02, 4.484520e-06},
566 {4.833473e-02, 1.641773e-04, -4.654200e-07},
567 {5.589232e-02, -3.455092e-04, -7.388560e-07},
568 {4.634443e-02, -2.658234e-05, 7.757000e-08},
569 {8.997041e-03, 6.329728e-06, -1.939256e-09},
570 {2.284178e-02, -9.941590e-05, 6.787400e-08},
571 {4.350267e-02, -6.839749e-05, -2.714956e-07},
572 {1.348204e-02, 1.091504e-05, 6.903760e-07},
573 {3.106570e-02, -1.665665e-04, -1.590188e-07}
584 const cxdouble dcargs[][2] = {
585 {5.0974222e+00, -7.8604195454652e+02},
586 {3.9584962e+00, -5.7533848094674e+02},
587 {1.6338070e+00, -1.1506769618935e+03},
588 {2.5487111e+00, -3.9302097727326e+02},
589 {4.9255514e+00, -5.8849265665348e+02},
590 {1.3363463e+00, -5.5076098609303e+02},
591 {1.6072053e+00, -5.2237501616674e+02},
592 {1.3629480e+00, -1.1790629318198e+03},
593 {5.5657014e+00, -1.0977134971135e+03},
594 {5.0708205e+00, -1.5774000881978e+02},
595 {3.9318944e+00, 5.2963464780000e+01},
596 {4.8989497e+00, 3.9809289073258e+01},
597 {1.3097446e+00, 7.7540959633708e+01},
598 {3.5147141e+00, 7.9618578146517e+01},
599 {3.5413158e+00, -5.4868336758022e+02}
609 const cxdouble ccamps[][5] = {
610 {-2.279594e-5, 1.407414e-5, 8.273188e-6, 1.340565e-5, -2.490817e-7},
611 {-3.494537e-5, 2.860401e-7, 1.289448e-7, 1.627237e-5, -1.823138e-7},
612 { 6.593466e-7, 1.322572e-5, 9.258695e-6, -4.674248e-7, -3.646275e-7},
613 { 1.140767e-5, -2.049792e-5, -4.747930e-6, -2.638763e-6, -1.245408e-7},
614 { 9.516893e-6, -2.748894e-6, -1.319381e-6, -4.549908e-6, -1.864821e-7},
615 { 7.310990e-6, -1.924710e-6, -8.772849e-7, -3.334143e-6, -1.745256e-7},
616 {-2.603449e-6, 7.359472e-6, 3.168357e-6, 1.119056e-6, -1.655307e-7},
617 {-3.228859e-6, 1.308997e-7, 1.013137e-7, 2.403899e-6, -3.736225e-7},
618 { 3.442177e-7, 2.671323e-6, 1.832858e-6, -2.394688e-7, -3.478444e-7},
619 { 8.702406e-6, -8.421214e-6, -1.372341e-6, -1.455234e-6, -4.998479e-8},
620 {-1.488378e-6, -1.251789e-5, 5.226868e-7, -2.049301e-7, 0.0e0},
621 {-8.043059e-6, -2.991300e-6, 1.473654e-7, -3.154542e-7, 0.0e0},
622 { 3.699128e-6, -3.316126e-6, 2.901257e-7, 3.407826e-7, 0.0e0},
623 { 2.550120e-6, -1.241123e-6, 9.901116e-8, 2.210482e-7, 0.0e0},
624 {-6.351059e-7, 2.341650e-6, 1.061492e-6, 2.878231e-7, 0.0e0}
634 const cxdouble ccsec3 = -7.757020e-08;
636 const cxdouble ccsec[][3] = {
637 {1.289600e-06, 5.550147e-01, 2.076942e+00},
638 {3.102810e-05, 4.035027e+00, 3.525565e-01},
639 {9.124190e-06, 9.990265e-01, 2.622706e+00},
640 {9.793240e-07, 5.508259e+00, 1.559103e+01}
648 const cxdouble dcsld = 1.990987e-07;
649 const cxdouble ccsgd = 1.990969e-07;
657 const cxdouble cckm = 3.122140e-05;
658 const cxdouble ccmld = 2.661699e-06;
659 const cxdouble ccfdi = 2.399485e-07;
669 const cxdouble dcargm[][2] = {
670 {5.1679830e+00, 8.3286911095275e+03},
671 {5.4913150e+00, -7.2140632838100e+03},
672 {5.9598530e+00, 1.5542754389685e+04}
681 const cxdouble ccampm[][4] = {
682 { 1.097594e-01, 2.896773e-07, 5.450474e-02, 1.438491e-07},
683 {-2.223581e-02, 5.083103e-08, 1.002548e-02, -2.291823e-08},
684 { 1.148966e-02, 5.658888e-08, 8.249439e-03, 4.063015e-08}
692 const cxdouble ccpamv[4] = {
704 const cxdouble dc1mme = 0.99999696;
707 register cxint k = 0;
708 register cxint n = 0;
721 cxdouble dlocal = 0.;
724 cxdouble pertld = 0.;
726 cxdouble pertrd = 0.;
728 cxdouble pertpd = 0.;
734 cxdouble dparam = 0.;
742 cxdouble d1pdro = 0.;
745 cxdouble dsinls = 0.;
746 cxdouble dcosls = 0.;
760 cxdouble dcosep = 0.;
761 cxdouble dsinep = 0.;
766 cxdouble sn[4] = {0., 0., 0., 0.};
767 cxdouble sinlp[4] = {0., 0., 0., 0.};
768 cxdouble coslp[4] = {0., 0., 0., 0.};
769 cxdouble forbel[7] = {0., 0., 0., 0., 0., 0., 0.};
773 memset(sorbel, 0,
sizeof sorbel);
781 dt = (dje - dct0) / dcjul;
791 for (k = 0; k < 8; k++) {
793 dlocal = fmod(dcfel[k][0] + dt * dcfel[k][1] + dtsq * dcfel[k][2],
801 forbel[k - 1] = dlocal;
806 deps = fmod(dceps[0] + dt * dceps[1] + dtsq * dceps[2], RV_D2PI);
808 for (k = 0; k < 17; k++) {
810 sorbel[k] = fmod(ccsel[k][0] + t * ccsel[k][1] + tsq * ccsel[k][2],
820 for (k = 0; k < 4; k++) {
822 a = fmod(ccsec[k][1] + t * ccsec[k][2], RV_D2PI);
832 pertl = ccsec[0][0] * sn[0] + ccsec[1][0] * sn[1] +
833 (ccsec[2][0] + t * ccsec3) * sn[2] + ccsec[3][0] * sn[3];
839 for (k = 0; k < 15; k++) {
841 a = fmod(dcargs[k][0] + dt * dcargs[k][1], RV_D2PI);
844 pertl += (ccamps[k][0] * cosa + ccamps[k][1] * sina);
845 pertr += (ccamps[k][2] * cosa + ccamps[k][3] * sina);
851 pertld += ((ccamps[k][1] * cosa - ccamps[k][0] * sina) * ccamps[k][4]);
852 pertrd += ((ccamps[k][3] * cosa - ccamps[k][2] * sina) * ccamps[k][4]);
861 esq = sorbel[0] * sorbel[0];
864 twoe = sorbel[0] + sorbel[0];
865 twog = forbel[0] + forbel[0];
866 phi = twoe * ((1.0 - esq * (1.0 / 8.0)) * sin (forbel[0]) +
867 sorbel[0] * (5.0 / 8.0) * sin (twog) +
868 esq * 0.5416667 * sin (forbel[0] + twog));
872 dpsi = dparam / (1. + sorbel[0] * cos_f);
873 phid = twoe * ccsgd * ((1.0 + esq * 1.50) * cos_f +
874 sorbel[0] * (1.250 - sin_f * sin_f * 0.50));
875 psid = ccsgd * sorbel[0] * sin_f / sqrt(param);
883 drd = d1pdro * (psid + dpsi * pertrd);
884 drld = d1pdro * dpsi * (dcsld + phid + pertld);
885 dtl = fmod(dml + phi + pertl, RV_D2PI);
888 dxhd = drd * dcosls - drld * dsinls;
889 dyhd = drd * dsinls + drld * dcosls;
902 for (k = 0; k < 3; k++) {
904 a = fmod(dcargm[k][0] + dt * dcargm[k][1], RV_D2PI);
907 pertl += ccampm[k][0] * sina;
908 pertld += ccampm[k][1] * cosa;
909 pertp += ccampm[k][2] * cosa;
910 pertpd -= ccampm[k][3] * sina;
919 tl = forbel[1] + pertl;
922 sigma = cckm / (1. + pertp);
923 a = sigma * (ccmld + pertld);
925 dxhd = dxhd + a * sinlm + b * coslm;
926 dyhd = dyhd - a * coslm + b * sinlm;
927 dzhd = -sigma * ccfdi * cos(forbel[2]);
934 dxbd = dxhd * dc1mme;
935 dybd = dyhd * dc1mme;
936 dzbd = dzhd * dc1mme;
938 for (k = 0; k < 4; k++) {
940 plon = forbel[k + 3];
941 pomg = sorbel[k + 1];
942 pecc = sorbel[k + 9];
943 tl = fmod(plon + 2.0 * pecc * sin (plon - pomg), RV_D2PI);
946 dxbd = dxbd + ccpamv[k] * (sinlp[k] + pecc * sin(pomg));
947 dybd = dybd - ccpamv[k] * (coslp[k] + pecc * cos(pomg));
948 dzbd = dzbd - ccpamv[k] * sorbel[k + 13] * cos(plon - sorbel[k + 5]);
959 dyahd = dcosep * dyhd - dsinep * dzhd;
960 dzahd = dsinep * dyhd + dcosep * dzhd;
961 dyabd = dcosep * dybd - dsinep * dzbd;
962 dzabd = dsinep * dybd + dcosep * dzbd;
981 cxdouble deqdat = (dje - dct0 - dcbes) / dctrop + dc1900;
983 cpl_matrix* prec = _giraffe_precession_matrix(deqdat, deq);
986 for (n = 0; n < 3; n++) {
989 dxhd * cpl_matrix_get(prec, 0, n) +
990 dyahd * cpl_matrix_get(prec, 1, n) +
991 dzahd * cpl_matrix_get(prec, 2, n);
994 dxbd * cpl_matrix_get(prec, 0, n) +
995 dyabd * cpl_matrix_get(prec, 1, n) +
996 dzabd * cpl_matrix_get(prec, 2, n);
999 cpl_matrix_delete(prec);
1047 cxdouble jdate, cxdouble longitude,
1048 cxdouble latitude, cxdouble elevation,
1049 cxdouble ra, cxdouble dec,
1055 const cxdouble aukm = 1.4959787e08;
1061 cxdouble dc[3] = {0., 0., 0.};
1062 cxdouble dcc[3] = {0., 0., 0.};
1063 cxdouble hv[3] = {0., 0., 0.};
1064 cxdouble bv[3] = {0., 0., 0.};
1065 cxdouble _long = longitude * RV_DD2R;
1066 cxdouble _lat = latitude * RV_DD2R;
1067 cxdouble _ra = ra * 15.0 * RV_DD2R;
1068 cxdouble _dec = dec * RV_DD2R;
1069 cxdouble st = sideral_time(jdate, _long);
1071 cpl_matrix* precession = NULL;
1078 eqt = (jdate - dct0 - dcbes) / dctrop + dc1900;
1080 dc[0] = cos(_ra) * cos(_dec);
1081 dc[1] = sin(_ra) * cos(_dec);
1084 precession = _giraffe_precession_matrix(equinox, eqt);
1086 for (i = 0; i < 3; ++i) {
1089 dc[0] * cpl_matrix_get(precession, i, 0) +
1090 dc[1] * cpl_matrix_get(precession, i, 1) +
1091 dc[2] * cpl_matrix_get(precession, i, 2);
1095 cpl_matrix_delete(precession);
1101 cxdouble darg = dcc[1] / dcc[0];
1127 dec2 = asin(dcc[2]);
1142 rv->gc = geo_correction(_lat, elevation, dec2, -ha);
1150 earth_velocity (jdate, eqt, hv, bv);
1161 for (i = 0; i < 3; ++i) {
1162 rv->bc += bv[i] * dcc[i] * aukm;
1163 rv->hc += hv[i] * dcc[i] * aukm;
void giraffe_rvcorrection_compute(GiRvCorrection *rv, cxdouble jdate, cxdouble longitude, cxdouble latitude, cxdouble elevation, cxdouble ra, cxdouble dec, cxdouble equinox)
Compute heliocentric, barycentric and geocentric correction.