gistools/space/propagation/
dsinit.rs

1use crate::space::util::constants::{X2_3, XKE};
2use core::f64::consts::{PI, TAU};
3use libm::pow;
4
5/// Options for DsInit
6#[derive(Debug, Default, Clone, Copy, PartialEq)]
7pub struct DsInitOptions {
8    /// cosim
9    pub cosim: f64,
10    /// argpo
11    pub argpo: f64,
12    /// s1
13    pub s1: f64,
14    /// s2
15    pub s2: f64,
16    /// s3
17    pub s3: f64,
18    /// s4
19    pub s4: f64,
20    /// s5
21    pub s5: f64,
22    /// sinim
23    pub sinim: f64,
24    /// ss1
25    pub ss1: f64,
26    /// ss2
27    pub ss2: f64,
28    /// ss3
29    pub ss3: f64,
30    /// ss4
31    pub ss4: f64,
32    /// ss5
33    pub ss5: f64,
34    /// sz1
35    pub sz1: f64,
36    /// sz3
37    pub sz3: f64,
38    /// sz11
39    pub sz11: f64,
40    /// sz13
41    pub sz13: f64,
42    /// sz21
43    pub sz21: f64,
44    /// sz23
45    pub sz23: f64,
46    /// sz31
47    pub sz31: f64,
48    /// sz33
49    pub sz33: f64,
50    /// tc
51    pub tc: f64,
52    /// gsto
53    pub gsto: f64,
54    /// mo
55    pub mo: f64,
56    /// mdot
57    pub mdot: f64,
58    /// no
59    pub no: f64,
60    /// nodeo
61    pub nodeo: f64,
62    /// nodedot
63    pub nodedot: f64,
64    /// xpidot
65    pub xpidot: f64,
66    /// z1
67    pub z1: f64,
68    /// z3
69    pub z3: f64,
70    /// z11
71    pub z11: f64,
72    /// z13
73    pub z13: f64,
74    /// z21
75    pub z21: f64,
76    /// z23
77    pub z23: f64,
78    /// z31
79    pub z31: f64,
80    /// z33
81    pub z33: f64,
82    /// ecco
83    pub ecco: f64,
84    /// eccsq
85    pub eccsq: f64,
86    /// emsq
87    pub emsq: f64,
88    /// em
89    pub em: f64,
90    /// argpm
91    pub argpm: f64,
92    /// inclm
93    pub inclm: f64,
94    /// mm
95    pub mm: f64,
96    /// nm
97    pub nm: f64,
98    /// nodem
99    pub nodem: f64,
100    /// irez
101    pub irez: f64,
102    /// atime
103    pub atime: f64,
104    /// d2201
105    pub d2201: f64,
106    /// d2211
107    pub d2211: f64,
108    /// d3210
109    pub d3210: f64,
110    /// d3222
111    pub d3222: f64,
112    /// d4410
113    pub d4410: f64,
114    /// d4422
115    pub d4422: f64,
116    /// d5220
117    pub d5220: f64,
118    /// d5232
119    pub d5232: f64,
120    /// d5421
121    pub d5421: f64,
122    /// d5433
123    pub d5433: f64,
124    /// dedt
125    pub dedt: f64,
126    /// didt
127    pub didt: f64,
128    /// dmdt
129    pub dmdt: f64,
130    /// dnodt
131    pub dnodt: f64,
132    /// domdt
133    pub domdt: f64,
134    /// del1
135    pub del1: f64,
136    /// del2
137    pub del2: f64,
138    /// del3
139    pub del3: f64,
140    /// xfact
141    pub xfact: f64,
142    /// xlamo
143    pub xlamo: f64,
144    /// xli
145    pub xli: f64,
146    /// xni
147    pub xni: f64,
148}
149
150/// Output from DsInit
151#[derive(Debug, Default, Clone, Copy, PartialEq)]
152pub struct DsInitOutput {
153    /// em
154    pub em: f64,
155    /// argpm
156    pub argpm: f64,
157    /// inclm
158    pub inclm: f64,
159    /// mm
160    pub mm: f64,
161    /// nm
162    pub nm: f64,
163    /// nodem
164    pub nodem: f64,
165
166    /// irez
167    pub irez: f64,
168    /// atime
169    pub atime: f64,
170
171    /// d2201
172    pub d2201: f64,
173    /// d2211
174    pub d2211: f64,
175    /// d3210
176    pub d3210: f64,
177    /// d3222
178    pub d3222: f64,
179    /// d4410
180    pub d4410: f64,
181
182    /// d4422
183    pub d4422: f64,
184    /// d5220
185    pub d5220: f64,
186    /// d5232
187    pub d5232: f64,
188    /// d5421
189    pub d5421: f64,
190    /// d5433
191    pub d5433: f64,
192
193    /// dedt
194    pub dedt: f64,
195    /// didt
196    pub didt: f64,
197    /// dmdt
198    pub dmdt: f64,
199    /// dndt
200    pub dndt: f64,
201    /// dnodt
202    pub dnodt: f64,
203    /// domdt
204    pub domdt: f64,
205
206    /// del1
207    pub del1: f64,
208    /// del2
209    pub del2: f64,
210    /// del3
211    pub del3: f64,
212
213    /// xfact
214    pub xfact: f64,
215    /// xlamo
216    pub xlamo: f64,
217    /// xli
218    pub xli: f64,
219    /// xni
220    pub xni: f64,
221}
222
223/// procedure dsinit
224///
225///  this procedure provides deep space contributions to mean motion dot due
226///    to geopotential resonance with half day and one day orbits.
227///
228///  author         david vallado                  719-573-2600   28 jun 2005
229///
230///  references
231///    hoots, roehrich, norad spacetrack report #3 1980
232///    hoots, norad spacetrack report #6 1986
233///    hoots, schumacher and glover 2004
234///    vallado, crawford, hujsak, kelso  2006
235///
236/// ## Parameters
237/// - `options`: the options
238/// - `tsince`: the time since epoch
239///
240/// ## Returns
241/// The computed dpsace initial values
242pub fn dsinit(options: DsInitOptions, tsince: f64) -> DsInitOutput {
243    let DsInitOptions {
244        cosim,
245        argpo,
246        s1,
247        s2,
248        s3,
249        s4,
250        s5,
251        sinim,
252        ss1,
253        ss2,
254        ss3,
255        ss4,
256        ss5,
257        sz1,
258        sz3,
259        sz11,
260        sz13,
261        sz21,
262        sz23,
263        sz31,
264        sz33,
265        tc,
266        gsto,
267        mo,
268        mdot,
269        no,
270        nodeo,
271        nodedot,
272        xpidot,
273        z1,
274        z3,
275        z11,
276        z13,
277        z21,
278        z23,
279        z31,
280        z33,
281        ecco,
282        eccsq,
283        mut emsq,
284        mut em,
285        mut argpm,
286        mut inclm,
287        mut mm,
288        mut nm,
289        mut nodem,
290        // irez,
291        mut atime,
292        mut d2201,
293        mut d2211,
294        mut d3210,
295        mut d3222,
296        mut d4410,
297        mut d4422,
298        mut d5220,
299        mut d5232,
300        mut d5421,
301        mut d5433,
302        // mut dedt,
303        // mut didt,
304        // mut dmdt,
305        // mut dnodt,
306        // mut domdt,
307        mut del1,
308        mut del2,
309        mut del3,
310        mut xfact,
311        mut xlamo,
312        mut xli,
313        mut xni,
314        ..
315    } = options;
316
317    let mut f220: f64;
318    let f221: f64;
319    let f311: f64;
320    let f321: f64;
321    let f322: f64;
322    let mut f330: f64;
323    let f441: f64;
324    let f442: f64;
325    let f522: f64;
326    let f523: f64;
327    let f542: f64;
328    let f543: f64;
329    let g200: f64;
330    let g201: f64;
331    let g211: f64;
332    let g300: f64;
333    let mut g310: f64;
334    let g322: f64;
335    let g410: f64;
336    let g422: f64;
337    let g520: f64;
338    let g521: f64;
339    let g532: f64;
340    let g533: f64;
341    let sini2: f64;
342    let mut temp: f64;
343    let mut temp1: f64;
344    let xno2: f64;
345    let ainv2: f64;
346    let aonv: f64;
347    let cosisq: f64;
348    let eoc: f64;
349
350    let q22 = 1.7891679e-6;
351    let q31 = 2.1460748e-6;
352    let q33 = 2.2123015e-7;
353    let root22 = 1.7891679e-6;
354    let root44 = 7.3636953e-9;
355    let root54 = 2.1765803e-9;
356
357    // eslint-disable-next-line no-loss-of-precision
358    let rptim = 4.375_269_088_011_3e-3; // equates to 7.29211514668855e-5 rad/sec
359    let root32 = 3.7393792e-7;
360    let root52 = 1.1428639e-7;
361    let znl = 1.5835218e-4;
362    let zns = 1.19459e-5;
363
364    // -------------------- deep space initialization ------------
365    let mut irez = 0;
366    if nm < 0.0052359877 && nm > 0.0034906585 {
367        irez = 1;
368    }
369    if (8.26e-3..=9.24e-3).contains(&nm) {
370        irez = 2;
371    }
372
373    // ------------------------ do solar terms -------------------
374    let ses = ss1 * zns * ss5;
375    let sis = ss2 * zns * (sz11 + sz13);
376    let sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq);
377    let sghs = ss4 * zns * (sz31 + sz33 - 6.0);
378    let mut shs = -zns * ss2 * (sz21 + sz23);
379
380    // sgp4fix for 180 deg incl
381    if !(5.2359877e-2..=PI - 5.2359877e-2).contains(&inclm) {
382        shs = 0.0;
383    }
384    if sinim != 0.0 {
385        shs /= sinim;
386    }
387    let sgs = sghs - cosim * shs;
388
389    // ------------------------- do lunar terms ------------------
390    let dedt = ses + s1 * znl * s5;
391    let didt = sis + s2 * znl * (z11 + z13);
392    let dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq);
393    let sghl = s4 * znl * (z31 + z33 - 6.0);
394    let mut shll = -znl * s2 * (z21 + z23);
395
396    // sgp4fix for 180 deg incl
397    if !(5.2359877e-2..=PI - 5.2359877e-2).contains(&inclm) {
398        shll = 0.0;
399    }
400    let mut domdt = sgs + sghl;
401    let mut dnodt = shs;
402    if sinim != 0.0 {
403        domdt -= (cosim / sinim) * shll;
404        dnodt += shll / sinim;
405    }
406
407    // ----------- calculate deep space resonance effects --------
408    let dndt = 0.0;
409    let theta = (gsto + tc * rptim) % TAU;
410    em += dedt * tsince;
411    inclm += didt * tsince;
412    argpm += domdt * tsince;
413    nodem += dnodt * tsince;
414    mm += dmdt * tsince;
415
416    // sgp4fix for negative inclinations
417    // the following if statement should be commented out
418    // if (inclm < 0.0)
419    // {
420    //   inclm  = -inclm;
421    //   argpm  = argpm - pi;
422    //   nodem = nodem + pi;
423    // }
424
425    // -------------- initialize the resonance terms -------------
426    if irez != 0 {
427        // aonv = (nm / xke) ** x2o3;
428        aonv = pow(nm / XKE, X2_3);
429
430        // ---------- geopotential resonance for 12 hour orbits ------
431        if irez == 2 {
432            cosisq = cosim * cosim;
433            let emo = em;
434            em = ecco;
435            let emsqo = emsq;
436            emsq = eccsq;
437            eoc = em * emsq;
438            g201 = -0.306 - (em - 0.64) * 0.44;
439
440            if em <= 0.65 {
441                g211 = 3.616 - 13.247 * em + 16.29 * emsq;
442                g310 = -19.302 + 117.39 * em - 228.419 * emsq + 156.591 * eoc;
443                g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc;
444                g410 = -41.122 + 242.694 * em - 471.094 * emsq + 313.953 * eoc;
445                g422 = -146.407 + 841.88 * em - 1629.014 * emsq + 1083.435 * eoc;
446                g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.276 * eoc;
447            } else {
448                g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc;
449                g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc;
450                g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc;
451                g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc;
452                g422 = -3581.69 + 16178.11 * em - 24462.77 * emsq + 12422.52 * eoc;
453                if em > 0.715 {
454                    g520 = -5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc;
455                } else {
456                    g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq;
457                }
458            }
459            if em < 0.7 {
460                g533 = -919.2277 + 4988.61 * em - 9064.77 * emsq + 5542.21 * eoc;
461                g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc;
462                g532 = -853.666 + 4690.25 * em - 8624.77 * emsq + 5341.4 * eoc;
463            } else {
464                g533 = -37995.78 + 161616.52 * em - 229838.2 * emsq + 109377.94 * eoc;
465                g521 = -51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc;
466                g532 = -40023.88 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc;
467            }
468            sini2 = sinim * sinim;
469            f220 = 0.75 * (1.0 + 2.0 * cosim + cosisq);
470            f221 = 1.5 * sini2;
471            f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq);
472            f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq);
473            f441 = 35.0 * sini2 * f220;
474            f442 = 39.375 * sini2 * sini2;
475
476            f522 = 9.84375
477                * sinim
478                * (sini2 * (1.0 - 2.0 * cosim - 5.0 * cosisq)
479                    + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq));
480            f523 = sinim
481                * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + 10.0 * cosisq)
482                    + 6.56250012 * (1.0 + 2.0 * cosim - 3.0 * cosisq));
483            f542 = 29.53125
484                * sinim
485                * (2.0 - 8.0 * cosim + cosisq * (-12.0 + 8.0 * cosim + 10.0 * cosisq));
486            f543 = 29.53125
487                * sinim
488                * (-2.0 - 8.0 * cosim + cosisq * (12.0 + 8.0 * cosim - 10.0 * cosisq));
489
490            xno2 = nm * nm;
491            ainv2 = aonv * aonv;
492            temp1 = 3.0 * xno2 * ainv2;
493            temp = temp1 * root22;
494            d2201 = temp * f220 * g201;
495            d2211 = temp * f221 * g211;
496            temp1 *= aonv;
497            temp = temp1 * root32;
498            d3210 = temp * f321 * g310;
499            d3222 = temp * f322 * g322;
500            temp1 *= aonv;
501            temp = 2.0 * temp1 * root44;
502            d4410 = temp * f441 * g410;
503            d4422 = temp * f442 * g422;
504            temp1 *= aonv;
505            temp = temp1 * root52;
506            d5220 = temp * f522 * g520;
507            d5232 = temp * f523 * g532;
508            temp = 2.0 * temp1 * root54;
509            d5421 = temp * f542 * g521;
510            d5433 = temp * f543 * g533;
511            xlamo = (mo + nodeo + nodeo - (theta + theta)) % TAU;
512            xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no;
513            em = emo;
514            emsq = emsqo;
515        }
516
517        //  ---------------- synchronous resonance terms --------------
518        if irez == 1 {
519            g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq);
520            g310 = 1.0 + 2.0 * emsq;
521            g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq);
522            f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim);
523            f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim);
524            f330 = 1.0 + cosim;
525            // f330 *= 1.875 * f330 * f330;
526            f330 = f330 * 1.875 * f330 * f330;
527            del1 = 3.0 * nm * nm * aonv * aonv;
528            del2 = 2.0 * del1 * f220 * g200 * q22;
529            del3 = 3.0 * del1 * f330 * g300 * q33 * aonv;
530            del1 = del1 * f311 * g310 * q31 * aonv;
531            xlamo = (mo + nodeo + argpo - theta) % TAU;
532            xfact = mdot + xpidot + dmdt + domdt + dnodt - (no + rptim);
533        }
534
535        //  ------------ for sgp4, initialize the integrator ----------
536        xli = xlamo;
537        xni = no;
538        atime = 0.0;
539        nm = no + dndt;
540    }
541
542    DsInitOutput {
543        em,
544        argpm,
545        inclm,
546        mm,
547        nm,
548        nodem,
549
550        irez: irez as f64,
551        atime,
552
553        d2201,
554        d2211,
555        d3210,
556        d3222,
557        d4410,
558
559        d4422,
560        d5220,
561        d5232,
562        d5421,
563        d5433,
564
565        dedt,
566        didt,
567        dmdt,
568        dndt,
569        dnodt,
570        domdt,
571
572        del1,
573        del2,
574        del3,
575
576        xfact,
577        xlamo,
578        xli,
579        xni,
580    }
581}