1 /*
2  *  This library is free software; you can redistribute it and/or
3  *  modify it under the terms of the GNU Lesser General Public
4  *  License as published by the Free Software Foundation; either
5  *  version 2 of the License, or (at your option) any later version.
6  *
7  *  This library is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  *  Lesser General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  *  Copyright (C) 2000 - 2005 Liam Girdwood  <lgirdwood@gmail.com>
17  */
18 
19 module nova.dynamical_time;
20 
21 import std.stdio;
22 
23 enum TERMS = 192;
24 
25 struct year_TD
26 {
27     int year;
28     double TD;
29 }
30 
31 extern (C) {
32 
33 /* Stephenson and Houlden  for years prior to 948 A.D.*/
34 // static double get_dynamical_diff_sh1(double JD);
35 
36 /* Stephenson and Houlden  for years between 948 A.D. and 1600 A.D.*/
37 // static double get_dynamical_diff_sh2(double JD);
38 
39 /* Table 9.a pg 72 for years 1620..1992.*/
40 // static double get_dynamical_diff_table(double JD);
41 
42 /* get the dynamical time diff in the near past / future 1992 .. 2010 */
43 // static double get_dynamical_diff_near(double JD);
44 
45 /* uses equation 9.1 pg 73 to calc JDE for othe JD values */
46 // static double get_dynamical_diff_other(double JD);
47 
48 }
49 
50 /* dynamical time in seconds for every second year from 1620 to 1992 */
51 const static double[TERMS] delta_t =
52 [   124.0, 115.0, 106.0, 98.0, 91.0,
53     85.0, 79.0, 74.0, 70.0, 65.0,
54     62.0, 58.0, 55.0, 53.0, 50.0,
55     48.0, 46.0, 44.0, 42.0, 40.0,
56     37.0, 35.0, 33.0, 31.0, 28.0,
57     26.0, 24.0, 22.0, 20.0, 18.0,
58     16.0, 14.0, 13.0, 12.0, 11.0,
59     10.0, 9.0, 9.0, 9.0, 9.0,
60     9.0, 9.0, 9.0, 9.0, 10.0,
61     10.0, 10.0, 10.0, 10.0, 11.0,
62     11.0, 11.0, 11.0, 11.0, 11.0,
63     11.0, 12.0, 12.0, 12.0, 12.0,
64     12.0, 12.0, 13.0, 13.0, 13.0,
65     13.0, 14.0, 14.0, 14.0, 15.0,
66     15.0, 15.0, 15.0, 16.0, 16.0,
67     16.0, 16.0, 16.0, 17.0, 17.0,
68     17.0, 17.0, 17.0, 17.0, 17.0,
69     17.0, 16.0, 16.0, 15.0, 14.0,
70     13.7, 13.1, 12.7, 12.5, 12.5,
71     12.5, 12.5, 12.5, 12.5, 12.3,
72     12.0, 11.4, 10.6, 9.6, 8.6,
73     7.5, 6.6, 6.0, 5.7, 5.6,
74     5.7, 5.9, 6.2, 6.5, 6.8,
75     7.1, 7.3, 7.5, 7.7, 7.8,
76     7.9, 7.5, 6.4, 5.4, 2.9,
77     1.6, -1.0, -2.7, -3.6, -4.7,
78     -5.4, -5.2, -5.5, -5.6, -5.8,
79     -5.9, -6.2, -6.4, -6.1, -4.7,
80     -2.7, 0.0, 2.6, 5.4, 7.7,
81     10.5, 13.4, 16.0, 18.2, 20.2,
82     21.2, 22.4, 23.5, 23.9, 24.3,
83     24.0, 23.9, 23.9, 23.7, 24.0,
84     24.3, 25.3, 26.2, 27.3, 28.2,
85     29.1, 30.0, 30.7, 31.4, 32.2,
86     33.1, 34.0, 35.0, 36.5, 38.3,
87     40.2, 42.2, 44.5, 46.5, 48.5,
88     50.5, 52.2, 53.8, 54.9, 55.8,
89     56.9, 58.3
90 ];
91 
92 extern (C) {
93 
94 /* Stephenson and Houlden  for years prior to 948 A.D.*/
95 static @nogc double get_dynamical_diff_sh1(double JD) nothrow
96 {
97     double TD,E;
98 
99     /* number of centuries from 948 */
100     E =(JD - 2067314.5) / 36525.0;
101 
102     TD = 1830.0 - 405.0 * E + 46.5 * E * E;
103     return TD;
104 }
105 
106 /* Stephenson and Houlden for years between 948 A.D. and 1600 A.D.*/
107 static @nogc double get_dynamical_diff_sh2(double JD) nothrow
108 {
109     double TD,t;
110 
111     /* number of centuries from 1850 */
112     t =(JD - 2396758.5) / 36525.0;
113 
114     TD = 22.5 * t * t;
115     return TD;
116 }
117 
118 /* Table 9.a pg 72 for years 1600..1992.*/
119 /* uses interpolation formula 3.3 on pg 25 */
120 static @nogc double get_dynamical_diff_table(double JD) nothrow
121 {
122     double TD = 0;
123     double a,b,c,n;
124     int i;
125 
126     /* get no days since 1620 and divide by 2 years */
127     i = cast(int)((JD - 2312752.5) / 730.5);
128 
129     /* get the base interpolation factor in the table */
130     if (i > (TERMS - 2))
131         i = TERMS - 2;
132 
133 	/* calc a,b,c,n */
134 	a = delta_t[i+1] - delta_t[i];
135 	b = delta_t[i+2] - delta_t[i+1];
136 	c = a - b;
137 	n = ((JD - (2312752.5 + (730.5 * i))) / 730.5);
138 
139 	TD = delta_t[i + 1] + n / 2 * (a + b + n * c);
140 
141     return TD;
142 }
143 
144 /* get the dynamical time diff in the near past / future 1992 .. 2010 */
145 /* uses interpolation formula 3.3 on pg 25 */
146 static @nogc double get_dynamical_diff_near(double JD) nothrow
147 {
148     double TD = 0;
149     /* TD for 1990, 2000, 2010 */
150     double[3] delta_T = [56.86, 63.83, 70.0];
151     double a,b,c,n;
152 
153     /* calculate TD by interpolating value */
154     a = delta_T[1] - delta_T[0];
155     b = delta_T[2] - delta_T[1];
156     c = b - a;
157 
158     /* get number of days since 2000 and divide by 10 years */
159 	n =(JD - 2451544.5) / 3652.5;
160 	TD = delta_T[1] + (n / 2) * (a + b + n * c);
161 
162     return TD;
163 }
164 
165 /* uses equation 9.1 pg 73 to calc JDE for other JD values */
166 static @nogc double get_dynamical_diff_other(double JD) nothrow
167 {
168     double TD, a;
169 
170     a = (JD - 2382148.0);
171     a *= a;
172 
173     TD = -15.0 + a / 41048480.0;
174 
175     return TD;
176 }
177 
178 /*! \fn double ln_get_dynamical_time_diff(double JD)
179 * \param JD Julian Day
180 * \return TD
181 *
182 * Calculates the dynamical time (TD) difference in seconds (delta T) from
183 * universal time.
184 */
185 /* Equation 9.1 on pg 73.
186 */
187 @nogc double ln_get_dynamical_time_diff(double JD) nothrow
188 {
189     double TD;
190 
191     /* check when JD is, and use corresponding formula */
192     /* check for date < 948 A.D. */
193     if (JD < 2067314.5)
194         /* Stephenson and Houlden */
195 	    TD = get_dynamical_diff_sh1(JD);
196     else if (JD >= 2067314.5 && JD < 2305447.5)
197 	    /* check for date 948..1600 A.D. Stephenson and Houlden */
198     	TD = get_dynamical_diff_sh2(JD);
199 	else if (JD >= 2312752.5 && JD < 2448622.5)
200 		/* check for value in table 1620..1992  interpolation of table */
201 		TD = get_dynamical_diff_table(JD);
202 	else if (JD >= 2448622.5 && JD <= 2455197.5)
203 		/* check for near future 1992..2010 interpolation */
204 		TD = get_dynamical_diff_near(JD);
205 	else
206 	    /* other time period outside */
207 	    TD = get_dynamical_diff_other(JD);
208 
209 	return TD;
210 }
211 
212 
213 /*! \fn double ln_get_jde(double JD)
214 * \param JD Julian Day
215 * \return Julian Ephemeris day
216 *
217 * Calculates the Julian Ephemeris Day(JDE) from the given julian day
218 */
219 
220 @nogc double ln_get_jde(double JD) nothrow
221 {
222     double JDE;
223     double secs_in_day = 24.0 * 60.0 * 60.0;
224 
225     JDE = JD +  ln_get_dynamical_time_diff(JD) / secs_in_day;
226 
227     return JDE;
228 }
229 
230 }