LAL  7.5.0.1-08ee4f4
XLALSiderealTime.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007 Jolien Creighton, and Kipp Cannon
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12  * Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <math.h>
20 #include <lal/Date.h>
21 #include <lal/XLALError.h>
22 
23 /**
24  * \defgroup XLALSideralTime_c SideralTime
25  * \ingroup Date_h
26  * \author Creighton, J., and Cannon, K.
27  * \brief XLAL routines for computing the sidereal time.
28  *
29  * ### Synopsis ###
30  *
31  * \code
32  * #include <lal/Date.h>
33  * \endcode
34  */
35 
36 /** @{ */
37 
38 /**
39  * Returns the Greenwich Sidereal Time IN RADIANS corresponding to a
40  * specified GPS time. Aparent sidereal time is computed by providing the
41  * equation of equinoxes in units of seconds. For mean sidereal time, set
42  * this parameter to 0.
43  *
44  * This function returns the sidereal time in radians measured from the
45  * Julian epoch (current J2000). The result is NOT modulo 2 pi.
46  *
47  * Inspired by the function sidereal_time() in the NOVAS-C library, version
48  * 2.0.1, which is dated December 10th, 1999, and carries the following
49  * references:
50  *
51  * Aoki, et al. (1982) Astronomy and Astrophysics 105, 359-361.
52  * Kaplan, G. H. "NOVAS: Naval Observatory Vector Astrometry
53  * Subroutines"; USNO internal document dated 20 Oct 1988;
54  * revised 15 Mar 1990.
55  *
56  * See http://aa.usno.navy.mil/software/novas for more information.
57  *
58  * Note: rather than maintaining this code separately, it would be a good
59  * idea for LAL to simply link to the NOVAS-C library directly. Something
60  * to do when we have some spare time.
61  */
63  const LIGOTimeGPS *gpstime,
64  REAL8 equation_of_equinoxes
65 )
66 {
67  struct tm utc;
68  double julian_day;
69  double t_hi, t_lo;
70  double t;
71  double sidereal_time;
72 
73  /*
74  * Convert GPS seconds to UTC. This is where we pick up knowledge
75  * of leap seconds which are required for the mapping of atomic
76  * time scales to celestial time scales. We deal only with integer
77  * seconds.
78  */
79 
80  if(!XLALGPSToUTC(&utc, gpstime->gpsSeconds))
82 
83  /*
84  * And now to Julian day number. Again, only accurate to integer
85  * seconds.
86  */
87 
88  julian_day = XLALConvertCivilTimeToJD(&utc);
89  if(XLAL_IS_REAL8_FAIL_NAN(julian_day))
91 
92  /*
93  * Convert Julian day number to the number of centuries since the
94  * Julian epoch (1 century = 36525.0 days). Here, we incorporate
95  * the fractional part of the seconds. For precision, we keep
96  * track of the most significant and least significant parts of the
97  * time separately. The original code in NOVAS-C determined t_hi
98  * and t_lo from Julian days, with t_hi receiving the integer part
99  * and t_lo the fractional part. Because LAL's Julian day routine
100  * is accurate to the second, here the hi/lo split is most
101  * naturally done at the integer seconds boundary. Note that the
102  * "hi" and "lo" components have the same units and so the split
103  * can be done anywhere.
104  */
105 
106  t_hi = (julian_day - XLAL_EPOCH_J2000_0_JD) / 36525.0;
107  t_lo = gpstime->gpsNanoSeconds / (1e9 * 36525.0 * 86400.0);
108 
109  /*
110  * Compute sidereal time in sidereal seconds. (magic)
111  */
112 
113  t = t_hi + t_lo;
114 
115  sidereal_time = equation_of_equinoxes + (-6.2e-6 * t + 0.093104) * t * t + 67310.54841;
116  sidereal_time += 8640184.812866 * t_lo;
117  sidereal_time += 3155760000.0 * t_lo;
118  sidereal_time += 8640184.812866 * t_hi;
119  sidereal_time += 3155760000.0 * t_hi;
120 
121  /*
122  * Return radians (2 pi radians in 1 sidereal day = 86400 sidereal
123  * seconds).
124  */
125 
126  return sidereal_time * LAL_PI / 43200.0;
127 }
128 
129 
130 /**
131  * Convenience wrapper, calling XLALGreenwichSiderealTime() with the
132  * equation of equinoxes set to 0.
133  */
135  const LIGOTimeGPS *gpstime
136 )
137 {
138  return XLALGreenwichSiderealTime(gpstime, 0.0);
139 }
140 
141 
142 /**
143  * Inverse of XLALGreenwichMeanSiderealTime(). The input is sidereal time
144  * in radians since the Julian epoch (currently J2000 for LAL), and the
145  * output is the corresponding GPS time. The algorithm uses a naive
146  * iterative root-finder, so it's slow.
147  */
149  REAL8 gmst,
150  LIGOTimeGPS *gps
151 )
152 {
153  const double gps_seconds_per_sidereal_radian = 13713.44; /* approx */
154  const double precision = 1e-14;
155  int iterations = 10;
156  double error;
157 
158  XLALGPSSet(gps, 0, 0);
159 
160  do {
161  error = gmst - XLALGreenwichMeanSiderealTime(gps);
162  if(fabs(error / gmst) <= precision)
163  return gps;
164  XLALGPSAdd(gps, error * gps_seconds_per_sidereal_radian);
165  } while(--iterations);
167 }
168 
169 
170 /**
171  * Convenience wrapper of XLALGreenwichMeanSiderealTimeToGPS(), adjusting
172  * the input by the equation of equinoxes.
173  */
175  REAL8 gmst,
176  REAL8 equation_of_equinoxes,
177  LIGOTimeGPS *gps
178 )
179 {
180  return XLALGreenwichMeanSiderealTimeToGPS(gmst - equation_of_equinoxes, gps);
181 }
182 
183 /** @} */
static REAL8TimeSeries * error(const REAL8TimeSeries *s1, const REAL8TimeSeries *s0)
#define XLAL_EPOCH_J2000_0_JD
Julian Day (UTC) of the J2000.0 epoch (2000 JAN 1 12h UTC).
Definition: Date.h:84
#define LAL_PI
Archimedes's constant, pi.
Definition: LALConstants.h:179
double REAL8
Double precision real floating-point number (8 bytes).
REAL8 XLALConvertCivilTimeToJD(const struct tm *civil)
Returns the Julian Day (JD) corresponding to the civil date and time given in a broken down time stru...
struct tm * XLALGPSToUTC(struct tm *utc, INT4 gpssec)
Returns a pointer to a tm structure representing the time specified in seconds since the GPS epoch.
#define XLAL_ERROR_REAL8(...)
Macro to invoke a failure from a XLAL routine returning a REAL8.
Definition: XLALError.h:752
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define XLAL_IS_REAL8_FAIL_NAN(val)
Tests if val is a XLAL REAL8 failure NaN.
Definition: XLALError.h:393
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EMAXITER
Exceeded maximum number of iterations.
Definition: XLALError.h:455
LIGOTimeGPS * XLALGreenwichMeanSiderealTimeToGPS(REAL8 gmst, LIGOTimeGPS *gps)
Inverse of XLALGreenwichMeanSiderealTime().
REAL8 XLALGreenwichSiderealTime(const LIGOTimeGPS *gpstime, REAL8 equation_of_equinoxes)
Returns the Greenwich Sidereal Time IN RADIANS corresponding to a specified GPS time.
LIGOTimeGPS * XLALGreenwichSiderealTimeToGPS(REAL8 gmst, REAL8 equation_of_equinoxes, LIGOTimeGPS *gps)
Convenience wrapper of XLALGreenwichMeanSiderealTimeToGPS(), adjusting the input by the equation of e...
REAL8 XLALGreenwichMeanSiderealTime(const LIGOTimeGPS *gpstime)
Convenience wrapper, calling XLALGreenwichSiderealTime() with the equation of equinoxes set to 0.
LIGOTimeGPS * XLALGPSAdd(LIGOTimeGPS *epoch, REAL8 dt)
Adds a double to a GPS time.
Definition: XLALTime.c:131
LIGOTimeGPS * XLALGPSSet(LIGOTimeGPS *epoch, INT4 gpssec, INT8 gpsnan)
Sets GPS time given GPS integer seconds and residual nanoseconds.
Definition: XLALTime.c:63
Epoch relative to GPS epoch, see LIGOTimeGPS type for more details.
Definition: LALDatatypes.h:458
INT4 gpsSeconds
Seconds since 0h UTC 6 Jan 1980.
Definition: LALDatatypes.h:459
INT4 gpsNanoSeconds
Residual nanoseconds.
Definition: LALDatatypes.h:460