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() */
1.5.2