1   /* Copyright 2002-2021 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.semianalytical.dsst.forces;
18  
19  import org.hipparchus.Field;
20  import org.hipparchus.CalculusFieldElement;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  import org.hipparchus.util.FastMath;
23  import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
24  import org.orekit.frames.FieldTransform;
25  import org.orekit.frames.Frame;
26  import org.orekit.propagation.semianalytical.dsst.utilities.FieldAuxiliaryElements;
27  
28  /**
29   * This class is a container for the common "field" parameters used in {@link DSSTTesseral}.
30   * <p>
31   * It performs parameters initialization at each integration step for the Tesseral contribution
32   * to the central body gravitational perturbation.
33   * <p>
34   * @author Bryan Cazabonne
35   * @since 10.0
36   */
37  public class FieldDSSTTesseralContext<T extends CalculusFieldElement<T>> extends FieldForceModelContext<T> {
38  
39      /** Retrograde factor I.
40       *  <p>
41       *  DSST model needs equinoctial orbit as internal representation.
42       *  Classical equinoctial elements have discontinuities when inclination
43       *  is close to zero. In this representation, I = +1. <br>
44       *  To avoid this discontinuity, another representation exists and equinoctial
45       *  elements can be expressed in a different way, called "retrograde" orbit.
46       *  This implies I = -1. <br>
47       *  As Orekit doesn't implement the retrograde orbit, I is always set to +1.
48       *  But for the sake of consistency with the theory, the retrograde factor
49       *  has been kept in the formulas.
50       *  </p>
51       */
52      private static final int I = 1;
53  
54      /** A = sqrt(μ * a). */
55      private T A;
56  
57      // Common factors for potential computation
58      /** &Chi; = 1 / sqrt(1 - e²) = 1 / B. */
59      private T chi;
60  
61      /** &Chi;². */
62      private T chi2;
63  
64      /** Central body rotation angle θ. */
65      private T theta;
66  
67      // Common factors from equinoctial coefficients
68      /** 2 * a / A .*/
69      private T ax2oA;
70  
71      /** 1 / (A * B) .*/
72      private T ooAB;
73  
74      /** B / A .*/
75      private T BoA;
76  
77      /** B / (A * (1 + B)) .*/
78      private T BoABpo;
79  
80      /** C / (2 * A * B) .*/
81      private T Co2AB;
82  
83      /** μ / a .*/
84      private T moa;
85  
86      /** R / a .*/
87      private T roa;
88  
89      /** ecc². */
90      private T e2;
91  
92      /** Keplerian mean motion. */
93      private T n;
94  
95      /** Keplerian period. */
96      private T period;
97  
98      /** Ratio of satellite period to central body rotation period. */
99      private T ratio;
100 
101     /**
102      * Simple constructor.
103      *
104      * @param auxiliaryElements auxiliary elements related to the current orbit
105      * @param centralBodyFrame rotating body frame
106      * @param provider provider for spherical harmonics
107      * @param maxFrequencyShortPeriodics maximum value for j
108      * @param bodyPeriod central body rotation period (seconds)
109      * @param parameters values of the force model parameters
110      */
111     FieldDSSTTesseralContext(final FieldAuxiliaryElements<T> auxiliaryElements,
112                                     final Frame centralBodyFrame,
113                                     final UnnormalizedSphericalHarmonicsProvider provider,
114                                     final int maxFrequencyShortPeriodics,
115                                     final double bodyPeriod,
116                                     final T[] parameters) {
117 
118         super(auxiliaryElements);
119 
120         final Field<T> field = auxiliaryElements.getDate().getField();
121         final T zero = field.getZero();
122 
123         final T mu = parameters[0];
124 
125         // Keplerian mean motion
126         final T absA = FastMath.abs(auxiliaryElements.getSma());
127         n = FastMath.sqrt(mu.divide(absA)).divide(absA);
128 
129         // Keplerian period
130         final T a = auxiliaryElements.getSma();
131         period = (a.getReal() < 0) ? zero.add(Double.POSITIVE_INFINITY) : a.multiply(a.getPi().multiply(2.0)).multiply(a.divide(mu).sqrt());
132 
133         A = FastMath.sqrt(mu.multiply(auxiliaryElements.getSma()));
134 
135         // Eccentricity square
136         e2 = auxiliaryElements.getEcc().multiply(auxiliaryElements.getEcc());
137 
138         // Central body rotation angle from equation 2.7.1-(3)(4).
139         final FieldTransform<T> t = centralBodyFrame.getTransformTo(auxiliaryElements.getFrame(), auxiliaryElements.getDate());
140         final FieldVector3D<T> xB = t.transformVector(FieldVector3D.getPlusI(field));
141         final FieldVector3D<T> yB = t.transformVector(FieldVector3D.getPlusJ(field));
142         theta = FastMath.atan2(auxiliaryElements.getVectorF().dotProduct(yB).negate().add((auxiliaryElements.getVectorG().dotProduct(xB)).multiply(I)),
143                                auxiliaryElements.getVectorF().dotProduct(xB).add(auxiliaryElements.getVectorG().dotProduct(yB).multiply(I)));
144 
145         // Common factors from equinoctial coefficients
146         // 2 * a / A
147         ax2oA  = auxiliaryElements.getSma().divide(A).multiply(2.);
148         // B / A
149         BoA    = auxiliaryElements.getB().divide(A);
150         // 1 / AB
151         ooAB   = A.multiply(auxiliaryElements.getB()).reciprocal();
152         // C / 2AB
153         Co2AB  = auxiliaryElements.getC().multiply(ooAB).divide(2.);
154         // B / (A * (1 + B))
155         BoABpo = BoA.divide(auxiliaryElements.getB().add(1.));
156         // &mu / a
157         moa    = mu.divide(auxiliaryElements.getSma());
158         // R / a
159         roa    = auxiliaryElements.getSma().divide(provider.getAe()).reciprocal();
160 
161         // &Chi; = 1 / B
162         chi  = auxiliaryElements.getB().reciprocal();
163         chi2 = chi.multiply(chi);
164 
165         // Ratio of satellite to central body periods to define resonant terms
166         ratio = period.divide(bodyPeriod);
167 
168     }
169 
170     /** Get ecc².
171      * @return e2
172      */
173     public T getE2() {
174         return e2;
175     }
176 
177     /** Get Central body rotation angle θ.
178      * @return theta
179      */
180     public T getTheta() {
181         return theta;
182     }
183 
184     /** Get ax2oA = 2 * a / A .
185      * @return ax2oA
186      */
187     public T getAx2oA() {
188         return ax2oA;
189     }
190 
191     /** Get &Chi; = 1 / sqrt(1 - e²) = 1 / B.
192      * @return chi
193      */
194     public T getChi() {
195         return chi;
196     }
197 
198     /** Get &Chi;².
199      * @return chi2
200      */
201     public T getChi2() {
202         return chi2;
203     }
204 
205     /** Get B / A.
206      * @return BoA
207      */
208     public T getBoA() {
209         return BoA;
210     }
211 
212     /** Get ooAB = 1 / (A * B).
213      * @return ooAB
214      */
215     public T getOoAB() {
216         return ooAB;
217     }
218 
219     /** Get Co2AB = C / 2AB.
220      * @return Co2AB
221      */
222     public T getCo2AB() {
223         return Co2AB;
224     }
225 
226     /** Get BoABpo = B / A(1 + B).
227      * @return BoABpo
228      */
229     public T getBoABpo() {
230         return BoABpo;
231     }
232 
233     /** Get μ / a .
234      * @return moa
235      */
236     public T getMoa() {
237         return moa;
238     }
239 
240     /** Get roa = R / a.
241      * @return roa
242      */
243     public T getRoa() {
244         return roa;
245     }
246 
247     /** Get the Keplerian period.
248      * <p>The Keplerian period is computed directly from semi major axis
249      * and central acceleration constant.</p>
250      * @return Keplerian period in seconds, or positive infinity for hyperbolic orbits
251      */
252     public T getOrbitPeriod() {
253         return period;
254     }
255 
256     /** Get the Keplerian mean motion.
257      * <p>The Keplerian mean motion is computed directly from semi major axis
258      * and central acceleration constant.</p>
259      * @return Keplerian mean motion in radians per second
260      */
261     public T getMeanMotion() {
262         return n;
263     }
264 
265     /** Get the ratio of satellite period to central body rotation period.
266      * @return ratio
267      */
268     public T getRatio() {
269         return ratio;
270     }
271 
272 }