EarthSolidTide.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: EarthSolidTide.cpp 2457 2010-08-18 14:20:12Z coandrei $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 //  Wei Yan - Chinese Academy of Sciences . 2009, 2010
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    // For dC21 and dS21
00043    // The coefficients we choose are in-phase(ip) amplitudes and out-of-phase amplitudes of the
00044    // corrections for frequency dependence, and multipliers of the Delaunay variables
00045    // Refers to Table 6.3a in IERS2003 P64
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    // For dC22 and dS22
00100    // Refer to Table 6.3c in IERS2003
00101    // (0.30102 . i 0.00130).
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    // For dC20
00109    // Refer to Table 6.3b in IERS2003
00110    // The nominal value k20 for the zonal tides is taken as 0.30190
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;         // in ecef m
00153       Vector<double> sunR = E * sunReci;           // in ecef m
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       // reference bern 5 TIDPT2.f
00170       /*
00171       PERTURBING ACCELERATION DUE TO TIDES CORRESPONDING TO IERS STANDARDS 2003.
00172       STEP 1 CORRECTIONS OF SOLID EARTH TIDES INCLUDED, 
00173       STEP 2 ONLY TERM DUE TO K1. SOLID EARTH POLE TIDES INCLUDED
00174       OCEAN TIDE TERMS UP TO N=M=4 INCLUDED
00175       */
00176 
00177       /*       IERS2003,  P60 
00178       Elastic Earth           Anelastic Earth
00179       n m    knm     k+nm    Reknm   Imknm    k+nm
00180       2 0 0.29525 .0.00087 0.30190 .0.00000 .0.00089
00181       2 1 0.29470 .0.00079 0.29830 .0.00144 .0.00080
00182       2 2 0.29801 .0.00057 0.30102 .0.00130 .0.00057
00183       3 0 0.093 ?¡è ?¡è ?¡è
00184       3 1 0.093 ?¡è ?¡è ?¡è
00185       3 2 0.093 ?¡è ?¡è ?¡è 
00186       3 3 0.094 ?¡è ?¡è ?¡è
00187       */
00188       complex<double> k[10] =      // Anelastic Earth
00189       { 
00190          complex<double >(0.30190, 0.0),          // 20
00191          complex<double >(0.29830,-0.00144),      // 21
00192          complex<double >(0.30102,-0.00130),      // 22
00193          complex<double >(0.093, 0.0),            // 30
00194          complex<double >(0.093, 0.0),            // 31
00195          complex<double >(0.093, 0.0),            // 32
00196          complex<double >(0.094, 0.0),            // 33
00197          complex<double >(-0.00089, 0.0),         // k+ 20
00198          complex<double >(-0.00080, 0.0),         // k+ 21
00199          complex<double >(-0.00057, 0.0)          // k+ 22
00200       };
00201 
00202       complex<double> res[7];
00203       
00204       //----------------------------------------------------------------------
00205       // The first step of the computation ,refer to "IERS conventions 2003" P59
00206       // Each iteration for dC[n,m] and dS[n,m]
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;          //index in the returning value array
00212             
00213             double Nnm = normFactor( n, m );        //normalization coefficents of degree n and order m
00214 
00215             // Pnm: normalized Legendre polynomials of degress n and order m
00216             // 0 for sun and 1 for lunar each
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             // Exp(-m*lamda*i) for sun and lunar each
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          }  // 'for(int m=0;m<=n;m++)'
00233 
00234       }  // 'for(int n=2;n<=3;n++)'
00235 
00236       // The correction of dC[4,i] and dS[4,i](i=0,1,2) produced by degree 2 tide
00237       // The only difference from the above dC[2,i] and dS[2,i] is value of k replaced by k+
00238       for(int n = 0; n <= 2; n ++ )
00239       {
00240          int index   = 2 * 2 - 2 * 2 + n;                     // liuwk            
00241          complex<double> c_temp   = k[n+7 ] * res[ index ];   // liuwk
00242          dC[7+n] = c_temp.real() / 5.0;
00243          dS[7+n] =-c_temp.imag() / 5.0;
00244       }
00245 
00246       
00247       //-------------------------------------------------------------
00248       // The second step 
00249 
00250       //   COMPUTE DOODSON'S FUNDAMENTAL ARGUMENTS (BETA) 
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          // Computation of thet_f
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          // Resulted from formula 5b in chapter 6.1
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          // Input the computation of thet_f
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          // Resulted from formula 5b in chapter 6.1
00281          // The corrections are only to the real part.
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          // Input the computation of thet_f
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          // Resulted from formula 5a in chapter 6.1
00297          // Modified, 05.12.2009
00298          //         dC[0] += ( ( Argu_C20[i][0] * t_c - Argu_C20[i][1] * t_s ) * 1e-12 );
00299          dC[0]+=((Argu_C20[i][0]*t_c+Argu_C20[i][1]*t_s)*1e-12);
00300       }
00301 
00302       //--------------------------------------------------------------------------------
00303       // the third step
00304       // 
00305       //C REMOVE PREMANENT TIDE FROM C02 (FOR JGM-3 NOT FOR GEM-T3)
00306       //C ---------------------------------------------------------
00307       //IF (IZTID.EQ.1) CPOT(4)=CPOT(4)+1.3914129D-8*K20
00308    
00309    }
00310 
00311    // Nnm IERS2003 P60
00312    double EarthSolidTide::normFactor(int n, int m) 
00313    {
00314       // The input should be n >= m >= 0
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       // We should make sure fac!=0, but it won't happen on the case,
00327       // so we just skip handling it
00328       double out = std::sqrt(num/fac);                  
00329       
00330       return out;
00331 
00332    }  // End of method 'EarthSolidTide::normFactor'
00333    
00334   
00335       //  Legendre polynomial
00336    double EarthSolidTide::legendrePoly(int n, int m, double u)
00337    {
00338       // reference:Satellite Orbits Montenbruck. P66
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    }  // End of method 'EarthSolidTide::legendrePoly()'
00357 
00358 
00359    void EarthSolidTide::test()
00360    {   
00361       cout<<"testing solid tide"<<endl;
00362       // debuging
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    }    // End of method 'EarthSolidTide::test()'
00371 
00372 
00373 
00374 }       // End of namespace 'gpstk'
00375 
00376 
00377 
00378 

Generated on Tue May 22 03:30:57 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1