/rust/registry/src/index.crates.io-1949cf8c6b5b557f/sofars-0.6.1/src/astro/aticqn.rs
Line | Count | Source |
1 | | use crate::vm::{anp, c2s, s2c, trxp, zp}; |
2 | | |
3 | | use super::{IauAstrom, IauLdBody, ab, ldn}; |
4 | | |
5 | | /// Quick CIRS −> ICRS, multiple deflections |
6 | | /// |
7 | | /// Quick CIRS to ICRS astrometric place transformation, given the star- |
8 | | /// independent astrometry parameters plus a list of light-deflecting |
9 | | /// bodies. |
10 | | /// |
11 | | /// Use of this function is appropriate when efficiency is important and |
12 | | /// where many star positions are all to be transformed for one date. |
13 | | /// The star-independent astrometry parameters can be obtained by |
14 | | /// calling one of the functions iauApci[13], iauApcg[13], iauApco[13] |
15 | | /// or iauApcs[13]. |
16 | | /// |
17 | | /// If the only light-deflecting body to be taken into account is the |
18 | | /// Sun, the iauAticq function can be used instead. |
19 | | /// |
20 | | /// This function is part of the International Astronomical Union's |
21 | | /// SOFA (Standards of Fundamental Astronomy) software collection. |
22 | | /// |
23 | | /// Status: support function. |
24 | | /// |
25 | | /// Given: |
26 | | /// ``` |
27 | | /// ri,di double CIRS RA,Dec (radians) |
28 | | /// astrom iauASTROM* star-independent astrometry parameters: |
29 | | /// pmt double PM time interval (SSB, Julian years) |
30 | | /// eb double[3] SSB to observer (vector, au) |
31 | | /// eh double[3] Sun to observer (unit vector) |
32 | | /// em double distance from Sun to observer (au) |
33 | | /// v double[3] barycentric observer velocity (vector, c) |
34 | | /// bm1 double sqrt(1-|v|^2): reciprocal of Lorenz factor |
35 | | /// bpn double[3][3] bias-precession-nutation matrix |
36 | | /// along double longitude + s' (radians) |
37 | | /// xpl double polar motion xp wrt local meridian (radians) |
38 | | /// ypl double polar motion yp wrt local meridian (radians) |
39 | | /// sphi double sine of geodetic latitude |
40 | | /// cphi double cosine of geodetic latitude |
41 | | /// diurab double magnitude of diurnal aberration vector |
42 | | /// eral double "local" Earth rotation angle (radians) |
43 | | /// refa double refraction constant A (radians) |
44 | | /// refb double refraction constant B (radians) |
45 | | /// n int number of bodies (Note 3) |
46 | | /// b iauLDBODY[n] data for each of the n bodies (Notes 3,4): |
47 | | /// bm double mass of the body (solar masses, Note 5) |
48 | | /// dl double deflection limiter (Note 6) |
49 | | /// pv [2][3] barycentric PV of the body (au, au/day) |
50 | | /// ``` |
51 | | /// Returned: |
52 | | /// ``` |
53 | | /// rc,dc double ICRS astrometric RA,Dec (radians) |
54 | | /// ``` |
55 | | /// Notes: |
56 | | /// |
57 | | /// 1) Iterative techniques are used for the aberration and light |
58 | | /// deflection corrections so that the functions iauAticqn and |
59 | | /// iauAtciqn are accurate inverses; even at the edge of the Sun's |
60 | | /// disk the discrepancy is only about 1 nanoarcsecond. |
61 | | /// |
62 | | /// 2) If the only light-deflecting body to be taken into account is the |
63 | | /// Sun, the iauAticq function can be used instead. |
64 | | /// |
65 | | /// 3) The struct b contains n entries, one for each body to be |
66 | | /// considered. If n = 0, no gravitational light deflection will be |
67 | | /// applied, not even for the Sun. |
68 | | /// |
69 | | /// 4) The struct b should include an entry for the Sun as well as for |
70 | | /// any planet or other body to be taken into account. The entries |
71 | | /// should be in the order in which the light passes the body. |
72 | | /// |
73 | | /// 5) In the entry in the b struct for body i, the mass parameter |
74 | | /// b[i].bm can, as required, be adjusted in order to allow for such |
75 | | /// effects as quadrupole field. |
76 | | /// |
77 | | /// 6) The deflection limiter parameter b[i].dl is phi^2/2, where phi is |
78 | | /// the angular separation (in radians) between star and body at |
79 | | /// which limiting is applied. As phi shrinks below the chosen |
80 | | /// threshold, the deflection is artificially reduced, reaching zero |
81 | | /// for phi = 0. Example values suitable for a terrestrial |
82 | | /// observer, together with masses, are as follows: |
83 | | /// ``` |
84 | | /// body i b[i].bm b[i].dl |
85 | | /// |
86 | | /// Sun 1.0 6e-6 |
87 | | /// Jupiter 0.00095435 3e-9 |
88 | | /// Saturn 0.00028574 3e-10 |
89 | | /// ``` |
90 | | /// 7) For efficiency, validation of the contents of the b array is |
91 | | /// omitted. The supplied masses must be greater than zero, the |
92 | | /// position and velocity vectors must be right, and the deflection |
93 | | /// limiter greater than zero. |
94 | | /// |
95 | | /// Called: |
96 | | /// ``` |
97 | | /// iauS2c spherical coordinates to unit vector |
98 | | /// iauTrxp product of transpose of r-matrix and p-vector |
99 | | /// iauZp zero p-vector |
100 | | /// iauAb stellar aberration |
101 | | /// iauLdn light deflection by n bodies |
102 | | /// iauC2s p-vector to spherical |
103 | | /// iauAnp normalize angle into range +/- pi |
104 | | /// ``` |
105 | 0 | pub fn aticqn(ri: f64, di: f64, astrom: &mut IauAstrom, n: i32, b: &[IauLdBody]) -> (f64, f64) { |
106 | | let pi: [f64; 3]; |
107 | 0 | let mut ppr = [0.0; 3]; |
108 | 0 | let mut pnat = [0.0; 3]; |
109 | 0 | let mut pco = [0.0; 3]; |
110 | | let mut w; |
111 | 0 | let mut d = [0.0; 3]; |
112 | 0 | let mut before = [0.0; 3]; |
113 | | let mut r2; |
114 | | let mut r; |
115 | | let mut after: [f64; 3]; |
116 | | |
117 | | // CIRS RA,Dec to Cartesian. |
118 | 0 | pi = s2c(ri, di); |
119 | | |
120 | | // Bias-precession-nutation, giving GCRS proper direction. |
121 | 0 | trxp(&astrom.bpn, &pi, &mut ppr); |
122 | | |
123 | | // Aberration, giving GCRS natural direction. |
124 | 0 | for _ in 0..2 { |
125 | 0 | r2 = 0.0; |
126 | 0 | for i in 0..3 { |
127 | 0 | w = ppr[i] - d[i]; |
128 | 0 | before[i] = w; |
129 | 0 | r2 += w * w; |
130 | 0 | } |
131 | 0 | r = r2.sqrt(); |
132 | 0 | for i in 0..3 { |
133 | 0 | before[i] /= r; |
134 | 0 | } |
135 | 0 | after = ab(&before, &astrom.v, astrom.em, astrom.bm1); |
136 | 0 | r2 = 0.0; |
137 | 0 | for i in 0..3 { |
138 | 0 | d[i] = after[i] - before[i]; |
139 | 0 | w = ppr[i] - d[i]; |
140 | 0 | pnat[i] = w; |
141 | 0 | r2 += w * w; |
142 | 0 | } |
143 | 0 | r = r2.sqrt(); |
144 | 0 | for i in 0..3 { |
145 | 0 | pnat[i] /= r; |
146 | 0 | } |
147 | | } |
148 | | |
149 | | // Light deflection, giving BCRS coordinate direction. |
150 | 0 | zp(&mut d); |
151 | 0 | for _ in 0..5 { |
152 | 0 | r2 = 0.0; |
153 | 0 | for i in 0..3 { |
154 | 0 | w = pnat[i] - d[i]; |
155 | 0 | before[i] = w; |
156 | 0 | r2 += w * w; |
157 | 0 | } |
158 | 0 | r = r2.sqrt(); |
159 | 0 | for i in 0..3 { |
160 | 0 | before[i] /= r; |
161 | 0 | } |
162 | 0 | after = ldn(n, b, &astrom.eb, &before); |
163 | 0 | r2 = 0.0; |
164 | 0 | for i in 0..3 { |
165 | 0 | d[i] = after[i] - before[i]; |
166 | 0 | w = pnat[i] - d[i]; |
167 | 0 | pco[i] = w; |
168 | 0 | r2 += w * w; |
169 | 0 | } |
170 | 0 | r = r2.sqrt(); |
171 | 0 | for i in 0..3 { |
172 | 0 | pco[i] /= r; |
173 | 0 | } |
174 | | } |
175 | | |
176 | | // ICRS astrometric RA,Dec. |
177 | 0 | let (w, dc) = c2s(&pco); |
178 | | |
179 | 0 | (anp(w), dc) |
180 | 0 | } |