line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Astro::Coord::ECI::VSOP87D; |
2
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
26015
|
use 5.008; |
|
13
|
|
|
|
|
51
|
|
4
|
|
|
|
|
|
|
|
5
|
13
|
|
|
13
|
|
157
|
use strict; |
|
13
|
|
|
|
|
27
|
|
|
13
|
|
|
|
|
392
|
|
6
|
13
|
|
|
13
|
|
101
|
use warnings; |
|
13
|
|
|
|
|
28
|
|
|
13
|
|
|
|
|
433
|
|
7
|
|
|
|
|
|
|
|
8
|
13
|
|
|
13
|
|
8716
|
use utf8; |
|
13
|
|
|
|
|
201
|
|
|
13
|
|
|
|
|
66
|
|
9
|
|
|
|
|
|
|
|
10
|
13
|
|
|
|
|
1282
|
use Astro::Coord::ECI::Utils qw{ |
11
|
|
|
|
|
|
|
AU PI SECSPERDAY TWOPI |
12
|
|
|
|
|
|
|
asin deg2rad jcent2000 julianday |
13
|
|
|
|
|
|
|
load_module looks_like_number mod2pi |
14
|
|
|
|
|
|
|
rad2deg rad2dms rad2hms tan |
15
|
13
|
|
|
13
|
|
1410
|
}; |
|
13
|
|
|
|
|
20794
|
|
16
|
13
|
|
|
13
|
|
87
|
use Exporter qw{ import }; |
|
13
|
|
|
|
|
31
|
|
|
13
|
|
|
|
|
361
|
|
17
|
13
|
|
|
13
|
|
82
|
use Carp; |
|
13
|
|
|
|
|
37
|
|
|
13
|
|
|
|
|
642
|
|
18
|
13
|
|
|
13
|
|
73
|
use POSIX qw{ floor }; |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
126
|
|
19
|
13
|
|
|
13
|
|
9911
|
use Storable qw{ dclone }; |
|
13
|
|
|
|
|
44416
|
|
|
13
|
|
|
|
|
1023
|
|
20
|
|
|
|
|
|
|
|
21
|
13
|
|
|
13
|
|
112
|
use constant DAYS_PER_JULIAN_MILENNIUM => 365250; |
|
13
|
|
|
|
|
31
|
|
|
13
|
|
|
|
|
970
|
|
22
|
13
|
|
|
13
|
|
82
|
use constant CODE_REF => ref sub {}; |
|
13
|
|
|
|
|
33
|
|
|
13
|
|
|
|
|
740
|
|
23
|
13
|
|
|
13
|
|
100
|
use constant HASH_REF => ref {}; |
|
13
|
|
|
|
|
66
|
|
|
13
|
|
|
|
|
794
|
|
24
|
13
|
|
|
13
|
|
84
|
use constant SUN_CLASS => __PACKAGE__ . '::Sun'; |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
815
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
BEGIN { |
27
|
13
|
100
|
|
13
|
|
6441
|
__PACKAGE__->can( 'DEBUG' ) |
28
|
|
|
|
|
|
|
or constant->import( DEBUG => 0 ); |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
our $VERSION = '0.006'; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my @basic_export = qw{ |
34
|
|
|
|
|
|
|
SUN_CLASS |
35
|
|
|
|
|
|
|
model_cutoff_definition |
36
|
|
|
|
|
|
|
nutation obliquity order period time_set year |
37
|
|
|
|
|
|
|
__default |
38
|
|
|
|
|
|
|
__get_attr |
39
|
|
|
|
|
|
|
__mutate_model_cutoff __mutate_nutation_cutoff |
40
|
|
|
|
|
|
|
}; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
our @EXPORT_OK = ( |
43
|
|
|
|
|
|
|
@basic_export, |
44
|
|
|
|
|
|
|
qw{ |
45
|
|
|
|
|
|
|
geometric_longitude |
46
|
|
|
|
|
|
|
synodic_period |
47
|
|
|
|
|
|
|
__angle_subtended_from_earth |
48
|
|
|
|
|
|
|
__longitude_from_sun |
49
|
|
|
|
|
|
|
__model |
50
|
|
|
|
|
|
|
}, |
51
|
|
|
|
|
|
|
); |
52
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
53
|
|
|
|
|
|
|
mixin => [ @basic_export, qw{ |
54
|
|
|
|
|
|
|
synodic_period |
55
|
|
|
|
|
|
|
__angle_subtended_from_earth |
56
|
|
|
|
|
|
|
__longitude_from_sun |
57
|
|
|
|
|
|
|
__model |
58
|
|
|
|
|
|
|
} ], |
59
|
|
|
|
|
|
|
sun => [ @basic_export, qw{ geometric_longitude } ], |
60
|
|
|
|
|
|
|
); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# We want to ensure SUN_CLASS is loaded because it is our default Sun |
63
|
|
|
|
|
|
|
# implementation, but we do it at run time to avoid a circular |
64
|
|
|
|
|
|
|
# dependency. |
65
|
|
|
|
|
|
|
load_module( SUN_CLASS ); |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub time_set { |
68
|
3011
|
|
|
3011
|
1
|
193284
|
my ( $self ) = @_; |
69
|
3011
|
|
|
|
|
8319
|
my $attr = $self->__get_attr(); |
70
|
3011
|
|
|
|
|
8254
|
my $time = $self->dynamical(); |
71
|
3011
|
|
|
|
|
70701
|
my $cutoff = $self->get( 'model_cutoff' ); |
72
|
3011
|
|
|
|
|
7989
|
my $cutoff_def = $self->model_cutoff_definition(); |
73
|
3011
|
|
|
|
|
6848
|
my $sun = $self->get( 'sun' ); |
74
|
|
|
|
|
|
|
|
75
|
3011
|
|
|
|
|
5292
|
DEBUG |
76
|
|
|
|
|
|
|
and printf <<'EOD', ref $self, ref $sun, julianday( $time ); |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
self = %s |
79
|
|
|
|
|
|
|
Sun = %s |
80
|
|
|
|
|
|
|
JDE = %.5f |
81
|
|
|
|
|
|
|
EOD |
82
|
|
|
|
|
|
|
|
83
|
3011
|
|
|
|
|
7929
|
my $T = jcent2000( $time ); |
84
|
|
|
|
|
|
|
|
85
|
3011
|
|
|
|
|
20085
|
my ( $Lb, $Bb, $Rb ) = $self->__model( $time, |
86
|
|
|
|
|
|
|
model_cutoff_definition => $cutoff_def, |
87
|
|
|
|
|
|
|
); |
88
|
|
|
|
|
|
|
|
89
|
3011
|
|
|
|
|
6958
|
my ( $Le, $Be, $Re ); |
90
|
|
|
|
|
|
|
|
91
|
3011
|
50
|
|
|
|
15217
|
if ( $sun->isa( SUN_CLASS ) ) { |
92
|
|
|
|
|
|
|
# We call __model as a subroutine because the Earth's model |
93
|
|
|
|
|
|
|
# parameters are hung on the Sun, but if we call it as a method |
94
|
|
|
|
|
|
|
# we get the Sun's model, which always returns zeroes. |
95
|
3011
|
|
|
|
|
8318
|
( $Le, $Be, $Re ) = __model( SUN_CLASS, $time, |
96
|
|
|
|
|
|
|
model_cutoff_definition => $sun->model_cutoff_definition( $cutoff ), |
97
|
|
|
|
|
|
|
); |
98
|
|
|
|
|
|
|
} else { |
99
|
0
|
|
|
|
|
0
|
confess sprintf 'TODO Sun class %s not supported', ref $sun; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
3011
|
|
|
|
|
5903
|
DEBUG |
103
|
|
|
|
|
|
|
and printf <<'EOD', rad2deg( $Le ), rad2deg( $Be ), $Re; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
Heliocentric position of the Earth: |
106
|
|
|
|
|
|
|
L0 = %.5f |
107
|
|
|
|
|
|
|
B0 = %.5f |
108
|
|
|
|
|
|
|
R0 = %.6f |
109
|
|
|
|
|
|
|
EOD |
110
|
|
|
|
|
|
|
|
111
|
3011
|
|
|
|
|
6096
|
my ( $lambda, $beta, $Delta, $long_sym ); |
112
|
3011
|
100
|
|
|
|
7481
|
if ( $Rb ) { # Not the Sun |
113
|
|
|
|
|
|
|
|
114
|
1719
|
|
|
|
|
2812
|
my $last_tau = 0; |
115
|
|
|
|
|
|
|
|
116
|
1719
|
|
|
|
|
3038
|
while ( 1 ) { |
117
|
3789
|
|
|
|
|
6006
|
DEBUG |
118
|
|
|
|
|
|
|
and printf <<'EOD', $self->get( 'name' ), |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Heliocentric position of %s: |
121
|
|
|
|
|
|
|
L = %.5f |
122
|
|
|
|
|
|
|
B = %.5f |
123
|
|
|
|
|
|
|
R = %.6f |
124
|
|
|
|
|
|
|
EOD |
125
|
|
|
|
|
|
|
rad2deg( $Lb ), rad2deg( $Bb ), $Rb; |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# Meeus 33.1 |
128
|
3789
|
|
|
|
|
8094
|
my $cosBb = cos( $Bb ); |
129
|
3789
|
|
|
|
|
6410
|
my $cosBe = cos( $Be ); |
130
|
3789
|
|
|
|
|
9290
|
my $x = $Rb * $cosBb * cos( $Lb ) - $Re * $cosBe * cos( $Le ); |
131
|
3789
|
|
|
|
|
9775
|
my $y = $Rb * $cosBb * sin( $Lb ) - $Re * $cosBe * sin( $Le ); |
132
|
3789
|
|
|
|
|
7419
|
my $z = $Rb * sin( $Bb ) - $Re * sin( $Be ); |
133
|
|
|
|
|
|
|
|
134
|
3789
|
|
|
|
|
7277
|
$Delta = sqrt( $x * $x + $y * $y + $z * $z ); |
135
|
|
|
|
|
|
|
|
136
|
13
|
|
|
13
|
|
109
|
use constant TAU_FACTOR => 0.005_775_518_3 * SECSPERDAY; |
|
13
|
|
|
|
|
30
|
|
|
13
|
|
|
|
|
3487
|
|
137
|
3789
|
|
|
|
|
6069
|
my $tau = TAU_FACTOR * $Delta; |
138
|
|
|
|
|
|
|
|
139
|
3789
|
|
|
|
|
5555
|
DEBUG |
140
|
|
|
|
|
|
|
and printf <<'EOD', $x, $y, $z, $Delta, $tau / SECSPERDAY; |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
x = %+.6f |
143
|
|
|
|
|
|
|
y = %+.6f |
144
|
|
|
|
|
|
|
z = %+.6f |
145
|
|
|
|
|
|
|
𝚫 = %.6f |
146
|
|
|
|
|
|
|
𝛕 = %.7f day |
147
|
|
|
|
|
|
|
EOD |
148
|
3789
|
100
|
|
|
|
45072
|
if ( ( my $check = sprintf '%.1f', $tau ) ne $last_tau ) { |
149
|
2070
|
|
|
|
|
4007
|
$last_tau = $check; |
150
|
|
|
|
|
|
|
|
151
|
2070
|
|
|
|
|
3410
|
DEBUG |
152
|
|
|
|
|
|
|
and printf <<'EOD', julianday( $time - $tau ); |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
new JDE = %.5f |
155
|
|
|
|
|
|
|
EOD |
156
|
2070
|
|
|
|
|
7258
|
( $Lb, $Bb, $Rb ) = $self->__model( |
157
|
|
|
|
|
|
|
$time - $tau, |
158
|
|
|
|
|
|
|
model_cutoff_definition => $cutoff_def, |
159
|
|
|
|
|
|
|
); |
160
|
|
|
|
|
|
|
} else { |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Meeus 33.2 |
163
|
1719
|
|
|
|
|
6938
|
$lambda = atan2( $y, $x ); |
164
|
1719
|
100
|
|
|
|
6012
|
$lambda < 0 |
165
|
|
|
|
|
|
|
and $lambda += TWOPI; |
166
|
1719
|
|
|
|
|
4227
|
$beta = atan2( $z, sqrt( $x * $x + $y * $y ) ); |
167
|
1719
|
|
|
|
|
3205
|
$long_sym = '𝛌'; |
168
|
1719
|
|
|
|
|
4195
|
last; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
DEBUG |
173
|
1719
|
|
|
|
|
2516
|
and printf <<'EOD', $long_sym, |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Geocentric ecliptic position: |
176
|
|
|
|
|
|
|
%s = %.5f |
177
|
|
|
|
|
|
|
= %s |
178
|
|
|
|
|
|
|
𝛃 = %.5f |
179
|
|
|
|
|
|
|
= %s |
180
|
|
|
|
|
|
|
EOD |
181
|
|
|
|
|
|
|
rad2deg( $lambda ), rad2dms( $lambda ), |
182
|
|
|
|
|
|
|
rad2deg( $beta ), rad2dms( $beta ); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Meeus corrects for aberration here for a planet, before |
185
|
|
|
|
|
|
|
# conversion to FK5. It makes no real difference to the answer, |
186
|
|
|
|
|
|
|
# since everything done to the latitude and longitude before |
187
|
|
|
|
|
|
|
# conversion to equatorial is just addition and subtraction, and |
188
|
|
|
|
|
|
|
# therefore commutes. But it plays merry Hell with the poor slob |
189
|
|
|
|
|
|
|
# who is trying to verify code versus the worked examples, |
190
|
|
|
|
|
|
|
# because it changes the intermediate results. Sigh. |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Aberration per Meeus 23.2 |
193
|
13
|
|
|
|
|
84
|
use constant CONSTANT_OF_ABERRATION => deg2rad( |
194
|
13
|
|
|
13
|
|
102
|
20.49552 / 3600 ); |
|
13
|
|
|
|
|
27
|
|
195
|
|
|
|
|
|
|
# Longitude of the Sun |
196
|
1719
|
|
|
|
|
4956
|
my $Ls = mod2pi( $Le + PI ); |
197
|
|
|
|
|
|
|
# Eccentricity of the Earth's orbit |
198
|
1719
|
|
|
|
|
8867
|
my $e = ( - 0.000_000_126_7 * $T - 0.000_042_037 ) * $T + |
199
|
|
|
|
|
|
|
0.016_708_634; |
200
|
|
|
|
|
|
|
# Longitude of perihelion of the Earth's orbit |
201
|
1719
|
|
|
|
|
5988
|
my $pi = deg2rad( ( 0.000_46 * $T + 1.71946 ) * $T + 102.93735 ); |
202
|
|
|
|
|
|
|
|
203
|
1719
|
|
|
|
|
10336
|
my $delta_lambda = ( ( $e * cos( $pi - $lambda ) - cos( $Ls - |
204
|
|
|
|
|
|
|
$lambda ) ) / cos $beta ) * CONSTANT_OF_ABERRATION; |
205
|
1719
|
|
|
|
|
5144
|
my $delta_beta = - sin( $beta ) * ( sin( $Ls - $lambda ) - $e * |
206
|
|
|
|
|
|
|
sin( $pi - $lambda ) ) * CONSTANT_OF_ABERRATION; |
207
|
1719
|
|
|
|
|
2602
|
$lambda += $delta_lambda; |
208
|
1719
|
|
|
|
|
2879
|
$beta += $delta_beta; |
209
|
|
|
|
|
|
|
|
210
|
1719
|
|
|
|
|
2990
|
DEBUG |
211
|
|
|
|
|
|
|
and printf <<'EOD', |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
Planetary aberration: |
214
|
|
|
|
|
|
|
𝚫𝛌 = %s |
215
|
|
|
|
|
|
|
𝛌 = %.5f |
216
|
|
|
|
|
|
|
= %s |
217
|
|
|
|
|
|
|
𝚫𝛃 = %s |
218
|
|
|
|
|
|
|
𝛃 = %.5f |
219
|
|
|
|
|
|
|
= %s |
220
|
|
|
|
|
|
|
EOD |
221
|
|
|
|
|
|
|
rad2dms( $delta_lambda), rad2deg( $lambda ), rad2dms( $lambda ), |
222
|
|
|
|
|
|
|
rad2dms( $delta_beta), rad2deg( $beta ), rad2dms( $beta ); |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
} else { # The Sun |
225
|
1292
|
|
|
|
|
3686
|
( $lambda, $beta, $Delta ) = ( mod2pi( $Le + PI ), - $Be, $Re ); |
226
|
1292
|
|
|
|
|
6656
|
$long_sym = '☉'; |
227
|
|
|
|
|
|
|
|
228
|
1292
|
|
|
|
|
2074
|
DEBUG |
229
|
|
|
|
|
|
|
and printf <<'EOD', $long_sym, |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Geocentric ecliptic position: |
232
|
|
|
|
|
|
|
%s = %.5f |
233
|
|
|
|
|
|
|
= %s |
234
|
|
|
|
|
|
|
𝛃 = %.5f |
235
|
|
|
|
|
|
|
= %s |
236
|
|
|
|
|
|
|
EOD |
237
|
|
|
|
|
|
|
rad2deg( $lambda ), rad2dms( $lambda ), |
238
|
|
|
|
|
|
|
rad2deg( $beta ), rad2dms( $beta ); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
3011
|
|
|
|
|
4918
|
DEBUG |
242
|
|
|
|
|
|
|
and printf <<'EOD', |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
%s = %.6f |
245
|
|
|
|
|
|
|
𝛃 = %.6f |
246
|
|
|
|
|
|
|
= %s |
247
|
|
|
|
|
|
|
𝚫 = %.6f |
248
|
|
|
|
|
|
|
EOD |
249
|
|
|
|
|
|
|
$long_sym, rad2deg( $lambda ), |
250
|
|
|
|
|
|
|
rad2deg( $beta ), rad2dms( $beta ), $Delta; |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# Convert to FK5. Meeus says (ch. 25 pg 166) this is necessary for |
253
|
|
|
|
|
|
|
# high accuracy (though not if using his truncated VSOP87D), though |
254
|
|
|
|
|
|
|
# Bretagnon & Francou seem to say it is needed only for VSOP87 and |
255
|
|
|
|
|
|
|
# VSOP87E. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Meeus 32.3 |
258
|
|
|
|
|
|
|
{ |
259
|
13
|
|
|
13
|
|
3597
|
use constant DYN_TO_FK5_LINEAR => deg2rad( 1.397 ); |
|
13
|
|
|
|
|
43
|
|
|
13
|
|
|
|
|
56
|
|
|
3011
|
|
|
|
|
5011
|
|
260
|
13
|
|
|
13
|
|
918
|
use constant DYN_TO_FK5_QUADRATIC => deg2rad( 0.00031 ); |
|
13
|
|
|
|
|
30
|
|
|
13
|
|
|
|
|
51
|
|
261
|
13
|
|
|
13
|
|
1018
|
use constant DYN_TO_FK5_DELTA_LON => - deg2rad( 0.09033 / 3600 ); |
|
13
|
|
|
|
|
27
|
|
|
13
|
|
|
|
|
56
|
|
262
|
13
|
|
|
13
|
|
966
|
use constant DYN_TO_FK5_FACTOR => deg2rad( 0.03916 / 3600 ); |
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
46
|
|
263
|
3011
|
|
|
|
|
6764
|
my $lambda_prime = $lambda - ( DYN_TO_FK5_LINEAR + |
264
|
|
|
|
|
|
|
DYN_TO_FK5_QUADRATIC * $T ) * $T; |
265
|
3011
|
|
|
|
|
7232
|
my $factor = DYN_TO_FK5_FACTOR * ( cos( $lambda_prime ) - sin( |
266
|
|
|
|
|
|
|
$lambda_prime ) ); |
267
|
3011
|
|
|
|
|
9534
|
my $delta_lambda = DYN_TO_FK5_DELTA_LON + $factor * tan( $beta ); |
268
|
3011
|
|
|
|
|
12738
|
my $delta_beta = $factor; |
269
|
|
|
|
|
|
|
|
270
|
3011
|
|
|
|
|
4676
|
DEBUG and printf <<'EOD', |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Conversion to FK5 |
273
|
|
|
|
|
|
|
𝛌' = %.2f |
274
|
|
|
|
|
|
|
𝚫%s = %s |
275
|
|
|
|
|
|
|
𝚫𝛃 = %s |
276
|
|
|
|
|
|
|
EOD |
277
|
|
|
|
|
|
|
rad2deg( $lambda_prime ), $long_sym, |
278
|
|
|
|
|
|
|
rad2dms( $delta_lambda, 5 ), rad2dms( $delta_beta ); |
279
|
|
|
|
|
|
|
|
280
|
3011
|
|
|
|
|
4783
|
$lambda += $delta_lambda; |
281
|
3011
|
|
|
|
|
4610
|
$beta += $delta_beta; |
282
|
|
|
|
|
|
|
|
283
|
3011
|
|
|
|
|
4482
|
DEBUG and printf <<'EOD', |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
%s = %.5f |
286
|
|
|
|
|
|
|
= %s |
287
|
|
|
|
|
|
|
𝛃 = %.5f |
288
|
|
|
|
|
|
|
= %s |
289
|
|
|
|
|
|
|
EOD |
290
|
|
|
|
|
|
|
$long_sym, rad2deg( $lambda ), rad2dms( $lambda ), |
291
|
|
|
|
|
|
|
rad2deg( $beta ), rad2dms( $beta ), |
292
|
|
|
|
|
|
|
; |
293
|
|
|
|
|
|
|
|
294
|
3011
|
|
|
|
|
7577
|
$attr->{geometric_longitude} = $lambda; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# Nutation |
298
|
3011
|
|
|
|
|
10999
|
my ( $delta_psi, $delta_eps ) = $self->nutation( $time ); |
299
|
3011
|
|
|
|
|
14852
|
$lambda += $delta_psi; |
300
|
|
|
|
|
|
|
|
301
|
3011
|
|
|
|
|
4502
|
DEBUG |
302
|
|
|
|
|
|
|
and printf <<"EOD", |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
Nutation: |
305
|
|
|
|
|
|
|
𝚫𝛙 = %s |
306
|
|
|
|
|
|
|
𝚫𝛆 = %s |
307
|
|
|
|
|
|
|
𝛌 = %.5f |
308
|
|
|
|
|
|
|
= %s |
309
|
|
|
|
|
|
|
EOD |
310
|
|
|
|
|
|
|
rad2dms( $delta_psi ), rad2dms( $delta_eps ), |
311
|
|
|
|
|
|
|
rad2deg( $lambda ), rad2dms( $lambda ); |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# Obliquity per Meeus 22.3 |
314
|
3011
|
|
|
|
|
9208
|
my $epsilon = $self->obliquity( $time ); |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Meeus 25.10 |
317
|
|
|
|
|
|
|
|
318
|
3011
|
100
|
|
|
|
7687
|
unless ( $Rb ) { # The Sun. |
319
|
|
|
|
|
|
|
# Aberration |
320
|
13
|
|
|
13
|
|
3781
|
use constant SOLAR_ABERRATION_FACTOR => - deg2rad( 20.4898 / 3600 ); |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
74
|
|
321
|
1292
|
|
|
|
|
2637
|
my $delta_lambda = SOLAR_ABERRATION_FACTOR / $Delta; |
322
|
1292
|
|
|
|
|
2027
|
$lambda += $delta_lambda; |
323
|
|
|
|
|
|
|
|
324
|
1292
|
|
|
|
|
1963
|
DEBUG |
325
|
|
|
|
|
|
|
and printf <<'EOD', |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
Solar aberration: |
328
|
|
|
|
|
|
|
𝚫𝛌 = %s |
329
|
|
|
|
|
|
|
𝛌 = %.5f |
330
|
|
|
|
|
|
|
= %s |
331
|
|
|
|
|
|
|
EOD |
332
|
|
|
|
|
|
|
rad2dms( $delta_lambda), rad2deg( $lambda ), rad2dms( $lambda ); |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
DEBUG |
336
|
3011
|
|
|
|
|
4195
|
and printf <<'EOD', $long_sym, |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
Final ecliptic coordinates: |
339
|
|
|
|
|
|
|
%s = %.5f |
340
|
|
|
|
|
|
|
= %s |
341
|
|
|
|
|
|
|
𝛃 = %.5f |
342
|
|
|
|
|
|
|
= %s |
343
|
|
|
|
|
|
|
EOD |
344
|
|
|
|
|
|
|
rad2deg( $lambda ), rad2dms( $lambda ), |
345
|
|
|
|
|
|
|
rad2deg( $beta ), rad2dms( $beta ); |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# NOTE: I could have stored the ecliptic coordinates at this point, |
348
|
|
|
|
|
|
|
# and trusted Astro::Coord::ECI to get the conversion right, but |
349
|
|
|
|
|
|
|
# since I was at this point not confident in that code, I decided to |
350
|
|
|
|
|
|
|
# see Meeus' example all the way to the end. |
351
|
|
|
|
|
|
|
# |
352
|
|
|
|
|
|
|
# Once nutation and obliquity became methods, it turns out that my |
353
|
|
|
|
|
|
|
# conversion between ecliptic and equatorial is equivalent to Meeus' |
354
|
|
|
|
|
|
|
# to his accuracy in the examples. That is, if I store equatorial, I |
355
|
|
|
|
|
|
|
# get back exactuly the same ecliptic coordiantes as I calculated |
356
|
|
|
|
|
|
|
# above. If I store ecliptic, I get back the same equatorial that |
357
|
|
|
|
|
|
|
# Meeus calculated. |
358
|
|
|
|
|
|
|
# |
359
|
|
|
|
|
|
|
# My current intent is to keep the code as-is, simply because for |
360
|
|
|
|
|
|
|
# verification purposes I want it to be as close as possible to |
361
|
|
|
|
|
|
|
# Meeus' example. |
362
|
|
|
|
|
|
|
|
363
|
3011
|
|
|
|
|
6050
|
my $sin_eps = sin $epsilon; |
364
|
3011
|
|
|
|
|
5156
|
my $cos_eps = cos $epsilon; |
365
|
3011
|
|
|
|
|
5214
|
my $sin_lam = sin $lambda; |
366
|
3011
|
|
|
|
|
4520
|
my $sin_bet = sin $beta; |
367
|
3011
|
|
|
|
|
4891
|
my $cos_bet = cos $beta; |
368
|
3011
|
|
|
|
|
14039
|
my $alpha = mod2pi( atan2( |
369
|
|
|
|
|
|
|
$sin_lam * $cos_eps - $sin_bet / $cos_bet * $sin_eps, |
370
|
|
|
|
|
|
|
cos $lambda ) ); # Meeus 13.3 |
371
|
3011
|
|
|
|
|
18700
|
my $delta = asin( $sin_bet * $cos_eps + $cos_bet * $sin_eps * |
372
|
|
|
|
|
|
|
$sin_lam ); # Meeus 13.4 |
373
|
|
|
|
|
|
|
|
374
|
3011
|
|
|
|
|
13033
|
DEBUG |
375
|
|
|
|
|
|
|
and printf <<'EOD', |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
Equatorial coordinates: |
378
|
|
|
|
|
|
|
𝛂 = %.6f |
379
|
|
|
|
|
|
|
= %s |
380
|
|
|
|
|
|
|
𝛅 = %.6f |
381
|
|
|
|
|
|
|
= %s |
382
|
|
|
|
|
|
|
EOD |
383
|
|
|
|
|
|
|
rad2deg( $alpha ), rad2hms( $alpha ), |
384
|
|
|
|
|
|
|
rad2deg( $delta ), rad2dms( $delta, 2 ); |
385
|
|
|
|
|
|
|
|
386
|
3011
|
|
|
|
|
14964
|
$self->equatorial( $alpha, $delta, $Delta * AU ); |
387
|
3011
|
|
|
|
|
527719
|
$self->equinox_dynamical( $time ); |
388
|
|
|
|
|
|
|
|
389
|
3011
|
|
|
|
|
18951
|
if ( DEBUG ) { |
390
|
|
|
|
|
|
|
my ( $lat, $lon ) = $self->ecliptic(); |
391
|
|
|
|
|
|
|
printf <<'EOD', $long_sym, |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
Check -- recovered ecliptic coordinates: |
394
|
|
|
|
|
|
|
%s = %.5f |
395
|
|
|
|
|
|
|
= %s |
396
|
|
|
|
|
|
|
𝛃 = %.5f |
397
|
|
|
|
|
|
|
= %s |
398
|
|
|
|
|
|
|
EOD |
399
|
|
|
|
|
|
|
rad2deg( $lon ), rad2dms( $lon ), |
400
|
|
|
|
|
|
|
rad2deg( $lat ), rad2dms( $lat ); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
3011
|
|
|
|
|
8462
|
return $self; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
{ |
407
|
|
|
|
|
|
|
my $earth; |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# NOTE that the sign of the angle returned is the same as the sign |
410
|
|
|
|
|
|
|
# of the result of __longitude_from_sun(). |
411
|
|
|
|
|
|
|
sub __angle_subtended_from_earth { |
412
|
246
|
|
|
246
|
|
588
|
my ( $self, $time ) = @_; |
413
|
246
|
100
|
|
|
|
630
|
defined $time |
414
|
|
|
|
|
|
|
or $time = $self->universal(); |
415
|
246
|
|
66
|
|
|
751
|
$earth ||= Astro::Coord::ECI->new()->eci( 0, 0, 0 ); |
416
|
246
|
|
|
|
|
977
|
$self->universal( $time ); |
417
|
246
|
|
|
|
|
3061
|
my $sun = $self->get( 'sun' )->universal( $time ); |
418
|
246
|
|
|
|
|
2958
|
$earth->universal( $time ); |
419
|
246
|
|
|
|
|
8346
|
my $lon = $self->__longitude_from_sun(); |
420
|
246
|
|
|
|
|
1494
|
my $angle = $earth->angle( $self, $sun ); |
421
|
246
|
100
|
|
|
|
84775
|
return $lon < 0 ? -$angle : $angle; |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub geometric_longitude { |
426
|
1
|
|
|
1
|
1
|
14
|
my ( $self ) = @_; |
427
|
1
|
|
|
|
|
3
|
my $attr = $self->__get_attr(); |
428
|
|
|
|
|
|
|
defined $attr->{geometric_longitude} |
429
|
1
|
50
|
|
|
|
5
|
and return $attr->{geometric_longitude}; |
430
|
0
|
|
|
|
|
0
|
croak 'Geometric longitude undefined -- time not set'; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub __longitude_from_sun { |
434
|
1248
|
|
|
1248
|
|
2907
|
my ( $self, $time, $offset ) = @_; |
435
|
1248
|
|
100
|
|
|
4297
|
$offset ||= 0; |
436
|
|
|
|
|
|
|
|
437
|
1248
|
100
|
|
|
|
2912
|
if ( defined $time ) { |
438
|
1002
|
|
|
|
|
2793
|
$self->universal( $time ); |
439
|
|
|
|
|
|
|
} else { |
440
|
246
|
|
|
|
|
555
|
$time = $self->universal(); |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
1248
|
|
|
|
|
17483
|
my $sun = $self->get( 'sun' )->universal( $time ); |
444
|
|
|
|
|
|
|
|
445
|
1248
|
|
|
|
|
16476
|
my ( undef, $lon_b ) = $self->ecliptic(); |
446
|
1248
|
|
|
|
|
85127
|
my ( undef, $lon_s ) = $sun->ecliptic(); |
447
|
|
|
|
|
|
|
|
448
|
1248
|
|
|
|
|
68096
|
return mod2pi( $lon_b - $lon_s - $offset + PI ) - PI; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
0
|
BEGIN { |
452
|
13
|
|
|
13
|
|
25501
|
my @model = ( |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# The following are from the IAU SOFA module src/nut80.c, from |
455
|
|
|
|
|
|
|
# http://www.iausofa.org/2018_0130_C/sofa_c-20180130.tar.gz |
456
|
|
|
|
|
|
|
# The only edit is the change from curly to square brackets and |
457
|
|
|
|
|
|
|
# the brute-force conversion of C comments to Perl comments. The |
458
|
|
|
|
|
|
|
# columns are: |
459
|
|
|
|
|
|
|
# IAU: nl nlp nf nd nom sp spt ce cet |
460
|
|
|
|
|
|
|
# Meeus: M' M F D 𝛀 |
461
|
|
|
|
|
|
|
# /* 1-10 */ |
462
|
|
|
|
|
|
|
[ 0, 0, 0, 0, 1, -171996.0, -174.2, 92025.0, 8.9 ], |
463
|
|
|
|
|
|
|
[ 0, 0, 0, 0, 2, 2062.0, 0.2, -895.0, 0.5 ], |
464
|
|
|
|
|
|
|
[ -2, 0, 2, 0, 1, 46.0, 0.0, -24.0, 0.0 ], |
465
|
|
|
|
|
|
|
[ 2, 0, -2, 0, 0, 11.0, 0.0, 0.0, 0.0 ], |
466
|
|
|
|
|
|
|
[ -2, 0, 2, 0, 2, -3.0, 0.0, 1.0, 0.0 ], |
467
|
|
|
|
|
|
|
[ 1, -1, 0, -1, 0, -3.0, 0.0, 0.0, 0.0 ], |
468
|
|
|
|
|
|
|
[ 0, -2, 2, -2, 1, -2.0, 0.0, 1.0, 0.0 ], |
469
|
|
|
|
|
|
|
[ 2, 0, -2, 0, 1, 1.0, 0.0, 0.0, 0.0 ], |
470
|
|
|
|
|
|
|
[ 0, 0, 2, -2, 2, -13187.0, -1.6, 5736.0, -3.1 ], |
471
|
|
|
|
|
|
|
[ 0, 1, 0, 0, 0, 1426.0, -3.4, 54.0, -0.1 ], |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
# /* 11-20 */ |
474
|
|
|
|
|
|
|
[ 0, 1, 2, -2, 2, -517.0, 1.2, 224.0, -0.6 ], |
475
|
|
|
|
|
|
|
[ 0, -1, 2, -2, 2, 217.0, -0.5, -95.0, 0.3 ], |
476
|
|
|
|
|
|
|
[ 0, 0, 2, -2, 1, 129.0, 0.1, -70.0, 0.0 ], |
477
|
|
|
|
|
|
|
[ 2, 0, 0, -2, 0, 48.0, 0.0, 1.0, 0.0 ], |
478
|
|
|
|
|
|
|
[ 0, 0, 2, -2, 0, -22.0, 0.0, 0.0, 0.0 ], |
479
|
|
|
|
|
|
|
[ 0, 2, 0, 0, 0, 17.0, -0.1, 0.0, 0.0 ], |
480
|
|
|
|
|
|
|
[ 0, 1, 0, 0, 1, -15.0, 0.0, 9.0, 0.0 ], |
481
|
|
|
|
|
|
|
[ 0, 2, 2, -2, 2, -16.0, 0.1, 7.0, 0.0 ], |
482
|
|
|
|
|
|
|
[ 0, -1, 0, 0, 1, -12.0, 0.0, 6.0, 0.0 ], |
483
|
|
|
|
|
|
|
[ -2, 0, 0, 2, 1, -6.0, 0.0, 3.0, 0.0 ], |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# /* 21-30 */ |
486
|
|
|
|
|
|
|
[ 0, -1, 2, -2, 1, -5.0, 0.0, 3.0, 0.0 ], |
487
|
|
|
|
|
|
|
[ 2, 0, 0, -2, 1, 4.0, 0.0, -2.0, 0.0 ], |
488
|
|
|
|
|
|
|
[ 0, 1, 2, -2, 1, 4.0, 0.0, -2.0, 0.0 ], |
489
|
|
|
|
|
|
|
[ 1, 0, 0, -1, 0, -4.0, 0.0, 0.0, 0.0 ], |
490
|
|
|
|
|
|
|
[ 2, 1, 0, -2, 0, 1.0, 0.0, 0.0, 0.0 ], |
491
|
|
|
|
|
|
|
[ 0, 0, -2, 2, 1, 1.0, 0.0, 0.0, 0.0 ], |
492
|
|
|
|
|
|
|
[ 0, 1, -2, 2, 0, -1.0, 0.0, 0.0, 0.0 ], |
493
|
|
|
|
|
|
|
[ 0, 1, 0, 0, 2, 1.0, 0.0, 0.0, 0.0 ], |
494
|
|
|
|
|
|
|
[ -1, 0, 0, 1, 1, 1.0, 0.0, 0.0, 0.0 ], |
495
|
|
|
|
|
|
|
[ 0, 1, 2, -2, 0, -1.0, 0.0, 0.0, 0.0 ], |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
# /* 31-40 */ |
498
|
|
|
|
|
|
|
[ 0, 0, 2, 0, 2, -2274.0, -0.2, 977.0, -0.5 ], |
499
|
|
|
|
|
|
|
[ 1, 0, 0, 0, 0, 712.0, 0.1, -7.0, 0.0 ], |
500
|
|
|
|
|
|
|
[ 0, 0, 2, 0, 1, -386.0, -0.4, 200.0, 0.0 ], |
501
|
|
|
|
|
|
|
[ 1, 0, 2, 0, 2, -301.0, 0.0, 129.0, -0.1 ], |
502
|
|
|
|
|
|
|
[ 1, 0, 0, -2, 0, -158.0, 0.0, -1.0, 0.0 ], |
503
|
|
|
|
|
|
|
[ -1, 0, 2, 0, 2, 123.0, 0.0, -53.0, 0.0 ], |
504
|
|
|
|
|
|
|
[ 0, 0, 0, 2, 0, 63.0, 0.0, -2.0, 0.0 ], |
505
|
|
|
|
|
|
|
[ 1, 0, 0, 0, 1, 63.0, 0.1, -33.0, 0.0 ], |
506
|
|
|
|
|
|
|
[ -1, 0, 0, 0, 1, -58.0, -0.1, 32.0, 0.0 ], |
507
|
|
|
|
|
|
|
[ -1, 0, 2, 2, 2, -59.0, 0.0, 26.0, 0.0 ], |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
# /* 41-50 */ |
510
|
|
|
|
|
|
|
[ 1, 0, 2, 0, 1, -51.0, 0.0, 27.0, 0.0 ], |
511
|
|
|
|
|
|
|
[ 0, 0, 2, 2, 2, -38.0, 0.0, 16.0, 0.0 ], |
512
|
|
|
|
|
|
|
[ 2, 0, 0, 0, 0, 29.0, 0.0, -1.0, 0.0 ], |
513
|
|
|
|
|
|
|
[ 1, 0, 2, -2, 2, 29.0, 0.0, -12.0, 0.0 ], |
514
|
|
|
|
|
|
|
[ 2, 0, 2, 0, 2, -31.0, 0.0, 13.0, 0.0 ], |
515
|
|
|
|
|
|
|
[ 0, 0, 2, 0, 0, 26.0, 0.0, -1.0, 0.0 ], |
516
|
|
|
|
|
|
|
[ -1, 0, 2, 0, 1, 21.0, 0.0, -10.0, 0.0 ], |
517
|
|
|
|
|
|
|
[ -1, 0, 0, 2, 1, 16.0, 0.0, -8.0, 0.0 ], |
518
|
|
|
|
|
|
|
[ 1, 0, 0, -2, 1, -13.0, 0.0, 7.0, 0.0 ], |
519
|
|
|
|
|
|
|
[ -1, 0, 2, 2, 1, -10.0, 0.0, 5.0, 0.0 ], |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
# /* 51-60 */ |
522
|
|
|
|
|
|
|
[ 1, 1, 0, -2, 0, -7.0, 0.0, 0.0, 0.0 ], |
523
|
|
|
|
|
|
|
[ 0, 1, 2, 0, 2, 7.0, 0.0, -3.0, 0.0 ], |
524
|
|
|
|
|
|
|
[ 0, -1, 2, 0, 2, -7.0, 0.0, 3.0, 0.0 ], |
525
|
|
|
|
|
|
|
[ 1, 0, 2, 2, 2, -8.0, 0.0, 3.0, 0.0 ], |
526
|
|
|
|
|
|
|
[ 1, 0, 0, 2, 0, 6.0, 0.0, 0.0, 0.0 ], |
527
|
|
|
|
|
|
|
[ 2, 0, 2, -2, 2, 6.0, 0.0, -3.0, 0.0 ], |
528
|
|
|
|
|
|
|
[ 0, 0, 0, 2, 1, -6.0, 0.0, 3.0, 0.0 ], |
529
|
|
|
|
|
|
|
[ 0, 0, 2, 2, 1, -7.0, 0.0, 3.0, 0.0 ], |
530
|
|
|
|
|
|
|
[ 1, 0, 2, -2, 1, 6.0, 0.0, -3.0, 0.0 ], |
531
|
|
|
|
|
|
|
[ 0, 0, 0, -2, 1, -5.0, 0.0, 3.0, 0.0 ], |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
# /* 61-70 */ |
534
|
|
|
|
|
|
|
[ 1, -1, 0, 0, 0, 5.0, 0.0, 0.0, 0.0 ], |
535
|
|
|
|
|
|
|
[ 2, 0, 2, 0, 1, -5.0, 0.0, 3.0, 0.0 ], |
536
|
|
|
|
|
|
|
[ 0, 1, 0, -2, 0, -4.0, 0.0, 0.0, 0.0 ], |
537
|
|
|
|
|
|
|
[ 1, 0, -2, 0, 0, 4.0, 0.0, 0.0, 0.0 ], |
538
|
|
|
|
|
|
|
[ 0, 0, 0, 1, 0, -4.0, 0.0, 0.0, 0.0 ], |
539
|
|
|
|
|
|
|
[ 1, 1, 0, 0, 0, -3.0, 0.0, 0.0, 0.0 ], |
540
|
|
|
|
|
|
|
[ 1, 0, 2, 0, 0, 3.0, 0.0, 0.0, 0.0 ], |
541
|
|
|
|
|
|
|
[ 1, -1, 2, 0, 2, -3.0, 0.0, 1.0, 0.0 ], |
542
|
|
|
|
|
|
|
[ -1, -1, 2, 2, 2, -3.0, 0.0, 1.0, 0.0 ], |
543
|
|
|
|
|
|
|
[ -2, 0, 0, 0, 1, -2.0, 0.0, 1.0, 0.0 ], |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
# /* 71-80 */ |
546
|
|
|
|
|
|
|
[ 3, 0, 2, 0, 2, -3.0, 0.0, 1.0, 0.0 ], |
547
|
|
|
|
|
|
|
[ 0, -1, 2, 2, 2, -3.0, 0.0, 1.0, 0.0 ], |
548
|
|
|
|
|
|
|
[ 1, 1, 2, 0, 2, 2.0, 0.0, -1.0, 0.0 ], |
549
|
|
|
|
|
|
|
[ -1, 0, 2, -2, 1, -2.0, 0.0, 1.0, 0.0 ], |
550
|
|
|
|
|
|
|
[ 2, 0, 0, 0, 1, 2.0, 0.0, -1.0, 0.0 ], |
551
|
|
|
|
|
|
|
[ 1, 0, 0, 0, 2, -2.0, 0.0, 1.0, 0.0 ], |
552
|
|
|
|
|
|
|
[ 3, 0, 0, 0, 0, 2.0, 0.0, 0.0, 0.0 ], |
553
|
|
|
|
|
|
|
[ 0, 0, 2, 1, 2, 2.0, 0.0, -1.0, 0.0 ], |
554
|
|
|
|
|
|
|
[ -1, 0, 0, 0, 2, 1.0, 0.0, -1.0, 0.0 ], |
555
|
|
|
|
|
|
|
[ 1, 0, 0, -4, 0, -1.0, 0.0, 0.0, 0.0 ], |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# /* 81-90 */ |
558
|
|
|
|
|
|
|
[ -2, 0, 2, 2, 2, 1.0, 0.0, -1.0, 0.0 ], |
559
|
|
|
|
|
|
|
[ -1, 0, 2, 4, 2, -2.0, 0.0, 1.0, 0.0 ], |
560
|
|
|
|
|
|
|
[ 2, 0, 0, -4, 0, -1.0, 0.0, 0.0, 0.0 ], |
561
|
|
|
|
|
|
|
[ 1, 1, 2, -2, 2, 1.0, 0.0, -1.0, 0.0 ], |
562
|
|
|
|
|
|
|
[ 1, 0, 2, 2, 1, -1.0, 0.0, 1.0, 0.0 ], |
563
|
|
|
|
|
|
|
[ -2, 0, 2, 4, 2, -1.0, 0.0, 1.0, 0.0 ], |
564
|
|
|
|
|
|
|
[ -1, 0, 4, 0, 2, 1.0, 0.0, 0.0, 0.0 ], |
565
|
|
|
|
|
|
|
[ 1, -1, 0, -2, 0, 1.0, 0.0, 0.0, 0.0 ], |
566
|
|
|
|
|
|
|
[ 2, 0, 2, -2, 1, 1.0, 0.0, -1.0, 0.0 ], |
567
|
|
|
|
|
|
|
[ 2, 0, 2, 2, 2, -1.0, 0.0, 0.0, 0.0 ], |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
# /* 91-100 */ |
570
|
|
|
|
|
|
|
[ 1, 0, 0, 2, 1, -1.0, 0.0, 0.0, 0.0 ], |
571
|
|
|
|
|
|
|
[ 0, 0, 4, -2, 2, 1.0, 0.0, 0.0, 0.0 ], |
572
|
|
|
|
|
|
|
[ 3, 0, 2, -2, 2, 1.0, 0.0, 0.0, 0.0 ], |
573
|
|
|
|
|
|
|
[ 1, 0, 2, -2, 0, -1.0, 0.0, 0.0, 0.0 ], |
574
|
|
|
|
|
|
|
[ 0, 1, 2, 0, 1, 1.0, 0.0, 0.0, 0.0 ], |
575
|
|
|
|
|
|
|
[ -1, -1, 0, 2, 1, 1.0, 0.0, 0.0, 0.0 ], |
576
|
|
|
|
|
|
|
[ 0, 0, -2, 0, 1, -1.0, 0.0, 0.0, 0.0 ], |
577
|
|
|
|
|
|
|
[ 0, 0, 2, -1, 2, -1.0, 0.0, 0.0, 0.0 ], |
578
|
|
|
|
|
|
|
[ 0, 1, 0, 2, 0, -1.0, 0.0, 0.0, 0.0 ], |
579
|
|
|
|
|
|
|
[ 1, 0, -2, -2, 0, -1.0, 0.0, 0.0, 0.0 ], |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
# /* 101-106 */ |
582
|
|
|
|
|
|
|
[ 0, -1, 2, 0, 1, -1.0, 0.0, 0.0, 0.0 ], |
583
|
|
|
|
|
|
|
[ 1, 1, 0, -2, 1, -1.0, 0.0, 0.0, 0.0 ], |
584
|
|
|
|
|
|
|
[ 1, 0, -2, 2, 0, -1.0, 0.0, 0.0, 0.0 ], |
585
|
|
|
|
|
|
|
[ 2, 0, 0, 2, 0, 1.0, 0.0, 0.0, 0.0 ], |
586
|
|
|
|
|
|
|
[ 0, 0, 2, 4, 2, -1.0, 0.0, 0.0, 0.0 ], |
587
|
|
|
|
|
|
|
[ 0, 1, 0, 1, 0, 1.0, 0.0, 0.0, 0.0 ] |
588
|
|
|
|
|
|
|
); |
589
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
# UNDOCUMENTED AND UNSUPPORTED -- MAY BE CHANGED OR REVOKED WITHOUT |
591
|
|
|
|
|
|
|
# WARNING |
592
|
|
|
|
|
|
|
# Return the IAU 1980 nutation model, as array references. Each |
593
|
|
|
|
|
|
|
# reference contains one term of the model, in the following order |
594
|
|
|
|
|
|
|
# in Meeus' terminology: |
595
|
|
|
|
|
|
|
# M' M F D Omega delta psi( const, T ), delta # epsilon( const, T ). |
596
|
|
|
|
|
|
|
sub __iau1980_nutation_model { |
597
|
0
|
|
|
0
|
|
0
|
return @model; |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
# This may be a premature optimization, BUT the nutation in |
601
|
|
|
|
|
|
|
# longitude and obliquity are used different places, so I anticipate |
602
|
|
|
|
|
|
|
# this getting called twice by time_set(), with the same time. So: |
603
|
13
|
|
|
|
|
60
|
my $memoize_args = ''; |
604
|
13
|
|
|
|
|
20730
|
my @memoize_result; |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub nutation { |
607
|
8281
|
|
|
8281
|
1
|
17050
|
my ( $self, $time, $cutoff ) = @_; |
608
|
|
|
|
|
|
|
|
609
|
8281
|
50
|
|
|
|
17947
|
defined $time |
610
|
|
|
|
|
|
|
or $time = $self->dynamical(); |
611
|
|
|
|
|
|
|
|
612
|
8281
|
|
50
|
|
|
33274
|
$cutoff ||= 0; # milli arc seconds. Meeus is 3 |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
{ |
615
|
8281
|
100
|
|
|
|
11553
|
( my $memo = "$time $cutoff" ) eq $memoize_args |
|
8281
|
|
|
|
|
66548
|
|
616
|
|
|
|
|
|
|
and return @memoize_result; |
617
|
1943
|
|
|
|
|
4058
|
$memoize_args = $memo; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
1943
|
|
|
|
|
5508
|
my $T = jcent2000( $time ); # Meeus 22.1 |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
# All this from Meeus Ch 22 pp 143ff, expressed in degrees |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# Mean elongation of Moon from Sun |
625
|
1943
|
|
|
|
|
13156
|
my $D = ( ( $T / 189_474 - 0.001_914_2 ) * $T + 445_267.111_480 |
626
|
|
|
|
|
|
|
) * $T + 297.850_36; |
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
# Mean anomaly of the Sun (Earth) |
629
|
1943
|
|
|
|
|
4972
|
my $M = ( ( - $T / 300_000 - 0.000_160_3 ) * $T + 35_999.050_340 |
630
|
|
|
|
|
|
|
) * $T + 357.527_72; |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
# Mean anomaly of the Moon |
633
|
1943
|
|
|
|
|
4174
|
my $M_prime = ( ( $T / 56_250 + 0.008_697_2 ) * $T + 477_198.867_398 |
634
|
|
|
|
|
|
|
) * $T + 134.962_98; |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
# Moon's argument of latitude |
637
|
1943
|
|
|
|
|
4374
|
my $F = ( ( $T / 327_270 - 0.003_682_5 ) * $T + 483_202.017_538 |
638
|
|
|
|
|
|
|
) * $T + 93.271_91; |
639
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
# Logitude of the ascending node of the Moon's mean orbit on the |
641
|
|
|
|
|
|
|
# ecliptic, measured from the equinox of the date |
642
|
1943
|
|
|
|
|
4110
|
my $Omega = ( ( $T / 450_000 + 0.002_070_8 ) * $T - 1_934.136_261 |
643
|
|
|
|
|
|
|
) * $T + 125.044_52; |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
# Convert to radians, and store in same order as model source |
646
|
1943
|
|
|
|
|
4894
|
my @arg = map { deg2rad( $_ ) } ( $M_prime, $M, $F, $D, $Omega ); |
|
9715
|
|
|
|
|
31810
|
|
647
|
|
|
|
|
|
|
|
648
|
1943
|
|
|
|
|
10775
|
my ( $delta_psi, $delta_eps ) = ( 0, 0 ); |
649
|
1943
|
|
|
|
|
4534
|
foreach my $row ( @model ) { |
650
|
205958
|
|
|
|
|
379675
|
my $a = $arg[0] * $row->[0] + $arg[1] * $row->[1] + |
651
|
|
|
|
|
|
|
$arg[2] * $row->[2] + $arg[3] * $row->[3] + |
652
|
|
|
|
|
|
|
$arg[4] * $row->[4]; |
653
|
205958
|
50
|
33
|
|
|
537693
|
if ( $row->[5] && $cutoff <= abs $row->[5] ) { |
654
|
205958
|
|
|
|
|
339675
|
$delta_psi += ( $row->[6] * $T + $row->[5] ) * sin $a; |
655
|
|
|
|
|
|
|
} |
656
|
205958
|
100
|
66
|
|
|
488645
|
if ( $row->[7] && $cutoff <= abs $row->[7] ) { |
657
|
124352
|
|
|
|
|
227368
|
$delta_eps += ( $row->[8] * $T + $row->[7] ) * cos $a; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
# The model computes nutations in milli arc seconds, but we |
663
|
|
|
|
|
|
|
# return them in radians |
664
|
|
|
|
|
|
|
return ( @memoize_result = |
665
|
1943
|
|
|
|
|
4355
|
map { deg2rad( $_ / 3600_0000 ) } $delta_psi, $delta_eps ); |
|
3886
|
|
|
|
|
16266
|
|
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub __get_attr { |
671
|
15180
|
|
|
15180
|
|
24604
|
my ( $self ) = @_; |
672
|
15180
|
50
|
|
|
|
34227
|
my $ref = ref $self |
673
|
|
|
|
|
|
|
or confess 'Can not call as static method'; |
674
|
15180
|
|
100
|
|
|
44936
|
return $self->{$ref} ||= { |
675
|
|
|
|
|
|
|
model_cutoff_definition => dclone( $self->__model_definition( |
676
|
|
|
|
|
|
|
'default_model_cutoff' ) ), |
677
|
|
|
|
|
|
|
}; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub __default { |
681
|
27
|
|
|
27
|
|
80
|
my ( $class, $arg ) = @_; |
682
|
|
|
|
|
|
|
|
683
|
27
|
|
|
|
|
123
|
my $name = $class->__model_definition( 'body' ); |
684
|
|
|
|
|
|
|
defined $arg->{id} |
685
|
27
|
50
|
|
|
|
249
|
or $arg->{id} = $name; |
686
|
|
|
|
|
|
|
defined $arg->{name} |
687
|
27
|
50
|
|
|
|
113
|
or $arg->{name} = $name; |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
defined $arg->{diameter} |
690
|
27
|
50
|
|
|
|
241
|
or $arg->{diameter} = $class->__model_definition( 'diameter' ); |
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
defined $arg->{model_cutoff} |
693
|
27
|
100
|
|
|
|
184
|
or $arg->{model_cutoff} = 'Meeus'; |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
defined $arg->{nutation_cutoff} |
696
|
27
|
50
|
|
|
|
92
|
or $arg->{nutation_cutoff} = 3; |
697
|
|
|
|
|
|
|
|
698
|
27
|
|
|
|
|
139
|
return; |
699
|
|
|
|
|
|
|
} |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
sub __mutate_model_cutoff { |
702
|
28
|
|
|
28
|
|
99
|
my ( $self, $name, $val ) = @_; |
703
|
28
|
50
|
|
|
|
92
|
defined $val |
704
|
|
|
|
|
|
|
or croak "model cutoff must be defined"; |
705
|
28
|
50
|
|
|
|
164
|
$self->model_cutoff_definition( $val ) |
706
|
|
|
|
|
|
|
or croak "model cutoff '$val' is unknown"; |
707
|
28
|
|
|
|
|
116
|
$self->__get_attr()->{$name} = $val; |
708
|
28
|
|
|
|
|
113
|
return $self; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
sub model_cutoff_definition { |
712
|
6066
|
|
|
6066
|
1
|
13499
|
my ( $self, $name, @arg ) = @_; |
713
|
6066
|
100
|
|
|
|
16741
|
defined $name |
714
|
|
|
|
|
|
|
or $name = $self->get( 'model_cutoff' ); |
715
|
6066
|
|
|
|
|
13325
|
my $attr = $self->__get_attr(); |
716
|
6066
|
100
|
|
|
|
14062
|
if ( @arg ) { |
717
|
6
|
100
|
|
|
|
20
|
if ( defined( my $val = $arg[0] ) ) { |
718
|
4
|
100
|
|
|
|
16
|
unless ( ref $val ) { |
719
|
2
|
50
|
33
|
|
|
63
|
looks_like_number( $val ) |
720
|
|
|
|
|
|
|
and $val !~ m/ \A Inf (?: inity )? | NaN \z /smx |
721
|
|
|
|
|
|
|
or croak 'Scalar model cutoff definition must be a number'; |
722
|
2
|
|
|
|
|
6
|
my $num = $val; |
723
|
|
|
|
|
|
|
$val = sub { |
724
|
2
|
|
|
2
|
|
7
|
my ( @model ) = @_; |
725
|
2
|
|
|
|
|
4
|
my %cutoff; |
726
|
2
|
|
|
|
|
6
|
foreach my $series ( @model ) { |
727
|
34
|
|
|
|
|
48
|
my $count = 0; |
728
|
34
|
|
|
|
|
48
|
foreach my $term ( @{ $series->{terms} } ) { |
|
34
|
|
|
|
|
51
|
|
729
|
308
|
100
|
|
|
|
639
|
last if $term->[0] < $num; |
730
|
274
|
|
|
|
|
346
|
$count++; |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
$count |
733
|
34
|
100
|
|
|
|
76
|
and $cutoff{$series->{series}} = $count; |
734
|
|
|
|
|
|
|
} |
735
|
2
|
|
|
|
|
9
|
return \%cutoff; |
736
|
2
|
|
|
|
|
16
|
}; |
737
|
|
|
|
|
|
|
} |
738
|
4
|
100
|
|
|
|
19
|
if ( CODE_REF eq ref $val ) { |
739
|
|
|
|
|
|
|
$val = $val->( |
740
|
9
|
|
|
|
|
19
|
map { @{ $_ } } @{ |
|
9
|
|
|
|
|
34
|
|
741
|
3
|
|
|
|
|
9
|
$self->__model_definition( 'model' ) } |
|
3
|
|
|
|
|
13
|
|
742
|
|
|
|
|
|
|
); |
743
|
3
|
|
|
|
|
1025
|
$val->{name} = $name; |
744
|
|
|
|
|
|
|
} |
745
|
4
|
50
|
|
|
|
21
|
HASH_REF eq ref $val |
746
|
|
|
|
|
|
|
or croak 'The model cutoff definition value must be a hash ref'; |
747
|
|
|
|
|
|
|
my $terms = $self->__model_definition( |
748
|
4
|
|
|
|
|
21
|
'default_model_cutoff')->{none}; |
749
|
4
|
|
|
|
|
30
|
foreach my $name ( keys %{ $val } ) { |
|
4
|
|
|
|
|
36
|
|
750
|
44
|
100
|
|
|
|
84
|
'name' eq $name |
751
|
|
|
|
|
|
|
and next; |
752
|
40
|
50
|
|
|
|
75
|
exists $terms->{$name} |
753
|
|
|
|
|
|
|
or croak "Series '$name' not in this model"; |
754
|
40
|
50
|
|
|
|
139
|
$val->{$name} > $terms->{$name} |
755
|
|
|
|
|
|
|
and croak "Series '$name' has only $terms->{$name} terms"; |
756
|
|
|
|
|
|
|
} |
757
|
4
|
|
|
|
|
21
|
$attr->{model_cutoff_definition}{$name} = $val; |
758
|
|
|
|
|
|
|
} else { |
759
|
2
|
50
|
|
|
|
10
|
$self->__model_definition( 'default_model_cutoff' )->{$name} |
760
|
|
|
|
|
|
|
and croak "You may not delete model cutoff definition '$name'"; |
761
|
2
|
|
|
|
|
19
|
delete $attr->{model_cutoff_definition}{$name}; |
762
|
|
|
|
|
|
|
} |
763
|
6
|
|
|
|
|
33
|
return $self; |
764
|
|
|
|
|
|
|
} else { |
765
|
6060
|
|
|
|
|
18194
|
return $attr->{model_cutoff_definition}{$name}; |
766
|
|
|
|
|
|
|
} |
767
|
|
|
|
|
|
|
} |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
# Static method |
770
|
|
|
|
|
|
|
# Given dynamical time in seconds, return Ecliptic position in Ecliptic |
771
|
|
|
|
|
|
|
# longitude (radians), Ecliptic latitude (radians), Range (AU) and |
772
|
|
|
|
|
|
|
# AU and velocity in AU/day |
773
|
|
|
|
|
|
|
sub __model { |
774
|
6834
|
|
|
6834
|
|
281233
|
my ( $self, $time, %arg ) = @_; |
775
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
DEBUG |
777
|
|
|
|
|
|
|
and printf <<'EOD', |
778
|
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
__model: |
780
|
|
|
|
|
|
|
invocant: %s |
781
|
|
|
|
|
|
|
model_cutoff: %s |
782
|
|
|
|
|
|
|
EOD |
783
|
|
|
|
|
|
|
$self, |
784
|
|
|
|
|
|
|
( $arg{model_cutoff_definition} ? |
785
|
6834
|
|
|
|
|
10476
|
( $arg{model_cutoff_definition}{name} || '' ) : |
786
|
|
|
|
|
|
|
'' ), |
787
|
|
|
|
|
|
|
; |
788
|
|
|
|
|
|
|
|
789
|
6834
|
|
|
|
|
17921
|
my $jm = jcent2000( $time ) / 10; # Meeus 32.1 |
790
|
6834
|
|
|
|
|
38913
|
my @p_vec; |
791
|
|
|
|
|
|
|
my @v_vec; |
792
|
6834
|
|
|
|
|
11287
|
foreach my $coord ( @{ $self->__model_definition( 'model' ) } ) { |
|
6834
|
|
|
|
|
26357
|
|
793
|
20502
|
|
|
|
|
45500
|
my $dT = my $exponent = 0; |
794
|
20502
|
|
|
|
|
29050
|
my $T = 1; |
795
|
20502
|
|
|
|
|
29652
|
my $pos = my $vel = 0; |
796
|
20502
|
|
|
|
|
28462
|
foreach my $series ( @{ $coord } ) { |
|
20502
|
|
|
|
|
36893
|
|
797
|
|
|
|
|
|
|
my $limit = $arg{model_cutoff_definition} ? |
798
|
|
|
|
|
|
|
( $arg{model_cutoff_definition}{$series->{series}} || 0 ) : |
799
|
118569
|
100
|
100
|
|
|
384387
|
@{ $series->{terms} } |
|
560
|
100
|
|
|
|
1578
|
|
800
|
|
|
|
|
|
|
or next; |
801
|
100172
|
|
|
|
|
130223
|
--$limit; |
802
|
100172
|
|
|
|
|
164419
|
foreach my $inx ( 0 .. $limit ) { |
803
|
1828592
|
|
|
|
|
2577590
|
my $term = $series->{terms}[$inx]; |
804
|
1828592
|
|
|
|
|
2715088
|
my $u = $term->[1] + $term->[2] * $jm; |
805
|
1828592
|
|
|
|
|
2553702
|
my $cos_u = cos $u; |
806
|
1828592
|
|
|
|
|
2554375
|
$pos += $term->[0] * $cos_u * $T; |
807
|
1828592
|
|
|
|
|
2469931
|
my $sin_u = sin $u; |
808
|
1828592
|
|
|
|
|
3471996
|
$vel += $dT * $exponent * $term->[0] * $cos_u - |
809
|
|
|
|
|
|
|
$T * $term->[0] * $term->[2] * $sin_u; |
810
|
|
|
|
|
|
|
} |
811
|
100172
|
|
|
|
|
133763
|
$dT = $T; |
812
|
100172
|
|
|
|
|
128971
|
$exponent++; |
813
|
100172
|
|
|
|
|
150252
|
$T *= $jm; |
814
|
|
|
|
|
|
|
} |
815
|
20502
|
|
|
|
|
34981
|
$vel /= DAYS_PER_JULIAN_MILENNIUM; # units/millennium -> units/day |
816
|
20502
|
|
|
|
|
37635
|
push @p_vec, $pos; |
817
|
20502
|
|
|
|
|
37239
|
push @v_vec, $vel; |
818
|
|
|
|
|
|
|
} |
819
|
6834
|
|
|
|
|
3846698
|
$p_vec[0] = mod2pi( $p_vec[0] ); |
820
|
6834
|
|
|
|
|
86901
|
return ( @p_vec, @v_vec ); |
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
sub __mutate_nutation_cutoff { |
824
|
27
|
|
|
27
|
|
99
|
my ( $self, undef, $val ) = @_; |
825
|
27
|
50
|
|
|
|
93
|
defined $val |
826
|
|
|
|
|
|
|
or croak 'Nutation cutoff must be defined'; |
827
|
27
|
50
|
33
|
|
|
210
|
looks_like_number( $val ) |
828
|
|
|
|
|
|
|
and $val >= 0 |
829
|
|
|
|
|
|
|
or croak 'Nutation cutoff must be a non-negative number'; |
830
|
27
|
|
|
|
|
101
|
$self->__get_attr()->{nutation_cutoff} = $val; |
831
|
27
|
|
|
|
|
137
|
return $self; |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
sub obliquity { |
835
|
5270
|
|
|
5270
|
1
|
154609
|
my ( $self, $time ) = @_; |
836
|
|
|
|
|
|
|
|
837
|
5270
|
100
|
|
|
|
14082
|
defined $time |
838
|
|
|
|
|
|
|
or $time = $self->dynamical(); |
839
|
|
|
|
|
|
|
# Obliquity per Meeus 22.3 |
840
|
5270
|
|
|
|
|
27768
|
my $U = jcent2000( $time ) / 100; |
841
|
5270
|
|
|
|
|
29730
|
my $epsilon_0 = 0; |
842
|
5270
|
|
|
|
|
24063
|
$epsilon_0 = $epsilon_0 * $U + $_ for qw{ 2.45 5.79 27.87 7.12 |
843
|
|
|
|
|
|
|
-39.05 -249.67 -51.38 1999.25 -1.55 -4680.93 84381.448 }; |
844
|
5270
|
|
|
|
|
13102
|
$epsilon_0 = deg2rad( $epsilon_0 / 3600 ); |
845
|
5270
|
|
|
|
|
24405
|
my ( undef, $delta_eps ) = $self->nutation( $time ); |
846
|
5270
|
|
|
|
|
10855
|
my $epsilon = $epsilon_0 + $delta_eps; |
847
|
|
|
|
|
|
|
|
848
|
5270
|
|
|
|
|
7749
|
DEBUG |
849
|
|
|
|
|
|
|
and printf <<"EOD", |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
Obliquity: |
852
|
|
|
|
|
|
|
𝛆₀ = %.7f |
853
|
|
|
|
|
|
|
𝛆 = %.7f |
854
|
|
|
|
|
|
|
= %s |
855
|
|
|
|
|
|
|
EOD |
856
|
|
|
|
|
|
|
rad2deg( $epsilon_0 ), rad2deg( $epsilon ), rad2dms( $epsilon ); |
857
|
|
|
|
|
|
|
|
858
|
5270
|
|
|
|
|
10522
|
return $epsilon; |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
sub order { |
862
|
0
|
|
|
0
|
1
|
0
|
my ( $self ) = @_; |
863
|
0
|
|
|
|
|
0
|
return $self->__model_definition( 'order' ); |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
# Calculate the period of the orbit. The orbital velocity in radians per |
867
|
|
|
|
|
|
|
# Julian centutu is just the inverse of the coefficient of the constant |
868
|
|
|
|
|
|
|
# L1 term -- that is, the A value of the one with B and C both zero, |
869
|
|
|
|
|
|
|
# since that computes as A * cos( B + C * tau ) = A * cos( 0 ) = A |
870
|
|
|
|
|
|
|
# |
871
|
|
|
|
|
|
|
# So the tropical year is just TWOPI divided by this. But we want the |
872
|
|
|
|
|
|
|
# Siderial year, so we have to add in the precession. I found no |
873
|
|
|
|
|
|
|
# reference for this, but to a first approximation the additional angle |
874
|
|
|
|
|
|
|
# to travel is the solar year times the rate of precession, and the |
875
|
|
|
|
|
|
|
# siderial year is the solar year plus the additional distance divided |
876
|
|
|
|
|
|
|
# by the orbital velocity. |
877
|
|
|
|
|
|
|
# |
878
|
|
|
|
|
|
|
# But this calculation is done when the model parameters are built, and |
879
|
|
|
|
|
|
|
# period() just returns the resultant value. |
880
|
|
|
|
|
|
|
# |
881
|
|
|
|
|
|
|
# The rate of pecession is the IAU 2003 value, taken from fapa03.c. |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
sub period { |
884
|
24
|
|
|
24
|
1
|
2503
|
my ( $self ) = @_; |
885
|
24
|
|
|
|
|
108
|
return $self->__model_definition( 'sidereal_period' ); |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
# https://in-the-sky.org/article.php?term=synodic_period |
889
|
|
|
|
|
|
|
# Note that I chose NOT to precalculate this because it depends on the |
890
|
|
|
|
|
|
|
# period of the 'sun' attribute, which may change. |
891
|
|
|
|
|
|
|
sub synodic_period { |
892
|
35
|
|
|
35
|
1
|
97
|
my ( $self ) = @_; |
893
|
35
|
|
|
|
|
139
|
return( 1 / abs( 1 / $self->get( 'sun' )->year() - 1 / $self->year() ) ); |
894
|
|
|
|
|
|
|
} |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub year { |
897
|
70
|
|
|
70
|
1
|
243
|
my ( $self ) = @_; |
898
|
70
|
|
|
|
|
309
|
return $self->__model_definition( 'tropical_period' ); |
899
|
|
|
|
|
|
|
} |
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
1; |
902
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
__END__ |