00001 #pragma ident "$Id: EarthSolidTide.cpp 2457 2010-08-18 14:20:12Z coandrei $"
00002
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "EarthSolidTide.hpp"
00032 #include "IERS.hpp"
00033 #include "UTCTime.hpp"
00034 #include "ReferenceFrames.hpp"
00035 #include <complex>
00036 #include "ASConstant.hpp"
00037
00038 namespace gpstk
00039 {
00040 using namespace std;
00041
00042
00043
00044
00045
00046
00047 const double EarthSolidTide::Argu_C21[48][7]=
00048 {
00049 -0.1, 0, 2, 0, 2, 0, 2,
00050 -0.1, 0, 0, 0, 2, 2, 2,
00051 -0.1, 0, 1, 0, 2, 0, 1,
00052 -0.7, 0.1, 1, 0, 2, 0, 2,
00053 -0.1, 0, -1, 0, 2, 2, 2,
00054 -1.3, 0.1, 0, 0, 2, 0, 1,
00055 -6.8, 0.6, 0, 0, 2, 0, 2,
00056 0.1, 0, 0, 0, 0, 2, 0,
00057 0.1, 0, 1, 0, 2, -2, 2,
00058 0.1, 0, -1, 0, 2, 0, 1,
00059 0.4, 0, -1, 0, 2, 0, 2,
00060 1.3, -0.1, 1, 0, 0, 0, 0,
00061 0.3, 0, 1, 0, 0, 0, 1,
00062 0.3, 0, -1, 0, 0, 2, 0,
00063 0.1, 0, -1, 0, 0, 2, 1,
00064 -1.9, 0.1, 0, 1, 2, -2, 2,
00065 0.5, 0, 0, 0, 2, -2, 1,
00066 -43.4, 2.9, 0, 0, 2, -2, 2,
00067 0.6, 0, 0, -1, 2, -2, 2,
00068 1.6, -0.1, 0, 1, 0, 0, 0,
00069 0.1, 0, -2, 0, 2, 0, 1,
00070 0.1, 0, 0, 0, 0, 0, -2,
00071 -8.8, 0.5, 0, 0, 0, 0, -1,
00072 470.9, -30.2, 0, 0, 0, 0, 0,
00073 68.1, -4.6, 0, 0, 0, 0, 1,
00074 -1.6, 0.1, 0, 0, 0, 0, 2,
00075 0.1, 0, -1, 0, 0, 1, 0,
00076 -0.1, 0, 0, -1, 0, 0, -1,
00077 -20.6, -0.3, 0, -1, 0, 0, 0,
00078 0.3, 0, 0, 1, -2, 2, -2,
00079 -0.3, 0, 0, -1, 0, 0, 1,
00080 -0.2, 0, -2, 0, 0, 2, 0,
00081 -0.1, 0, -2, 0, 0, 2, 1,
00082 -5.0, 0.3, 0, 0, -2, 2, -2,
00083 0.2, 0, 0, 0, -2, 2, -1,
00084 -0.2, 0, 0, -1, -2, 2, -2,
00085 -0.5, 0, 1, 0, 0, -2, 0,
00086 -0.1, 0, 1, 0, 0, -2, 1,
00087 0.1, 0, -1, 0, 0, 0, -1,
00088 -2.1, 0.1, -1, 0, 0, 0, 0,
00089 -0.4, 0, -1, 0, 0, 0, 1,
00090 -0.2, 0, 0, 0, 0, -2, 0,
00091 -0.1, 0, -2, 0, 0, 0, 0,
00092 -0.6, 0, 0, 0, -2, 0, -2,
00093 -0.4, 0, 0, 0, -2, 0, -1,
00094 -0.1, 0, 0, 0, -2, 0, 0,
00095 -0.1, 0, -1, 0, -2, 0, -2,
00096 -0.1, 0, -1, 0, -2, 0, -1
00097 };
00098
00099
00100
00101
00102 const double EarthSolidTide::Argu_C22[2][6] =
00103 {
00104 -0.3, 1, 0, 2, 0, 2,
00105 -1.2, 0, 0, 2, 0, 2
00106 };
00107
00108
00109
00110
00111 const double EarthSolidTide::Argu_C20[21][7]=
00112 {
00113 16.6, -6.7, 0, 0, 0, 0, 1,
00114 -0.1, 0.1, 0, 0, 0, 0, 2,
00115 -1.2, 0.8, 0, -1, 0, 0, 0,
00116 -5.5, 4.3, 0, 0, -2, 2, -2,
00117 0.1, -0.1, 0, 0, -2, 2, -1,
00118 -0.3, 0.2, 0, -1, -2, 2, -2,
00119 -0.3, 0.7, 1, 0, 0, -2, 0,
00120 0.1, -0.2, -1, 0, 0, 0, -1,
00121 -1.2, 3.7, -1, 0, 0, 0, 0,
00122 0.1, -0.2, -1, 0, 0, 0, 1,
00123 0.1, -0.2, 1, 0, -2, 0, -2,
00124 0, 0.6, 0, 0, 0, -2, 0,
00125 0, 0.3, -2, 0, 0, 0, 0,
00126 0.6, 6.3, 0, 0, -2, 0, -2,
00127 0.2, 2.6, 0, 0, -2, 0, -1,
00128 0, 0.2, 0, 0, -2, 0, 0,
00129 0.1, 0.2, 1, 0, -2, -2, -2,
00130 0.4, 1.1, -1, 0, -2, 0, -2,
00131 0.2, 0.5, -1, 0, -2, 0, -1,
00132 0.1, 0.2, 0, 0, -2, -2, -2,
00133 0.1, 0.1, -2, 0, -2, 0, -2
00134 };
00135
00143 void EarthSolidTide::getSolidTide(double mjdUtc, double dC[], double dS[] )
00144 {
00145 UTCTime utc(mjdUtc);
00146
00147 Matrix<double> E = ReferenceFrames::J2kToECEFMatrix(utc);
00148
00149 Vector<double> moonReci = ReferenceFrames::getJ2kPosition(utc.asTDB(),SolarSystem::Moon)*1000.0;
00150 Vector<double> sunReci = ReferenceFrames::getJ2kPosition(utc.asTDB(),SolarSystem::Sun)*1000.0;
00151
00152 Vector<double> moonR = E * moonReci;
00153 Vector<double> sunR = E * sunReci;
00154
00155 Position moonP(moonR(0),moonR(1),moonR(2));
00156 Position sunP(sunR(0),sunR(1),sunR(2));
00157
00158 double r_sun, phi_sun, lamda_sun;
00159 r_sun = norm(sunR);
00160 phi_sun = sunP.getGeocentricLatitude()*ASConstant::PI/180.0;
00161 lamda_sun = sunP.getLongitude()*ASConstant::PI/180.0;
00162
00163 double r_lunar, phi_lunar, lamda_lunar;
00164 r_lunar = norm(moonR);
00165 phi_lunar = moonP.getGeocentricLatitude()*ASConstant::PI/180.0;
00166 lamda_lunar = moonP.getLongitude()*ASConstant::PI/180.0;
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 complex<double> k[10] =
00189 {
00190 complex<double >(0.30190, 0.0),
00191 complex<double >(0.29830,-0.00144),
00192 complex<double >(0.30102,-0.00130),
00193 complex<double >(0.093, 0.0),
00194 complex<double >(0.093, 0.0),
00195 complex<double >(0.093, 0.0),
00196 complex<double >(0.094, 0.0),
00197 complex<double >(-0.00089, 0.0),
00198 complex<double >(-0.00080, 0.0),
00199 complex<double >(-0.00057, 0.0)
00200 };
00201
00202 complex<double> res[7];
00203
00204
00205
00206
00207 for(int n=2;n<=3;n++)
00208 {
00209 for(int m=0;m<=n;m++)
00210 {
00211 int index = n * n - 2 * n + m;
00212
00213 double Nnm = normFactor( n, m );
00214
00215
00216
00217 double sunPnm = Nnm * legendrePoly( n, m, std::sin( phi_sun) );
00218 double moonPnm = Nnm * legendrePoly( n, m, std::sin( phi_lunar) );
00219
00220 double sunTemp = (ASConstant::GM_Sun/ASConstant::GM_Earth)*std::pow(ASConstant::R_Earth/r_sun,n+1) * sunPnm;
00221 double moonTemp = (ASConstant::GM_Moon/ASConstant::GM_Earth)*std::pow(ASConstant::R_Earth/r_lunar,n+1)*moonPnm;
00222
00223
00224 complex<double> c_sun = complex<double>( std::cos( - m * lamda_sun ), std::sin( - m * lamda_sun ) );
00225 complex<double> c_lunar = complex<double>( std::cos( - m * lamda_lunar ), std::sin( - m * lamda_lunar ) );
00226
00227 res[index] = sunTemp * c_sun + moonTemp * c_lunar;
00228
00229 dC[index] = (k[index]*res[index]).real()/(2.0*n+1.0);
00230 dS[index] = -(k[index]*res[index]).imag()/(2.0*n+1.0);
00231
00232 }
00233
00234 }
00235
00236
00237
00238 for(int n = 0; n <= 2; n ++ )
00239 {
00240 int index = 2 * 2 - 2 * 2 + n;
00241 complex<double> c_temp = k[n+7 ] * res[ index ];
00242 dC[7+n] = c_temp.real() / 5.0;
00243 dS[7+n] =-c_temp.imag() / 5.0;
00244 }
00245
00246
00247
00248
00249
00250
00251 double BETA[6] = {0.0};
00252 double Dela[5] = {0.0};
00253 ReferenceFrames::doodsonArguments(utc.asUT1(),utc.asTT(),BETA,Dela);
00254 double GMST = ReferenceFrames::iauGmst00(utc.asUT1(), utc.asTT());
00255
00256
00257 for(int i=0;i<48;i++)
00258 {
00259
00260 double thet_f = (GMST+ASConstant::PI)-(Argu_C21[i][2]*Dela[0]+Argu_C21[i][3]*Dela[1]+Argu_C21[i][4]*Dela[2]
00261 + Argu_C21[i][5]*Dela[3]+Argu_C21[i][6]*Dela[4]);
00262
00263 double t_s = std::sin(thet_f);
00264 double t_c = std::cos(thet_f);
00265
00266
00267 dC[1] += ((Argu_C21[i][0]*t_s+Argu_C21[i][1]*t_c )*1e-12);
00268 dS[1] += ((Argu_C21[i][0]*t_c-Argu_C21[i][1]*t_s )*1e-12);
00269 }
00270
00271 for(int i=0;i<2;i++)
00272 {
00273
00274 double thet_f = 2*(GMST+ASConstant::PI)-(Argu_C22[i][1]*Dela[0]+Argu_C22[i][2]*Dela[1]+Argu_C22[i][3]*Dela[2]
00275 + Argu_C22[i][4]*Dela[3]+Argu_C22[i][5]*Dela[4]);
00276
00277 double t_s = std::sin(thet_f);
00278 double t_c = std::cos(thet_f);
00279
00280
00281
00282 dC[2] += ((Argu_C22[i][0]*t_c)*1e-12 );
00283 dS[2] += ((-Argu_C22[i][0]*t_s)*1e-12 );
00284 }
00285
00286
00287 for(int i=0;i<21;i++)
00288 {
00289
00290 double thet_f = -(Argu_C20[i][2]*Dela[0]+Argu_C20[i][3]*Dela[1]+Argu_C20[i][4]*Dela[2]
00291 + Argu_C20[i][5]*Dela[3]+Argu_C20[i][6]*Dela[4]);
00292
00293 double t_s = std::sin(thet_f);
00294 double t_c = std::cos(thet_f);
00295
00296
00297
00298
00299 dC[0]+=((Argu_C20[i][0]*t_c+Argu_C20[i][1]*t_s)*1e-12);
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 }
00310
00311
00312 double EarthSolidTide::normFactor(int n, int m)
00313 {
00314
00315
00316 double fac(1.0);
00317 for(int i = (n-m+1); i <= (n+m); i++)
00318 {
00319 fac = fac * double(i);
00320 }
00321
00322 double delta = (m == 0) ? 1.0 : 0.0;
00323
00324 double num = (2.0 * n + 1.0) * (2.0 - delta);
00325
00326
00327
00328 double out = std::sqrt(num/fac);
00329
00330 return out;
00331
00332 }
00333
00334
00335
00336 double EarthSolidTide::legendrePoly(int n, int m, double u)
00337 {
00338
00339 if(0==n && 0==m)
00340 {
00341 return 1.0;
00342 }
00343 else if(m==n)
00344 {
00345 return (2.0*m-1.0)*std::sqrt(1.0-u*u)*legendrePoly(n-1,m-1,u);
00346 }
00347 else if(n==m+1)
00348 {
00349 return (2.0*m+1)*u*legendrePoly(m,m,u);
00350 }
00351 else
00352 {
00353 return ((2.0*n-1.0)*u*legendrePoly(n-1,m,u)-(n+m-1.0)*legendrePoly(n-2,m,u))/(n-m);
00354 }
00355
00356 }
00357
00358
00359 void EarthSolidTide::test()
00360 {
00361 cout<<"testing solid tide"<<endl;
00362
00363 double mjdUtc = 2454531 + 0.49983796296296296 - 2400000.5;
00364 double dc[10]={0.0},ds[10]={0.0};
00365 getSolidTide(mjdUtc,dc,ds);
00366
00367 int a = 0;
00368
00369
00370 }
00371
00372
00373
00374 }
00375
00376
00377
00378