| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Astro::Coord::ECI::VSOP87D; |
|
2
|
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
25881
|
use 5.008; |
|
|
13
|
|
|
|
|
52
|
|
|
4
|
|
|
|
|
|
|
|
|
5
|
13
|
|
|
13
|
|
173
|
use strict; |
|
|
13
|
|
|
|
|
35
|
|
|
|
13
|
|
|
|
|
393
|
|
|
6
|
13
|
|
|
13
|
|
97
|
use warnings; |
|
|
13
|
|
|
|
|
27
|
|
|
|
13
|
|
|
|
|
398
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
13
|
|
|
13
|
|
8938
|
use utf8; |
|
|
13
|
|
|
|
|
192
|
|
|
|
13
|
|
|
|
|
73
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
13
|
|
|
|
|
1403
|
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
|
|
1268
|
}; |
|
|
13
|
|
|
|
|
20404
|
|
|
16
|
13
|
|
|
13
|
|
104
|
use Exporter qw{ import }; |
|
|
13
|
|
|
|
|
37
|
|
|
|
13
|
|
|
|
|
375
|
|
|
17
|
13
|
|
|
13
|
|
72
|
use Carp; |
|
|
13
|
|
|
|
|
33
|
|
|
|
13
|
|
|
|
|
720
|
|
|
18
|
13
|
|
|
13
|
|
92
|
use POSIX qw{ floor }; |
|
|
13
|
|
|
|
|
24
|
|
|
|
13
|
|
|
|
|
95
|
|
|
19
|
13
|
|
|
13
|
|
10097
|
use Storable qw{ dclone }; |
|
|
13
|
|
|
|
|
44176
|
|
|
|
13
|
|
|
|
|
1036
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
13
|
|
|
13
|
|
161
|
use constant DAYS_PER_JULIAN_MILENNIUM => 365250; |
|
|
13
|
|
|
|
|
30
|
|
|
|
13
|
|
|
|
|
939
|
|
|
22
|
13
|
|
|
13
|
|
81
|
use constant CODE_REF => ref sub {}; |
|
|
13
|
|
|
|
|
42
|
|
|
|
13
|
|
|
|
|
752
|
|
|
23
|
13
|
|
|
13
|
|
131
|
use constant HASH_REF => ref {}; |
|
|
13
|
|
|
|
|
51
|
|
|
|
13
|
|
|
|
|
856
|
|
|
24
|
13
|
|
|
13
|
|
86
|
use constant SUN_CLASS => __PACKAGE__ . '::Sun'; |
|
|
13
|
|
|
|
|
32
|
|
|
|
13
|
|
|
|
|
860
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
BEGIN { |
|
27
|
13
|
100
|
|
13
|
|
6669
|
__PACKAGE__->can( 'DEBUG' ) |
|
28
|
|
|
|
|
|
|
or constant->import( DEBUG => 0 ); |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
our $VERSION = '0.005_01'; |
|
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
|
210538
|
my ( $self ) = @_; |
|
69
|
3011
|
|
|
|
|
8478
|
my $attr = $self->__get_attr(); |
|
70
|
3011
|
|
|
|
|
8661
|
my $time = $self->dynamical(); |
|
71
|
3011
|
|
|
|
|
74972
|
my $cutoff = $self->get( 'model_cutoff' ); |
|
72
|
3011
|
|
|
|
|
8939
|
my $cutoff_def = $self->model_cutoff_definition(); |
|
73
|
3011
|
|
|
|
|
7588
|
my $sun = $self->get( 'sun' ); |
|
74
|
|
|
|
|
|
|
|
|
75
|
3011
|
|
|
|
|
5321
|
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
|
|
|
|
|
8759
|
my $T = jcent2000( $time ); |
|
84
|
|
|
|
|
|
|
|
|
85
|
3011
|
|
|
|
|
20819
|
my ( $Lb, $Bb, $Rb ) = $self->__model( $time, |
|
86
|
|
|
|
|
|
|
model_cutoff_definition => $cutoff_def, |
|
87
|
|
|
|
|
|
|
); |
|
88
|
|
|
|
|
|
|
|
|
89
|
3011
|
|
|
|
|
7395
|
my ( $Le, $Be, $Re ); |
|
90
|
|
|
|
|
|
|
|
|
91
|
3011
|
50
|
|
|
|
15576
|
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
|
|
|
|
|
8928
|
( $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
|
|
|
|
|
6762
|
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
|
|
|
|
|
6496
|
my ( $lambda, $beta, $Delta, $long_sym ); |
|
112
|
3011
|
100
|
|
|
|
7588
|
if ( $Rb ) { # Not the Sun |
|
113
|
|
|
|
|
|
|
|
|
114
|
1719
|
|
|
|
|
2956
|
my $last_tau = 0; |
|
115
|
|
|
|
|
|
|
|
|
116
|
1719
|
|
|
|
|
3048
|
while ( 1 ) { |
|
117
|
3789
|
|
|
|
|
6667
|
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
|
|
|
|
|
8809
|
my $cosBb = cos( $Bb ); |
|
129
|
3789
|
|
|
|
|
6829
|
my $cosBe = cos( $Be ); |
|
130
|
3789
|
|
|
|
|
9264
|
my $x = $Rb * $cosBb * cos( $Lb ) - $Re * $cosBe * cos( $Le ); |
|
131
|
3789
|
|
|
|
|
10074
|
my $y = $Rb * $cosBb * sin( $Lb ) - $Re * $cosBe * sin( $Le ); |
|
132
|
3789
|
|
|
|
|
7382
|
my $z = $Rb * sin( $Bb ) - $Re * sin( $Be ); |
|
133
|
|
|
|
|
|
|
|
|
134
|
3789
|
|
|
|
|
8392
|
$Delta = sqrt( $x * $x + $y * $y + $z * $z ); |
|
135
|
|
|
|
|
|
|
|
|
136
|
13
|
|
|
13
|
|
113
|
use constant TAU_FACTOR => 0.005_775_518_3 * SECSPERDAY; |
|
|
13
|
|
|
|
|
27
|
|
|
|
13
|
|
|
|
|
3558
|
|
|
137
|
3789
|
|
|
|
|
6656
|
my $tau = TAU_FACTOR * $Delta; |
|
138
|
|
|
|
|
|
|
|
|
139
|
3789
|
|
|
|
|
5606
|
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
|
|
|
|
45555
|
if ( ( my $check = sprintf '%.1f', $tau ) ne $last_tau ) { |
|
149
|
2070
|
|
|
|
|
4339
|
$last_tau = $check; |
|
150
|
|
|
|
|
|
|
|
|
151
|
2070
|
|
|
|
|
3276
|
DEBUG |
|
152
|
|
|
|
|
|
|
and printf <<'EOD', julianday( $time - $tau ); |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
new JDE = %.5f |
|
155
|
|
|
|
|
|
|
EOD |
|
156
|
2070
|
|
|
|
|
7847
|
( $Lb, $Bb, $Rb ) = $self->__model( |
|
157
|
|
|
|
|
|
|
$time - $tau, |
|
158
|
|
|
|
|
|
|
model_cutoff_definition => $cutoff_def, |
|
159
|
|
|
|
|
|
|
); |
|
160
|
|
|
|
|
|
|
} else { |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Meeus 33.2 |
|
163
|
1719
|
|
|
|
|
7136
|
$lambda = atan2( $y, $x ); |
|
164
|
1719
|
100
|
|
|
|
6274
|
$lambda < 0 |
|
165
|
|
|
|
|
|
|
and $lambda += TWOPI; |
|
166
|
1719
|
|
|
|
|
4262
|
$beta = atan2( $z, sqrt( $x * $x + $y * $y ) ); |
|
167
|
1719
|
|
|
|
|
3642
|
$long_sym = '𝛌'; |
|
168
|
1719
|
|
|
|
|
4550
|
last; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
DEBUG |
|
173
|
1719
|
|
|
|
|
2729
|
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
|
|
106
|
20.49552 / 3600 ); |
|
|
13
|
|
|
|
|
29
|
|
|
195
|
|
|
|
|
|
|
# Longitude of the Sun |
|
196
|
1719
|
|
|
|
|
5371
|
my $Ls = mod2pi( $Le + PI ); |
|
197
|
|
|
|
|
|
|
# Eccentricity of the Earth's orbit |
|
198
|
1719
|
|
|
|
|
8767
|
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
|
|
|
|
|
5910
|
my $pi = deg2rad( ( 0.000_46 * $T + 1.71946 ) * $T + 102.93735 ); |
|
202
|
|
|
|
|
|
|
|
|
203
|
1719
|
|
|
|
|
10261
|
my $delta_lambda = ( ( $e * cos( $pi - $lambda ) - cos( $Ls - |
|
204
|
|
|
|
|
|
|
$lambda ) ) / cos $beta ) * CONSTANT_OF_ABERRATION; |
|
205
|
1719
|
|
|
|
|
5819
|
my $delta_beta = - sin( $beta ) * ( sin( $Ls - $lambda ) - $e * |
|
206
|
|
|
|
|
|
|
sin( $pi - $lambda ) ) * CONSTANT_OF_ABERRATION; |
|
207
|
1719
|
|
|
|
|
2895
|
$lambda += $delta_lambda; |
|
208
|
1719
|
|
|
|
|
2830
|
$beta += $delta_beta; |
|
209
|
|
|
|
|
|
|
|
|
210
|
1719
|
|
|
|
|
3032
|
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
|
|
|
|
|
4258
|
( $lambda, $beta, $Delta ) = ( mod2pi( $Le + PI ), - $Be, $Re ); |
|
226
|
1292
|
|
|
|
|
7336
|
$long_sym = '☉'; |
|
227
|
|
|
|
|
|
|
|
|
228
|
1292
|
|
|
|
|
2057
|
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
|
|
|
|
|
5092
|
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
|
|
3883
|
use constant DYN_TO_FK5_LINEAR => deg2rad( 1.397 ); |
|
|
13
|
|
|
|
|
30
|
|
|
|
13
|
|
|
|
|
51
|
|
|
|
3011
|
|
|
|
|
5279
|
|
|
260
|
13
|
|
|
13
|
|
920
|
use constant DYN_TO_FK5_QUADRATIC => deg2rad( 0.00031 ); |
|
|
13
|
|
|
|
|
30
|
|
|
|
13
|
|
|
|
|
68
|
|
|
261
|
13
|
|
|
13
|
|
1016
|
use constant DYN_TO_FK5_DELTA_LON => - deg2rad( 0.09033 / 3600 ); |
|
|
13
|
|
|
|
|
28
|
|
|
|
13
|
|
|
|
|
91
|
|
|
262
|
13
|
|
|
13
|
|
990
|
use constant DYN_TO_FK5_FACTOR => deg2rad( 0.03916 / 3600 ); |
|
|
13
|
|
|
|
|
29
|
|
|
|
13
|
|
|
|
|
52
|
|
|
263
|
3011
|
|
|
|
|
7439
|
my $lambda_prime = $lambda - ( DYN_TO_FK5_LINEAR + |
|
264
|
|
|
|
|
|
|
DYN_TO_FK5_QUADRATIC * $T ) * $T; |
|
265
|
3011
|
|
|
|
|
8281
|
my $factor = DYN_TO_FK5_FACTOR * ( cos( $lambda_prime ) - sin( |
|
266
|
|
|
|
|
|
|
$lambda_prime ) ); |
|
267
|
3011
|
|
|
|
|
10238
|
my $delta_lambda = DYN_TO_FK5_DELTA_LON + $factor * tan( $beta ); |
|
268
|
3011
|
|
|
|
|
14039
|
my $delta_beta = $factor; |
|
269
|
|
|
|
|
|
|
|
|
270
|
3011
|
|
|
|
|
4788
|
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
|
|
|
|
|
5106
|
$lambda += $delta_lambda; |
|
281
|
3011
|
|
|
|
|
5075
|
$beta += $delta_beta; |
|
282
|
|
|
|
|
|
|
|
|
283
|
3011
|
|
|
|
|
4632
|
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
|
|
|
|
|
8389
|
$attr->{geometric_longitude} = $lambda; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# Nutation |
|
298
|
3011
|
|
|
|
|
12603
|
my ( $delta_psi, $delta_eps ) = $self->nutation( $time ); |
|
299
|
3011
|
|
|
|
|
16205
|
$lambda += $delta_psi; |
|
300
|
|
|
|
|
|
|
|
|
301
|
3011
|
|
|
|
|
5021
|
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
|
|
|
|
|
10055
|
my $epsilon = $self->obliquity( $time ); |
|
315
|
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# Meeus 25.10 |
|
317
|
|
|
|
|
|
|
|
|
318
|
3011
|
100
|
|
|
|
7964
|
unless ( $Rb ) { # The Sun. |
|
319
|
|
|
|
|
|
|
# Aberration |
|
320
|
13
|
|
|
13
|
|
3897
|
use constant SOLAR_ABERRATION_FACTOR => - deg2rad( 20.4898 / 3600 ); |
|
|
13
|
|
|
|
|
30
|
|
|
|
13
|
|
|
|
|
69
|
|
|
321
|
1292
|
|
|
|
|
2697
|
my $delta_lambda = SOLAR_ABERRATION_FACTOR / $Delta; |
|
322
|
1292
|
|
|
|
|
2206
|
$lambda += $delta_lambda; |
|
323
|
|
|
|
|
|
|
|
|
324
|
1292
|
|
|
|
|
2179
|
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
|
|
|
|
|
4829
|
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
|
|
|
|
|
6342
|
my $sin_eps = sin $epsilon; |
|
364
|
3011
|
|
|
|
|
5344
|
my $cos_eps = cos $epsilon; |
|
365
|
3011
|
|
|
|
|
5641
|
my $sin_lam = sin $lambda; |
|
366
|
3011
|
|
|
|
|
4956
|
my $sin_bet = sin $beta; |
|
367
|
3011
|
|
|
|
|
4940
|
my $cos_bet = cos $beta; |
|
368
|
3011
|
|
|
|
|
14873
|
my $alpha = mod2pi( atan2( |
|
369
|
|
|
|
|
|
|
$sin_lam * $cos_eps - $sin_bet / $cos_bet * $sin_eps, |
|
370
|
|
|
|
|
|
|
cos $lambda ) ); # Meeus 13.3 |
|
371
|
3011
|
|
|
|
|
19886
|
my $delta = asin( $sin_bet * $cos_eps + $cos_bet * $sin_eps * |
|
372
|
|
|
|
|
|
|
$sin_lam ); # Meeus 13.4 |
|
373
|
|
|
|
|
|
|
|
|
374
|
3011
|
|
|
|
|
13834
|
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
|
|
|
|
|
16707
|
$self->equatorial( $alpha, $delta, $Delta * AU ); |
|
387
|
3011
|
|
|
|
|
568822
|
$self->equinox_dynamical( $time ); |
|
388
|
|
|
|
|
|
|
|
|
389
|
3011
|
|
|
|
|
20807
|
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
|
|
|
|
|
9503
|
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
|
|
689
|
my ( $self, $time ) = @_; |
|
413
|
246
|
100
|
|
|
|
782
|
defined $time |
|
414
|
|
|
|
|
|
|
or $time = $self->universal(); |
|
415
|
246
|
|
66
|
|
|
835
|
$earth ||= Astro::Coord::ECI->new()->eci( 0, 0, 0 ); |
|
416
|
246
|
|
|
|
|
1000
|
$self->universal( $time ); |
|
417
|
246
|
|
|
|
|
3802
|
my $sun = $self->get( 'sun' )->universal( $time ); |
|
418
|
246
|
|
|
|
|
3381
|
$earth->universal( $time ); |
|
419
|
246
|
|
|
|
|
9656
|
my $lon = $self->__longitude_from_sun(); |
|
420
|
246
|
|
|
|
|
1744
|
my $angle = $earth->angle( $self, $sun ); |
|
421
|
246
|
100
|
|
|
|
91676
|
return $lon < 0 ? -$angle : $angle; |
|
422
|
|
|
|
|
|
|
} |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
sub geometric_longitude { |
|
426
|
1
|
|
|
1
|
1
|
19
|
my ( $self ) = @_; |
|
427
|
1
|
|
|
|
|
2
|
my $attr = $self->__get_attr(); |
|
428
|
|
|
|
|
|
|
defined $attr->{geometric_longitude} |
|
429
|
1
|
50
|
|
|
|
11
|
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
|
|
3023
|
my ( $self, $time, $offset ) = @_; |
|
435
|
1248
|
|
100
|
|
|
4683
|
$offset ||= 0; |
|
436
|
|
|
|
|
|
|
|
|
437
|
1248
|
100
|
|
|
|
2792
|
if ( defined $time ) { |
|
438
|
1002
|
|
|
|
|
3193
|
$self->universal( $time ); |
|
439
|
|
|
|
|
|
|
} else { |
|
440
|
246
|
|
|
|
|
681
|
$time = $self->universal(); |
|
441
|
|
|
|
|
|
|
} |
|
442
|
|
|
|
|
|
|
|
|
443
|
1248
|
|
|
|
|
18385
|
my $sun = $self->get( 'sun' )->universal( $time ); |
|
444
|
|
|
|
|
|
|
|
|
445
|
1248
|
|
|
|
|
16972
|
my ( undef, $lon_b ) = $self->ecliptic(); |
|
446
|
1248
|
|
|
|
|
89440
|
my ( undef, $lon_s ) = $sun->ecliptic(); |
|
447
|
|
|
|
|
|
|
|
|
448
|
1248
|
|
|
|
|
70878
|
return mod2pi( $lon_b - $lon_s - $offset + PI ) - PI; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
0
|
|
|
|
|
0
|
BEGIN { |
|
452
|
13
|
|
|
13
|
|
25735
|
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
|
|
|
|
|
21514
|
my @memoize_result; |
|
605
|
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
sub nutation { |
|
607
|
8281
|
|
|
8281
|
1
|
18250
|
my ( $self, $time, $cutoff ) = @_; |
|
608
|
|
|
|
|
|
|
|
|
609
|
8281
|
50
|
|
|
|
19299
|
defined $time |
|
610
|
|
|
|
|
|
|
or $time = $self->dynamical(); |
|
611
|
|
|
|
|
|
|
|
|
612
|
8281
|
|
50
|
|
|
34804
|
$cutoff ||= 0; # milli arc seconds. Meeus is 3 |
|
613
|
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
{ |
|
615
|
8281
|
100
|
|
|
|
12421
|
( my $memo = "$time $cutoff" ) eq $memoize_args |
|
|
8281
|
|
|
|
|
73188
|
|
|
616
|
|
|
|
|
|
|
and return @memoize_result; |
|
617
|
1943
|
|
|
|
|
4299
|
$memoize_args = $memo; |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
|
|
620
|
1943
|
|
|
|
|
6267
|
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
|
|
|
|
|
14595
|
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
|
|
|
|
|
4870
|
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
|
|
|
|
|
4539
|
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
|
|
|
|
|
4649
|
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
|
|
|
|
|
4435
|
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
|
|
|
|
|
5770
|
my @arg = map { deg2rad( $_ ) } ( $M_prime, $M, $F, $D, $Omega ); |
|
|
9715
|
|
|
|
|
33940
|
|
|
647
|
|
|
|
|
|
|
|
|
648
|
1943
|
|
|
|
|
12726
|
my ( $delta_psi, $delta_eps ) = ( 0, 0 ); |
|
649
|
1943
|
|
|
|
|
5382
|
foreach my $row ( @model ) { |
|
650
|
205958
|
|
|
|
|
407922
|
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
|
|
|
566146
|
if ( $row->[5] && $cutoff <= abs $row->[5] ) { |
|
654
|
205958
|
|
|
|
|
367169
|
$delta_psi += ( $row->[6] * $T + $row->[5] ) * sin $a; |
|
655
|
|
|
|
|
|
|
} |
|
656
|
205958
|
100
|
66
|
|
|
514199
|
if ( $row->[7] && $cutoff <= abs $row->[7] ) { |
|
657
|
124352
|
|
|
|
|
245241
|
$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
|
|
|
|
|
5020
|
map { deg2rad( $_ / 3600_0000 ) } $delta_psi, $delta_eps ); |
|
|
3886
|
|
|
|
|
17364
|
|
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
} |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub __get_attr { |
|
671
|
15180
|
|
|
15180
|
|
26228
|
my ( $self ) = @_; |
|
672
|
15180
|
50
|
|
|
|
35672
|
my $ref = ref $self |
|
673
|
|
|
|
|
|
|
or confess 'Can not call as static method'; |
|
674
|
15180
|
|
100
|
|
|
47803
|
return $self->{$ref} ||= { |
|
675
|
|
|
|
|
|
|
model_cutoff_definition => dclone( $self->__model_definition( |
|
676
|
|
|
|
|
|
|
'default_model_cutoff' ) ), |
|
677
|
|
|
|
|
|
|
}; |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub __default { |
|
681
|
27
|
|
|
27
|
|
78
|
my ( $class, $arg ) = @_; |
|
682
|
|
|
|
|
|
|
|
|
683
|
27
|
|
|
|
|
120
|
my $name = $class->__model_definition( 'body' ); |
|
684
|
|
|
|
|
|
|
defined $arg->{id} |
|
685
|
27
|
50
|
|
|
|
221
|
or $arg->{id} = $name; |
|
686
|
|
|
|
|
|
|
defined $arg->{name} |
|
687
|
27
|
50
|
|
|
|
109
|
or $arg->{name} = $name; |
|
688
|
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
defined $arg->{diameter} |
|
690
|
27
|
50
|
|
|
|
224
|
or $arg->{diameter} = $class->__model_definition( 'diameter' ); |
|
691
|
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
defined $arg->{model_cutoff} |
|
693
|
27
|
100
|
|
|
|
175
|
or $arg->{model_cutoff} = 'Meeus'; |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
defined $arg->{nutation_cutoff} |
|
696
|
27
|
50
|
|
|
|
97
|
or $arg->{nutation_cutoff} = 3; |
|
697
|
|
|
|
|
|
|
|
|
698
|
27
|
|
|
|
|
131
|
return; |
|
699
|
|
|
|
|
|
|
} |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
sub __mutate_model_cutoff { |
|
702
|
28
|
|
|
28
|
|
78
|
my ( $self, $name, $val ) = @_; |
|
703
|
28
|
50
|
|
|
|
84
|
defined $val |
|
704
|
|
|
|
|
|
|
or croak "model cutoff must be defined"; |
|
705
|
28
|
50
|
|
|
|
138
|
$self->model_cutoff_definition( $val ) |
|
706
|
|
|
|
|
|
|
or croak "model cutoff '$val' is unknown"; |
|
707
|
28
|
|
|
|
|
81
|
$self->__get_attr()->{$name} = $val; |
|
708
|
28
|
|
|
|
|
104
|
return $self; |
|
709
|
|
|
|
|
|
|
} |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
sub model_cutoff_definition { |
|
712
|
6066
|
|
|
6066
|
1
|
14405
|
my ( $self, $name, @arg ) = @_; |
|
713
|
6066
|
100
|
|
|
|
17903
|
defined $name |
|
714
|
|
|
|
|
|
|
or $name = $self->get( 'model_cutoff' ); |
|
715
|
6066
|
|
|
|
|
14454
|
my $attr = $self->__get_attr(); |
|
716
|
6066
|
100
|
|
|
|
14880
|
if ( @arg ) { |
|
717
|
6
|
100
|
|
|
|
15
|
if ( defined( my $val = $arg[0] ) ) { |
|
718
|
4
|
100
|
|
|
|
13
|
unless ( ref $val ) { |
|
719
|
2
|
50
|
33
|
|
|
33
|
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
|
|
|
|
|
5
|
foreach my $series ( @model ) { |
|
727
|
34
|
|
|
|
|
47
|
my $count = 0; |
|
728
|
34
|
|
|
|
|
46
|
foreach my $term ( @{ $series->{terms} } ) { |
|
|
34
|
|
|
|
|
56
|
|
|
729
|
308
|
100
|
|
|
|
516
|
last if $term->[0] < $num; |
|
730
|
274
|
|
|
|
|
368
|
$count++; |
|
731
|
|
|
|
|
|
|
} |
|
732
|
|
|
|
|
|
|
$count |
|
733
|
34
|
100
|
|
|
|
72
|
and $cutoff{$series->{series}} = $count; |
|
734
|
|
|
|
|
|
|
} |
|
735
|
2
|
|
|
|
|
6
|
return \%cutoff; |
|
736
|
2
|
|
|
|
|
12
|
}; |
|
737
|
|
|
|
|
|
|
} |
|
738
|
4
|
100
|
|
|
|
16
|
if ( CODE_REF eq ref $val ) { |
|
739
|
|
|
|
|
|
|
$val = $val->( |
|
740
|
9
|
|
|
|
|
17
|
map { @{ $_ } } @{ |
|
|
9
|
|
|
|
|
27
|
|
|
741
|
3
|
|
|
|
|
5
|
$self->__model_definition( 'model' ) } |
|
|
3
|
|
|
|
|
10
|
|
|
742
|
|
|
|
|
|
|
); |
|
743
|
3
|
|
|
|
|
1009
|
$val->{name} = $name; |
|
744
|
|
|
|
|
|
|
} |
|
745
|
4
|
50
|
|
|
|
15
|
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
|
|
|
|
|
13
|
'default_model_cutoff')->{none}; |
|
749
|
4
|
|
|
|
|
20
|
foreach my $name ( keys %{ $val } ) { |
|
|
4
|
|
|
|
|
21
|
|
|
750
|
44
|
100
|
|
|
|
80
|
'name' eq $name |
|
751
|
|
|
|
|
|
|
and next; |
|
752
|
40
|
50
|
|
|
|
85
|
exists $terms->{$name} |
|
753
|
|
|
|
|
|
|
or croak "Series '$name' not in this model"; |
|
754
|
40
|
50
|
|
|
|
127
|
$val->{$name} > $terms->{$name} |
|
755
|
|
|
|
|
|
|
and croak "Series '$name' has only $terms->{$name} terms"; |
|
756
|
|
|
|
|
|
|
} |
|
757
|
4
|
|
|
|
|
19
|
$attr->{model_cutoff_definition}{$name} = $val; |
|
758
|
|
|
|
|
|
|
} else { |
|
759
|
2
|
50
|
|
|
|
7
|
$self->__model_definition( 'default_model_cutoff' )->{$name} |
|
760
|
|
|
|
|
|
|
and croak "You may not delete model cutoff definition '$name'"; |
|
761
|
2
|
|
|
|
|
16
|
delete $attr->{model_cutoff_definition}{$name}; |
|
762
|
|
|
|
|
|
|
} |
|
763
|
6
|
|
|
|
|
23
|
return $self; |
|
764
|
|
|
|
|
|
|
} else { |
|
765
|
6060
|
|
|
|
|
20294
|
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
|
|
275299
|
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
|
|
|
|
|
11415
|
( $arg{model_cutoff_definition}{name} || '' ) : |
|
786
|
|
|
|
|
|
|
'' ), |
|
787
|
|
|
|
|
|
|
; |
|
788
|
|
|
|
|
|
|
|
|
789
|
6834
|
|
|
|
|
18902
|
my $jm = jcent2000( $time ) / 10; # Meeus 32.1 |
|
790
|
6834
|
|
|
|
|
41906
|
my @p_vec; |
|
791
|
|
|
|
|
|
|
my @v_vec; |
|
792
|
6834
|
|
|
|
|
11191
|
foreach my $coord ( @{ $self->__model_definition( 'model' ) } ) { |
|
|
6834
|
|
|
|
|
27016
|
|
|
793
|
20502
|
|
|
|
|
50022
|
my $dT = my $exponent = 0; |
|
794
|
20502
|
|
|
|
|
32030
|
my $T = 1; |
|
795
|
20502
|
|
|
|
|
31504
|
my $pos = my $vel = 0; |
|
796
|
20502
|
|
|
|
|
30821
|
foreach my $series ( @{ $coord } ) { |
|
|
20502
|
|
|
|
|
40502
|
|
|
797
|
|
|
|
|
|
|
my $limit = $arg{model_cutoff_definition} ? |
|
798
|
|
|
|
|
|
|
( $arg{model_cutoff_definition}{$series->{series}} || 0 ) : |
|
799
|
118569
|
100
|
100
|
|
|
407707
|
@{ $series->{terms} } |
|
|
560
|
100
|
|
|
|
1468
|
|
|
800
|
|
|
|
|
|
|
or next; |
|
801
|
100172
|
|
|
|
|
139264
|
--$limit; |
|
802
|
100172
|
|
|
|
|
175575
|
foreach my $inx ( 0 .. $limit ) { |
|
803
|
1828592
|
|
|
|
|
2760278
|
my $term = $series->{terms}[$inx]; |
|
804
|
1828592
|
|
|
|
|
2924082
|
my $u = $term->[1] + $term->[2] * $jm; |
|
805
|
1828592
|
|
|
|
|
2714696
|
my $cos_u = cos $u; |
|
806
|
1828592
|
|
|
|
|
2734642
|
$pos += $term->[0] * $cos_u * $T; |
|
807
|
1828592
|
|
|
|
|
2636552
|
my $sin_u = sin $u; |
|
808
|
1828592
|
|
|
|
|
3697789
|
$vel += $dT * $exponent * $term->[0] * $cos_u - |
|
809
|
|
|
|
|
|
|
$T * $term->[0] * $term->[2] * $sin_u; |
|
810
|
|
|
|
|
|
|
} |
|
811
|
100172
|
|
|
|
|
144823
|
$dT = $T; |
|
812
|
100172
|
|
|
|
|
139572
|
$exponent++; |
|
813
|
100172
|
|
|
|
|
157717
|
$T *= $jm; |
|
814
|
|
|
|
|
|
|
} |
|
815
|
20502
|
|
|
|
|
37811
|
$vel /= DAYS_PER_JULIAN_MILENNIUM; # units/millennium -> units/day |
|
816
|
20502
|
|
|
|
|
41145
|
push @p_vec, $pos; |
|
817
|
20502
|
|
|
|
|
39159
|
push @v_vec, $vel; |
|
818
|
|
|
|
|
|
|
} |
|
819
|
6834
|
|
|
|
|
4278760
|
$p_vec[0] = mod2pi( $p_vec[0] ); |
|
820
|
6834
|
|
|
|
|
94190
|
return ( @p_vec, @v_vec ); |
|
821
|
|
|
|
|
|
|
} |
|
822
|
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
sub __mutate_nutation_cutoff { |
|
824
|
27
|
|
|
27
|
|
79
|
my ( $self, undef, $val ) = @_; |
|
825
|
27
|
50
|
|
|
|
85
|
defined $val |
|
826
|
|
|
|
|
|
|
or croak 'Nutation cutoff must be defined'; |
|
827
|
27
|
50
|
33
|
|
|
201
|
looks_like_number( $val ) |
|
828
|
|
|
|
|
|
|
and $val >= 0 |
|
829
|
|
|
|
|
|
|
or croak 'Nutation cutoff must be a non-negative number'; |
|
830
|
27
|
|
|
|
|
104
|
$self->__get_attr()->{nutation_cutoff} = $val; |
|
831
|
27
|
|
|
|
|
145
|
return $self; |
|
832
|
|
|
|
|
|
|
} |
|
833
|
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
sub obliquity { |
|
835
|
5270
|
|
|
5270
|
1
|
164876
|
my ( $self, $time ) = @_; |
|
836
|
|
|
|
|
|
|
|
|
837
|
5270
|
100
|
|
|
|
15963
|
defined $time |
|
838
|
|
|
|
|
|
|
or $time = $self->dynamical(); |
|
839
|
|
|
|
|
|
|
# Obliquity per Meeus 22.3 |
|
840
|
5270
|
|
|
|
|
28569
|
my $U = jcent2000( $time ) / 100; |
|
841
|
5270
|
|
|
|
|
31191
|
my $epsilon_0 = 0; |
|
842
|
5270
|
|
|
|
|
25847
|
$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
|
|
|
|
|
13881
|
$epsilon_0 = deg2rad( $epsilon_0 / 3600 ); |
|
845
|
5270
|
|
|
|
|
25172
|
my ( undef, $delta_eps ) = $self->nutation( $time ); |
|
846
|
5270
|
|
|
|
|
12016
|
my $epsilon = $epsilon_0 + $delta_eps; |
|
847
|
|
|
|
|
|
|
|
|
848
|
5270
|
|
|
|
|
8261
|
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
|
|
|
|
|
11449
|
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
|
2684
|
my ( $self ) = @_; |
|
885
|
24
|
|
|
|
|
133
|
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
|
93
|
my ( $self ) = @_; |
|
893
|
35
|
|
|
|
|
131
|
return( 1 / abs( 1 / $self->get( 'sun' )->year() - 1 / $self->year() ) ); |
|
894
|
|
|
|
|
|
|
} |
|
895
|
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub year { |
|
897
|
70
|
|
|
70
|
1
|
327
|
my ( $self ) = @_; |
|
898
|
70
|
|
|
|
|
304
|
return $self->__model_definition( 'tropical_period' ); |
|
899
|
|
|
|
|
|
|
} |
|
900
|
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
1; |
|
902
|
|
|
|
|
|
|
|
|
903
|
|
|
|
|
|
|
__END__ |