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