30 #include <cxstrutils.h>
32 #include <cpl_matrix.h>
34 #include "girvcorrection.h"
50 static const cxdouble dct0 = 2415020.0;
51 static const cxdouble dcjul = 36525.0;
52 static const cxdouble dc1900 = 1900.0;
53 static const cxdouble dctrop = 365.24219572;
54 static const cxdouble dcbes = 0.313;
56 static const cxdouble RV_DPI =
57 3.1415926535897932384626433832795028841971693993751;
59 static const cxdouble RV_D2PI =
60 6.2831853071795864769252867665590057683943387987502;
62 static const cxdouble RV_D4PI =
63 12.566370614359172953850573533118011536788677597500;
65 static const cxdouble RV_DPIBY2 =
66 1.5707963267948966192313216916397514420985846996876;
68 static const cxdouble RV_DD2R =
69 0.017453292519943295769236907684886127134428718885417;
71 static const cxdouble RV_DAS2R =
72 4.8481368110953599358991410235794797595635330237270e-6;
103 inline static cpl_matrix *
104 _giraffe_create_rotation(
const cxchar *mode, cxdouble phi, cxdouble theta,
108 cxint nrotations = strlen(mode);
110 cpl_matrix *
self = cpl_matrix_new(3, 3);
113 nrotations = nrotations <= 3 ? nrotations : 3;
120 cpl_matrix_fill_diagonal(
self, 1., 0);
128 if (nrotations > 0) {
130 const cxchar *_mode = cx_strlower(cx_strdup(mode));
132 register cxint i = 0;
134 cpl_matrix *R = cpl_matrix_new(3, 3);
136 cxdouble angle[3] = {phi, theta, psi};
137 cxdouble *_R = cpl_matrix_get_data(R);
140 for (i = 0; i < nrotations; ++i) {
142 cxdouble sa = sin(angle[i]);
143 cxdouble ca = cos(angle[i]);
145 cpl_matrix *mt = NULL;
148 cpl_matrix_fill(R, 0.);
185 cpl_matrix_delete(R);
186 cpl_matrix_delete(
self);
188 cx_free((cxchar*)_mode);
196 mt = cpl_matrix_product_create(R,
self);
198 cpl_matrix_delete(
self);
203 cpl_matrix_delete(R);
204 cx_free((cxchar *)_mode);
235 inline static cpl_matrix *
236 _giraffe_precession_matrix(cxdouble epoch0, cxdouble epoch1)
243 const cxdouble sigma0 = 2000.;
244 const cxdouble sigmaF = epoch0;
245 const cxdouble sigmaD = epoch1;
254 const cxdouble T = (sigmaF - sigma0) / 1000.;
255 const cxdouble t = (sigmaD - sigmaF) / 1000.;
258 cpl_matrix *mprc = NULL;
260 cxdouble thetaA = RV_DAS2R;
261 cxdouble zetaA = RV_DAS2R;
262 cxdouble zA = RV_DAS2R;
265 cxdouble T3 = T2 * T;
266 cxdouble T4 = T3 * T;
267 cxdouble T5 = T4 * T;
270 cxdouble t3 = t2 * t;
271 cxdouble t4 = t3 * t;
272 cxdouble t5 = t4 * t;
273 cxdouble t6 = t5 * t;
285 thetaA *= (20042.0207 - 85.3131 * T - 0.2111 * T2 + 0.3642 * T3 +
286 0.0008 * T4 -0.0005 * T5) * t +
287 (-42.6566 - 0.2111 * T + 0.5463 * T2 + 0.0017 * T3 -
289 (-41.8238 + 0.0359 * T + 0.0027 * T2 - 0.0001 * T3) * t3 +
290 (-0.0731 + 0.0019 * T + 0.0009 * T2) * t4 +
291 (-0.0127 + 0.0011 * T) * t5 +
294 zetaA *= (23060.9097 + 139.7495 * T - 0.0038 * T2 - 0.5918 * T3 -
295 0.0037 * T4 + 0.0007 * T5) * t +
296 (30.2226 - 0.2523 * T - 0.3840 * T2 - 0.0014 * T3 +
298 (18.0183 - 0.1326 * T + 0.0006 * T2 + 0.0005 * T3) * t3 +
299 (-0.0583 - 0.0001 * T + 0.0007 * T2) * t4 +
303 zA *= (23060.9097 + 139.7495 * T - 0.0038 * T2 - 0.5918 * T3 -
304 0.0037 * T4 + 0.0007 * T5) * t +
305 (109.5270 + 0.2446 * T - 1.3913 * T2 - 0.0134 * T3 +
307 (18.2667 - 1.1400 * T - 0.0173 * T2 + 0.0044 * T3) * t3 +
308 (-0.2821 - 0.0093 * T + 0.0032 * T2) * t4 +
309 (-0.0301 + 0.0006 * T) * t5 +
317 mprc = _giraffe_create_rotation(
"zyz", -zetaA, thetaA, -zA);
339 inline static cxdouble
340 sideral_time(cxdouble djd, cxdouble dlong)
348 const cxdouble d1 = 1.739935934667999;
349 const cxdouble d2 = 6.283319509909095e02;
350 const cxdouble d3 = 6.755878646261384e-06;
352 const cxdouble df = 1.00273790934;
358 cxdouble djd0 = floor(djd) + 0.5;
364 dut = (djd - djd0) * RV_D2PI;
366 dt = (djd0 - dct0) / dcjul;
367 dst0 = d1 + d2 * dt + d3 * dt * dt;
368 dst0 = fmod(dst0, RV_D2PI);
369 dst = df * dut + dst0 - dlong;
370 dst = fmod(dst + RV_D4PI, RV_D2PI);
407 inline static cxdouble
408 geo_correction(cxdouble dlat, cxdouble dalt, cxdouble dec, cxdouble dha)
415 const cxdouble da = 6378.137;
421 const cxdouble df = 1./298.257222;
427 const cxdouble dw = RV_D2PI/86164.;
430 const cxdouble de2 = df * (2.0 - df);
431 const cxdouble dsdlats = sin (dlat) * sin (dlat);
445 d1 = 1.0 - de2 * (2.0 - de2) * dsdlats;
446 d2 = 1.0 - de2 * dsdlats;
447 dr0 = da * sqrt(d1 / d2);
454 d1 = de2 * sin(2.0 * dlat);
456 dlatg = dlat - atan(d1 / d2);
463 drh = dr0 * cos(dlatg) + (dalt / 1000.) * cos(dlat);
471 dvelg = dw * drh * cos(dec) * sin(dha);
513 earth_velocity(cxdouble dje, cxdouble deq, cxdouble*
const hvel,
514 cxdouble*
const bvel)
524 const cxdouble dcfel[][3] = {
525 {1.7400353e+00, 6.2833195099091e+02, 5.2796e-06},
526 {6.2565836e+00, 6.2830194572674e+02, -2.6180e-06},
527 {4.7199666e+00, 8.3997091449254e+03, -1.9780e-05},
528 {1.9636505e-01, 8.4334662911720e+03, -5.6044e-05},
529 {4.1547339e+00, 5.2993466764997e+01, 5.8845e-06},
530 {4.6524223e+00, 2.1354275911213e+01, 5.6797e-06},
531 {4.2620486e+00, 7.5025342197656e+00, 5.5317e-06},
532 {1.4740694e+00, 3.8377331909193e+00, 5.6093e-06}
542 const cxdouble dceps[3] = {
548 const cxdouble ccsel[][3] = {
549 {1.675104e-02, -4.179579e-05, -1.260516e-07},
550 {2.220221e-01, 2.809917e-02, 1.852532e-05},
551 {1.589963e+00, 3.418075e-02, 1.430200e-05},
552 {2.994089e+00, 2.590824e-02, 4.155840e-06},
553 {8.155457e-01, 2.486352e-02, 6.836840e-06},
554 {1.735614e+00, 1.763719e-02, 6.370440e-06},
555 {1.968564e+00, 1.524020e-02, -2.517152e-06},
556 {1.282417e+00, 8.703393e-03, 2.289292e-05},
557 {2.280820e+00, 1.918010e-02, 4.484520e-06},
558 {4.833473e-02, 1.641773e-04, -4.654200e-07},
559 {5.589232e-02, -3.455092e-04, -7.388560e-07},
560 {4.634443e-02, -2.658234e-05, 7.757000e-08},
561 {8.997041e-03, 6.329728e-06, -1.939256e-09},
562 {2.284178e-02, -9.941590e-05, 6.787400e-08},
563 {4.350267e-02, -6.839749e-05, -2.714956e-07},
564 {1.348204e-02, 1.091504e-05, 6.903760e-07},
565 {3.106570e-02, -1.665665e-04, -1.590188e-07}
576 const cxdouble dcargs[][2] = {
577 {5.0974222e+00, -7.8604195454652e+02},
578 {3.9584962e+00, -5.7533848094674e+02},
579 {1.6338070e+00, -1.1506769618935e+03},
580 {2.5487111e+00, -3.9302097727326e+02},
581 {4.9255514e+00, -5.8849265665348e+02},
582 {1.3363463e+00, -5.5076098609303e+02},
583 {1.6072053e+00, -5.2237501616674e+02},
584 {1.3629480e+00, -1.1790629318198e+03},
585 {5.5657014e+00, -1.0977134971135e+03},
586 {5.0708205e+00, -1.5774000881978e+02},
587 {3.9318944e+00, 5.2963464780000e+01},
588 {4.8989497e+00, 3.9809289073258e+01},
589 {1.3097446e+00, 7.7540959633708e+01},
590 {3.5147141e+00, 7.9618578146517e+01},
591 {3.5413158e+00, -5.4868336758022e+02}
601 const cxdouble ccamps[][5] = {
602 {-2.279594e-5, 1.407414e-5, 8.273188e-6, 1.340565e-5, -2.490817e-7},
603 {-3.494537e-5, 2.860401e-7, 1.289448e-7, 1.627237e-5, -1.823138e-7},
604 { 6.593466e-7, 1.322572e-5, 9.258695e-6, -4.674248e-7, -3.646275e-7},
605 { 1.140767e-5, -2.049792e-5, -4.747930e-6, -2.638763e-6, -1.245408e-7},
606 { 9.516893e-6, -2.748894e-6, -1.319381e-6, -4.549908e-6, -1.864821e-7},
607 { 7.310990e-6, -1.924710e-6, -8.772849e-7, -3.334143e-6, -1.745256e-7},
608 {-2.603449e-6, 7.359472e-6, 3.168357e-6, 1.119056e-6, -1.655307e-7},
609 {-3.228859e-6, 1.308997e-7, 1.013137e-7, 2.403899e-6, -3.736225e-7},
610 { 3.442177e-7, 2.671323e-6, 1.832858e-6, -2.394688e-7, -3.478444e-7},
611 { 8.702406e-6, -8.421214e-6, -1.372341e-6, -1.455234e-6, -4.998479e-8},
612 {-1.488378e-6, -1.251789e-5, 5.226868e-7, -2.049301e-7, 0.0e0},
613 {-8.043059e-6, -2.991300e-6, 1.473654e-7, -3.154542e-7, 0.0e0},
614 { 3.699128e-6, -3.316126e-6, 2.901257e-7, 3.407826e-7, 0.0e0},
615 { 2.550120e-6, -1.241123e-6, 9.901116e-8, 2.210482e-7, 0.0e0},
616 {-6.351059e-7, 2.341650e-6, 1.061492e-6, 2.878231e-7, 0.0e0}
626 const cxdouble ccsec3 = -7.757020e-08;
628 const cxdouble ccsec[][3] = {
629 {1.289600e-06, 5.550147e-01, 2.076942e+00},
630 {3.102810e-05, 4.035027e+00, 3.525565e-01},
631 {9.124190e-06, 9.990265e-01, 2.622706e+00},
632 {9.793240e-07, 5.508259e+00, 1.559103e+01}
640 const cxdouble dcsld = 1.990987e-07;
641 const cxdouble ccsgd = 1.990969e-07;
649 const cxdouble cckm = 3.122140e-05;
650 const cxdouble ccmld = 2.661699e-06;
651 const cxdouble ccfdi = 2.399485e-07;
661 const cxdouble dcargm[][2] = {
662 {5.1679830e+00, 8.3286911095275e+03},
663 {5.4913150e+00, -7.2140632838100e+03},
664 {5.9598530e+00, 1.5542754389685e+04}
673 const cxdouble ccampm[][4] = {
674 { 1.097594e-01, 2.896773e-07, 5.450474e-02, 1.438491e-07},
675 {-2.223581e-02, 5.083103e-08, 1.002548e-02, -2.291823e-08},
676 { 1.148966e-02, 5.658888e-08, 8.249439e-03, 4.063015e-08}
684 const cxdouble ccpamv[4] = {
696 const cxdouble dc1mme = 0.99999696;
699 register cxint k = 0;
700 register cxint n = 0;
713 cxdouble dlocal = 0.;
716 cxdouble pertld = 0.;
718 cxdouble pertrd = 0.;
720 cxdouble pertpd = 0.;
726 cxdouble dparam = 0.;
734 cxdouble d1pdro = 0.;
737 cxdouble dsinls = 0.;
738 cxdouble dcosls = 0.;
752 cxdouble dcosep = 0.;
753 cxdouble dsinep = 0.;
758 cxdouble sn[4] = {0., 0., 0., 0.};
759 cxdouble sinlp[4] = {0., 0., 0., 0.};
760 cxdouble coslp[4] = {0., 0., 0., 0.};
761 cxdouble forbel[7] = {0., 0., 0., 0., 0., 0., 0.};
765 memset(sorbel, 0,
sizeof sorbel);
773 dt = (dje - dct0) / dcjul;
783 for (k = 0; k < 8; k++) {
785 dlocal = fmod(dcfel[k][0] + dt * dcfel[k][1] + dtsq * dcfel[k][2],
793 forbel[k - 1] = dlocal;
798 deps = fmod(dceps[0] + dt * dceps[1] + dtsq * dceps[2], RV_D2PI);
800 for (k = 0; k < 17; k++) {
802 sorbel[k] = fmod(ccsel[k][0] + t * ccsel[k][1] + tsq * ccsel[k][2],
812 for (k = 0; k < 4; k++) {
814 a = fmod(ccsec[k][1] + t * ccsec[k][2], RV_D2PI);
824 pertl = ccsec[0][0] * sn[0] + ccsec[1][0] * sn[1] +
825 (ccsec[2][0] + t * ccsec3) * sn[2] + ccsec[3][0] * sn[3];
831 for (k = 0; k < 15; k++) {
833 a = fmod(dcargs[k][0] + dt * dcargs[k][1], RV_D2PI);
836 pertl += (ccamps[k][0] * cosa + ccamps[k][1] * sina);
837 pertr += (ccamps[k][2] * cosa + ccamps[k][3] * sina);
843 pertld += ((ccamps[k][1] * cosa - ccamps[k][0] * sina) * ccamps[k][4]);
844 pertrd += ((ccamps[k][3] * cosa - ccamps[k][2] * sina) * ccamps[k][4]);
853 esq = sorbel[0] * sorbel[0];
856 twoe = sorbel[0] + sorbel[0];
857 twog = forbel[0] + forbel[0];
858 phi = twoe * ((1.0 - esq * (1.0 / 8.0)) * sin (forbel[0]) +
859 sorbel[0] * (5.0 / 8.0) * sin (twog) +
860 esq * 0.5416667 * sin (forbel[0] + twog));
864 dpsi = dparam / (1. + sorbel[0] * cos_f);
865 phid = twoe * ccsgd * ((1.0 + esq * 1.50) * cos_f +
866 sorbel[0] * (1.250 - sin_f * sin_f * 0.50));
867 psid = ccsgd * sorbel[0] * sin_f / sqrt(param);
875 drd = d1pdro * (psid + dpsi * pertrd);
876 drld = d1pdro * dpsi * (dcsld + phid + pertld);
877 dtl = fmod(dml + phi + pertl, RV_D2PI);
880 dxhd = drd * dcosls - drld * dsinls;
881 dyhd = drd * dsinls + drld * dcosls;
894 for (k = 0; k < 3; k++) {
896 a = fmod(dcargm[k][0] + dt * dcargm[k][1], RV_D2PI);
899 pertl += ccampm[k][0] * sina;
900 pertld += ccampm[k][1] * cosa;
901 pertp += ccampm[k][2] * cosa;
902 pertpd -= ccampm[k][3] * sina;
911 tl = forbel[1] + pertl;
914 sigma = cckm / (1. + pertp);
915 a = sigma * (ccmld + pertld);
917 dxhd = dxhd + a * sinlm + b * coslm;
918 dyhd = dyhd - a * coslm + b * sinlm;
919 dzhd = -sigma * ccfdi * cos(forbel[2]);
926 dxbd = dxhd * dc1mme;
927 dybd = dyhd * dc1mme;
928 dzbd = dzhd * dc1mme;
930 for (k = 0; k < 4; k++) {
932 plon = forbel[k + 3];
933 pomg = sorbel[k + 1];
934 pecc = sorbel[k + 9];
935 tl = fmod(plon + 2.0 * pecc * sin (plon - pomg), RV_D2PI);
938 dxbd = dxbd + ccpamv[k] * (sinlp[k] + pecc * sin(pomg));
939 dybd = dybd - ccpamv[k] * (coslp[k] + pecc * cos(pomg));
940 dzbd = dzbd - ccpamv[k] * sorbel[k + 13] * cos(plon - sorbel[k + 5]);
951 dyahd = dcosep * dyhd - dsinep * dzhd;
952 dzahd = dsinep * dyhd + dcosep * dzhd;
953 dyabd = dcosep * dybd - dsinep * dzbd;
954 dzabd = dsinep * dybd + dcosep * dzbd;
973 cxdouble deqdat = (dje - dct0 - dcbes) / dctrop + dc1900;
975 cpl_matrix* prec = _giraffe_precession_matrix(deqdat, deq);
978 for (n = 0; n < 3; n++) {
981 dxhd * cpl_matrix_get(prec, 0, n) +
982 dyahd * cpl_matrix_get(prec, 1, n) +
983 dzahd * cpl_matrix_get(prec, 2, n);
986 dxbd * cpl_matrix_get(prec, 0, n) +
987 dyabd * cpl_matrix_get(prec, 1, n) +
988 dzabd * cpl_matrix_get(prec, 2, n);
991 cpl_matrix_delete(prec);
1039 cxdouble jdate, cxdouble longitude,
1040 cxdouble latitude, cxdouble elevation,
1041 cxdouble ra, cxdouble dec,
1047 const cxdouble aukm = 1.4959787e08;
1053 cxdouble dc[3] = {0., 0., 0.};
1054 cxdouble dcc[3] = {0., 0., 0.};
1055 cxdouble hv[3] = {0., 0., 0.};
1056 cxdouble bv[3] = {0., 0., 0.};
1057 cxdouble _long = longitude * RV_DD2R;
1058 cxdouble _lat = latitude * RV_DD2R;
1059 cxdouble _ra = ra * 15.0 * RV_DD2R;
1060 cxdouble _dec = dec * RV_DD2R;
1061 cxdouble st = sideral_time(jdate, _long);
1063 cpl_matrix* precession = NULL;
1070 eqt = (jdate - dct0 - dcbes) / dctrop + dc1900;
1072 dc[0] = cos(_ra) * cos(_dec);
1073 dc[1] = sin(_ra) * cos(_dec);
1076 precession = _giraffe_precession_matrix(equinox, eqt);
1078 for (i = 0; i < 3; ++i) {
1081 dc[0] * cpl_matrix_get(precession, i, 0) +
1082 dc[1] * cpl_matrix_get(precession, i, 1) +
1083 dc[2] * cpl_matrix_get(precession, i, 2);
1087 cpl_matrix_delete(precession);
1093 cxdouble darg = dcc[1] / dcc[0];
1119 dec2 = asin(dcc[2]);
1134 rv->gc = geo_correction(_lat, elevation, dec2, -ha);
1142 earth_velocity (jdate, eqt, hv, bv);
1153 for (i = 0; i < 3; ++i) {
1154 rv->bc += bv[i] * dcc[i] * aukm;
1155 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.