LMST1.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Duncan Brown, David Chin, Jolien Creighton, Kipp Cannon, Peter Shawhan, Reinhard Prix
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /* <lalVerbatim file="LMST1CV">
00021 Author: David Chin <dwchin@umich.edu> +1-734-709-9119
00022 $Id: LMST1.c,v 1.27 2008/04/29 01:10:39 kipp Exp $
00023 </lalVerbatim> */
00024 
00025 /* <lalLaTeX>
00026 
00027 \subsection{Module \texttt{LMST1.c}}
00028 \label{ss:LMST1.c}
00029 
00030 Routines related to Local and Greenwich Mean Sidereal Time (LMST1 and
00031 GMST1) computations.
00032 
00033 \subsection*{Prototypes}
00034 \vspace{0.1in}
00035 
00036 \input{LMST1CP}
00037 \idx{LALGMST1()}
00038 \idx{LALGPStoGMST1()}
00039 \idx{LALLMST1()}
00040 \idx{LALGPStoLMST1()}
00041 
00042 
00043 \subsubsection*{Description}
00044 
00045 The routines in this module compute Mean Sidereal Time in a choice of
00046 units: seconds, hours, degrees, or radians. LMST1 is offset from GMST1
00047 by the longitude of the observing post.
00048 
00049 \begin{itemize}
00050 \item \texttt{LALGMST1()} computes GMST1 given a Gregorian date UTC in an
00051 \texttt{LALDate} structure. 
00052 \item  \texttt{LALGPStoGMST1()} computes GMST1 given a GPS time. 
00053 \item  \texttt{LALLMST1()} computes LMST1 given an observing location (in a
00054   \texttt{LALDetector} structure) and a Gregorian date UTC.
00055 \item \texttt{LALGPStoLMST1()} computes LMST1 given an observing location
00056   and a GPS time.
00057 \end{itemize}
00058 
00059 
00060 All the routines will output GMST1 or LMST1 in the units and leap second
00061 accuracy specified by the \texttt{pUnitsAndAcc} argument.  The sidereal
00062 time produced is within $\tilde 1$ sidereal second of values published in
00063 the Almanac.
00064 
00065 \subsubsection*{Algorithms}
00066 
00067 The basic definitions and formulae are from~\cite{esaa:1992}, Ch. 2,
00068 Sec. 24, and also Sec. B of the Astronomical Almanac. The formula
00069 computes GMST1 for 0h UT1.  To compute GMST1 for other times, a simple
00070 linear interpolation is done. The implementation used in
00071 \texttt{LALGMST1()} is from~\cite{novas:1999} .  Since 1984-Jan-01,
00072 GMST has been related to UT1 as follows:
00073 %
00074 \begin{displaymath}
00075   \mathrm{GMST>of}>0^{h}\mathrm{UT1} = 24110^{s}.54841 +
00076   8640184^{s}.812866\,T_{u} + 0^{s}.093104\,T^{2}_{u} -
00077   6.2\times10^{-6}\,T^{3}_{u} 
00078 \end{displaymath}
00079 %
00080 where $T_{u} = d_{u} / 36525$, $d_{u}$ is the number of days of
00081 Universal Time elapsed since JD 2451545.0 UT1 (January 1, 2000, at 12:00 UT1),
00082 taking on values of $\pm 0.5, \pm 1.5, \pm 2.5,
00083 \pm 3.5, \ldots$
00084 
00085 
00086 
00087 \subsubsection*{Uses}
00088 
00089 \subsubsection*{Notes}
00090 
00091 Here is a simple example:
00092 
00093 \begin{verbatim}
00094 #include <stdlib.h>
00095 #include <lal/LALStdlib.h>
00096 #include <lal/Date.h>
00097 
00098 INT4 debuglevel = 2;
00099 
00100 NRCSID (TESTLMSTC, "Id");
00101 
00102 int
00103 main(int argc, char *argv[])
00104 {
00105     LALDate date;
00106     LALDate mstdate;
00107     REAL8   gmsthours, lmsthours;
00108     REAL8   gmstsecs;
00109     REAL8   longitude;
00110     LALMSTUnitsAndAcc units_and_acc;
00111     time_t  timer;
00112     CHAR    timestamp[64], tmpstr[64];
00113     Status  status = {0};
00114 
00115     if (argc == 1)
00116     {
00117         printf("Usage: TestUTCtoGPS debug_level -- debug_level = [0,1,2]\n");
00118         return 0;
00119     }
00120 
00121     if (argc == 2)
00122         debuglevel = atoi(argv[1]);
00123 
00124     INITSTATUS(&status, "TestLMST", TESTLMSTC);
00125 
00126     printf("TEST of GMST1 routine\n");
00127     printf("=====================\n");
00128 
00129     
00130     // Check against the Astronomical Almanac:
00131     // For 1994-11-16 0h UT - Julian Date 2449672.5, GMST 03h 39m 21.2738s
00132     date.unixDate.tm_sec  = 0;
00133     date.unixDate.tm_min  = 0;
00134     date.unixDate.tm_hour = 0;
00135     date.unixDate.tm_mday = 16;
00136     date.unixDate.tm_mon  = LALMONTH_NOV;
00137     date.unixDate.tm_year = 94;
00138 
00139     longitude = 0.; 
00140     LALGMST1(&status, &gmsthours, &date, MST_HRS);
00141     LALLMST1(&status, &lmsthours, &date, longitude, MST_HRS);
00142 
00143     LALGMST1(&status, &gmstsecs, &date, MST_SEC);
00144     LALSecsToLALDate(&status, &mstdate, gmstsecs);
00145     strftime(timestamp, 64, "%Hh %Mm %S", &(mstdate.unixDate));
00146     sprintf(tmpstr, "%fs", mstdate.residualNanoSeconds * 1.e-9);
00147     strcat(timestamp, tmpstr+1);
00148     
00149     printf("gmsthours = %f = %s\n", gmsthours, timestamp);
00150     printf("    expect: 3.655728 = 03h 39m 20.6222s \n");
00151 
00152     return(0);
00153 }
00154 \end{verbatim}
00155 
00156 
00157 From~\cite{esaa:1992}:
00158 
00159 \begin{quote}
00160   Universal Time (UT) is the measure of time used as the basis for all
00161   civil time-keeping.  It conforms closely to the mean diurnal motion
00162   of the Sun.  The apparent diurnal motion of the Sun involves both
00163   the nonuniform diurnal rotation of the Earth and the motion of the
00164   Earth in its orbit around the Sun.  Although it would be possible to
00165   define a system of time measurement in terms of the hour angle of
00166   the Sun, such a system could never be related precisely to sidereal
00167   time and could not, therefore, be determined by observations of star
00168   transits.  As a result, Universal Time is directly related to
00169   sidereal time by means of a numerical formula.  It does not refer to
00170   the motion of the Earth and is not precisely related to the hour
00171   angle of the Sun.
00172   
00173   Universal Time at any instant can be derived from observations of
00174   the diurnal motion of the stars or radio sources.  The uncorrected
00175   observed rotational timescale, which is dependent on the place of
00176   observation, is designated UT0.  Correcting this timescale for the
00177   shift in longitude of the observing station caused by polar motion
00178   produces the UT1 timescale, which is independent of observing
00179   location, but is influenced by the slightly variable rotation of the
00180   Earth. 
00181 \end{quote}
00182 
00183 A useful resource is \url{http://aa.usno.navy.mil/}.
00184 
00185 </lalLaTeX> */
00186 
00187 
00188 /*******************************************************************
00189  *
00190  * SYNOPSIS
00191  *
00192  * LALGMST1(): Returns LALGMST1 for given date-time
00193  * LALLMST1(): Returns LALLMST1 given date-time, and longitude
00194  * 
00195  * DESCRIPTION
00196  *
00197  * LALGMST1():
00198  *      Inputs: LALDate *date      -- date-time to compute GMST1
00199  *              LALMSTUnits outunits -- units requested:
00200  *                                      MST_SEC - seconds
00201  *                                      MST_HRS - hours
00202  *                                      MST_DEG - degrees
00203  *                                      MST_RAD - radians
00204  *
00205  *      Outputs: REAL8  *gmst      -- LALGMST1 in units requested
00206  *
00207  * LALLMST1():
00208  *      Inputs: LALPlaceAndDate *place_and_date -- location and date-time
00209  *                                                 to compute GMST1
00210  *              LALMSTUnits outunits -- units requested:
00211  *                                      MST_SEC - seconds
00212  *                                      MST_HRS - hours
00213  *                                      MST_DEG - degrees
00214  *                                      MST_RAD - radians
00215  *
00216  *      Outputs: REAL8  *lmst      -- LALGMST1 in units requested
00217  *
00218  * 
00219  *----------------------------------------------------------------------- */
00220 
00221 #include <lal/LALRCSID.h>
00222 
00223 NRCSID (LMST1C, "$Id: LMST1.c,v 1.27 2008/04/29 01:10:39 kipp Exp $");
00224 
00225 #include <math.h>
00226 #include <lal/LALStdio.h>
00227 #include <lal/Date.h>
00228 #include "date_value.h"
00229 #include <lal/XLALError.h>
00230 
00231 #define INFOSTR_LEN 256
00232 
00233 /*
00234  * Compute GMST in requested units given date UTC.
00235  */
00236 
00237 /* <lalVerbatim file="LMST1CP"> */
00238 void
00239 LALGMST1 (LALStatus     *status,
00240           REAL8         *p_gmst,     /* output - GMST1 */
00241           const LALDate *p_date,     /* input  - date and time */
00242           LALMSTUnits    outunits)   /* GMST1 units */
00243 { /* </lalVerbatim> */
00244   LIGOTimeGPS gps;
00245   LALMSTUnitsAndAcc UnitsAndAcc;
00246   char infostr[INFOSTR_LEN];
00247 
00248   INITSTATUS (status, "LALGMST1", LMST1C);
00249   ATTATCHSTATUSPTR(status);
00250 
00251   /*
00252    * Check pointer to input variables
00253    */
00254   ASSERT (p_date != (LALDate *)NULL, status,
00255           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00256 
00257   /*
00258    * Check pointer to output variable
00259    */
00260   ASSERT (p_gmst != (REAL8 *)NULL, status,
00261           DATEH_ENULLOUTPUT, DATEH_MSGENULLOUTPUT);
00262 
00263   /*
00264    * Compute GMST for UTC on given date in seconds 
00265    */
00266 
00267   UnitsAndAcc.accuracy = LALLEAPSEC_STRICT;
00268   UnitsAndAcc.units = outunits;
00269 
00270   TRY( LALUTCtoGPS( status->statusPtr, &gps, p_date, &UnitsAndAcc.accuracy ), status );
00271   TRY( LALGPStoGMST1( status->statusPtr, p_gmst, &gps, &UnitsAndAcc ), status );
00272 
00273   if (lalDebugLevel & LALINFO)
00274   {
00275     LALSnprintf(infostr, INFOSTR_LEN, "LALGMST1: *p_gmst = %g\n", *p_gmst);
00276     LALInfo(status, infostr);
00277   }
00278 
00279   DETATCHSTATUSPTR(status);
00280   RETURN (status);
00281 } /* END LALGMST1() */
00282 
00283 
00284 
00285 /*
00286  * Compute GMST1 in requested units given GPS time
00287  */
00288 /* <lalVerbatim file="LMST1CP"> */
00289 void
00290 LALGPStoGMST1( LALStatus         *status,
00291                REAL8             *p_gmst,   /* output - GMST1 */
00292                const LIGOTimeGPS *p_gps,    /* input - GPS time */
00293                const LALMSTUnitsAndAcc *pUnitsAndAcc) /* GMST1 units and accuracy */
00294 { /* </lalVerbatim> */
00295   INITSTATUS (status, "LALGPStoGMST1", LMST1C);
00296   ATTATCHSTATUSPTR(status);
00297     
00298   /*
00299    * Check pointer to input variables
00300    */
00301   ASSERT (p_gps != (LIGOTimeGPS *)NULL, status,
00302           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00303   ASSERT (pUnitsAndAcc != (LALMSTUnitsAndAcc *)NULL, status,
00304           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00305 
00306   /*
00307    * Check pointer to output variable
00308    */
00309   ASSERT (p_gmst != (REAL8 *)NULL, status,
00310           DATEH_ENULLOUTPUT, DATEH_MSGENULLOUTPUT);
00311 
00312   XLALPrintDeprecationWarning("LALGPStoGMST1", "XLALGreenwichMeanSiderealTime");
00313 
00314   /*
00315    * Compute GMST for GPS on given date in seconds 
00316    */
00317   *p_gmst = fmod(XLALGreenwichMeanSiderealTime(p_gps) / (2.0 * LAL_PI) * SECS_PER_DAY, SECS_PER_DAY);
00318   if(*p_gmst < 0.0)
00319     *p_gmst += SECS_PER_DAY;
00320 
00321   /*
00322    * Convert GMST to requested units
00323    */
00324   switch (pUnitsAndAcc->units)
00325     {
00326     case MST_SEC:
00327       break;
00328     case MST_HRS:
00329       *p_gmst /= (REAL8)SECS_PER_HOUR;
00330       break;
00331     case MST_DEG:
00332       *p_gmst /= (REAL8)SECS_PER_HOUR / (REAL8)DEGS_PER_HOUR;
00333       break;
00334     case MST_RAD:
00335       *p_gmst /= (REAL8)SECS_PER_HOUR / (REAL8)DEGS_PER_HOUR * 180. /
00336         (REAL8)LAL_PI;
00337       break;
00338     default:
00339       break;
00340     }
00341 
00342   DETATCHSTATUSPTR(status);
00343   RETURN(status);
00344 } /* END: LALGPStoGMST1() */
00345 
00346 
00347 
00348 
00349 
00350 /*
00351  * Compute LMST1 in requested units given date-time
00352  */
00353 /* <lalVerbatim file="LMST1CP"> */
00354 void
00355 LALLMST1 (LALStatus             *status,
00356           REAL8                 *p_lmst,            /* output - LMST1 */
00357           const LALPlaceAndDate *p_place_and_date,  /* input - place and date */
00358           LALMSTUnits            outunits)          /* LMST1 units */
00359 { /* </lalVerbatim> */
00360   REAL8 gmst;
00361   REAL8 day = 0;
00362   REAL8 longitude = LAL_180_PI *
00363     atan2(p_place_and_date->p_detector->location[1],
00364           p_place_and_date->p_detector->location[0]);
00365 
00366   INITSTATUS (status, "LALLMST1", LMST1C);
00367   ATTATCHSTATUSPTR(status);
00368 
00369   /*
00370    * Check pointer to input variables
00371    */
00372   ASSERT (p_place_and_date != (LALPlaceAndDate *)NULL, status,
00373           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00374 
00375   /*
00376    * Check pointer to output variable
00377    */
00378   ASSERT (p_lmst != (REAL8 *)NULL, status,
00379           DATEH_ENULLOUTPUT, DATEH_MSGENULLOUTPUT);
00380 
00381   /*
00382    * Compute LMST1 in seconds since J2000.0
00383    */
00384 
00385   /* get GMST1 in seconds */
00386   TRY( LALGMST1(status->statusPtr, &gmst, p_place_and_date->p_date, outunits),
00387        status);
00388 
00389   /* convert longitude to appropriate units of sidereal time */
00390   switch (outunits)
00391         {
00392     case MST_SEC:
00393       longitude /= (REAL8)DEGS_PER_HOUR / (REAL8)SECS_PER_HOUR;
00394       day        = SECS_PER_DAY;
00395       break;
00396     case MST_HRS:
00397       longitude /= (REAL8)DEGS_PER_HOUR;
00398       day        = 24.;
00399       break;
00400     case MST_DEG:
00401       day        = 360.;
00402       break;
00403     case MST_RAD:
00404       longitude /= 180. / (REAL8)LAL_PI;
00405       day        = (REAL8)LAL_TWOPI;
00406       break;
00407     default:
00408       break;
00409     }
00410 
00411   *p_lmst = gmst + longitude;
00412 
00413   while (*p_lmst < 0)
00414     *p_lmst += day;
00415 
00416   DETATCHSTATUSPTR(status);
00417   RETURN (status);
00418 } /* END LALLMST1() */
00419 
00420 
00421 
00422 /*
00423  * Compute LMST1 in requested units given GPS time
00424  */
00425 /* <lalVerbatim file="LMST1CP"> */
00426 void
00427 LALGPStoLMST1( LALStatus             *status,
00428                REAL8                 *p_lmst,          /* output - LMST1 */
00429                const LALPlaceAndGPS  *p_place_and_gps, /* input - place and GPS */
00430                const LALMSTUnitsAndAcc *pUnitsAndAcc)        /* LMST1 units and accuracy */
00431 { /* </lalVerbatim> */
00432   LALDate         date;
00433   LALPlaceAndDate place_and_date;
00434 
00435   INITSTATUS (status, "LALGPStoLMST1", LMST1C);
00436   ATTATCHSTATUSPTR(status);
00437 
00438     
00439   /*
00440    * Check pointer to input variables
00441    */
00442   ASSERT (p_place_and_gps != (LALPlaceAndGPS *)NULL, status,
00443           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00444 
00445   ASSERT (pUnitsAndAcc != (LALMSTUnitsAndAcc *)NULL, status,
00446           DATEH_ENULLINPUT, DATEH_MSGENULLINPUT);
00447   
00448   /*
00449    * Check pointer to output variable
00450    */
00451   ASSERT (p_lmst != (REAL8 *)NULL, status,
00452           DATEH_ENULLOUTPUT, DATEH_MSGENULLOUTPUT);
00453 
00454 
00455   /*
00456    * Convert GPS to date-time structure
00457    */
00458 
00459   /* first, GPS to Unix */
00460   TRY( LALGPStoUTC(status->statusPtr, &date, p_place_and_gps->p_gps,
00461                    &(pUnitsAndAcc->accuracy)),
00462        status );
00463 
00464   /* stuff it all into a LALPlaceAndDate */
00465   place_and_date.p_detector = p_place_and_gps->p_detector;
00466   place_and_date.p_date     = &date;
00467 
00468   TRY( LALLMST1(status->statusPtr, p_lmst, &place_and_date,
00469                 pUnitsAndAcc->units), status );
00470 
00471   DETATCHSTATUSPTR(status);
00472   RETURN(status);
00473 } /* END: LALGPStoLMST1() */

Generated on Tue Oct 14 02:32:03 2008 for LAL by  doxygen 1.5.2