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.utilities.hansen;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.polynomials.PolynomialFunction;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.MathArrays;
24
25 /**
26 * Hansen coefficients K(t,n,s) for t=0 and n > 0.
27 * <p>
28 * Implements Collins 4-254 or Danielson 2.7.3-(7) for Hansen Coefficients and
29 * Danielson 3.2-(3) for derivatives. The recursions are transformed into
30 * composition of linear transformations to obtain the associated polynomials
31 * for coefficients and their derivatives - see Petre's paper
32 *
33 * @author Petre Bazavan
34 * @author Lucian Barbulescu
35 * @author Bryan Cazabonne
36 */
37 public class FieldHansenThirdBodyLinear <T extends CalculusFieldElement<T>> {
38
39 /** The number of coefficients that will be computed with a set of roots. */
40 private static final int SLICE = 10;
41
42 /**
43 * The first vector of polynomials associated to Hansen coefficients and
44 * derivatives.
45 */
46 private PolynomialFunction[][] mpvec;
47
48 /** The second vector of polynomials associated only to derivatives. */
49 private PolynomialFunction[][] mpvecDeriv;
50
51 /** The Hansen coefficients used as roots. */
52 private T[][] hansenRoot;
53
54 /** The derivatives of the Hansen coefficients used as roots. */
55 private T[][] hansenDerivRoot;
56
57 /** The number of slices needed to compute the coefficients. */
58 private int numSlices;
59
60 /** The maximum order of n indexes. */
61 private int nMax;
62
63 /** The index of the initial condition, Petre's paper. */
64 private int N0;
65
66 /** The s index. */
67 private int s;
68
69 /** (-1)<sup>s</sup> * (2*s + 1)!! / (s+1)! */
70 private double twosp1dfosp1f;
71
72 /** (-1)<sup>s</sup> * (2*s + 1)!! / (s+2)! */
73 private double twosp1dfosp2f;
74
75 /** (-1)<sup>s</sup> * 2 * (2*s + 1)!! / (s+2)! */
76 private double two2sp1dfosp2f;
77
78 /** (2*s + 3). */
79 private double twosp3;
80
81 /**
82 * Constructor.
83 *
84 * @param nMax the maximum value of n
85 * @param s the value of s
86 * @param field field used by default
87 */
88 public FieldHansenThirdBodyLinear(final int nMax, final int s, final Field<T> field) {
89 // initialise fields
90 this.nMax = nMax;
91 N0 = s;
92 this.s = s;
93
94 // initialization of structures for stored data
95 mpvec = new PolynomialFunction[this.nMax + 1][];
96 mpvecDeriv = new PolynomialFunction[this.nMax + 1][];
97
98 //Compute the fields that will be used to determine the initial values for the coefficients
99 this.twosp1dfosp1f = (s % 2 == 0) ? 1.0 : -1.0;
100 for (int i = s; i >= 1; i--) {
101 this.twosp1dfosp1f *= (2.0 * i + 1.0) / (i + 1.0);
102 }
103
104 this.twosp1dfosp2f = this.twosp1dfosp1f / (s + 2.);
105 this.twosp3 = 2 * s + 3;
106 this.two2sp1dfosp2f = 2 * this.twosp1dfosp2f;
107
108 // initialization of structures for stored data
109 mpvec = new PolynomialFunction[this.nMax + 1][];
110 mpvecDeriv = new PolynomialFunction[this.nMax + 1][];
111
112 this.numSlices = FastMath.max(1, (nMax - s + SLICE - 2) / SLICE);
113
114 hansenRoot = MathArrays.buildArray(field, numSlices, 2);
115 hansenDerivRoot = MathArrays.buildArray(field, numSlices, 2);
116
117 // Prepare the database of the associated polynomials
118 generatePolynomials();
119
120 }
121
122 /**
123 * Compute polynomial coefficient a.
124 *
125 * <p>
126 * It is used to generate the coefficient for K₀<sup>n-1, s</sup> when computing K₀<sup>n, s</sup>
127 * and the coefficient for dK₀<sup>n-1, s</sup> / dΧ when computing dK₀<sup>n, s</sup> / dΧ
128 * </p>
129 *
130 * <p>
131 * See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
132 * </p>
133 *
134 * @param n n value
135 * @return the polynomial
136 */
137 private PolynomialFunction a(final int n) {
138 // from recurrence Danielson 2.7.3-(7c), Collins 4-254
139 final double r1 = 2 * n + 1;
140 final double r2 = n + 1;
141
142 return new PolynomialFunction(new double[] {
143 r1 / r2
144 });
145 }
146
147 /**
148 * Compute polynomial coefficient b.
149 *
150 * <p>
151 * It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing K₀<sup>n, s</sup>
152 * and the coefficient for dK₀<sup>n-2, s</sup> / dΧ when computing dK₀<sup>n, s</sup> / dΧ
153 * </p>
154 *
155 * <p>
156 * See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
157 * </p>
158 *
159 * @param n n value
160 * @return the polynomial
161 */
162 private PolynomialFunction b(final int n) {
163 // from recurrence Danielson 2.7.3-(7c), Collins 4-254
164 final double r1 = (n + s) * (n - s);
165 final double r2 = n * (n + 1);
166
167 return new PolynomialFunction(new double[] {
168 0.0, 0.0, -r1 / r2
169 });
170 }
171
172 /**
173 * Compute polynomial coefficient d.
174 *
175 * <p>
176 * It is used to generate the coefficient for K₀<sup>n-2, s</sup> when computing dK₀<sup>n, s</sup> / dΧ
177 * </p>
178 *
179 * <p>
180 * See Danielson 2.7.3-(7c) and Collins 4-254 and 4-257
181 * </p>
182 *
183 * @param n n value
184 * @return the polynomial
185 */
186 private PolynomialFunction d(final int n) {
187 // from Danielson 3.2-(3b)
188 final double r1 = 2 * (n + s) * (n - s);
189 final double r2 = n * (n + 1);
190
191 return new PolynomialFunction(new double[] {
192 0.0, 0.0, 0.0, r1 / r2
193 });
194 }
195
196 /**
197 * Generate the polynomials needed in the linear transformation.
198 *
199 * <p>
200 * See Petre's paper
201 * </p>
202 */
203 private void generatePolynomials() {
204
205 int sliceCounter = 0;
206
207 // Initialization of the matrices for linear transformations
208 // The final configuration of these matrices are obtained by composition
209 // of linear transformations
210
211 // the matrix A for the polynomials associated
212 // to Hansen coefficients, Petre's pater
213 PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix2();
214
215 // the matrix D for the polynomials associated
216 // to derivatives, Petre's paper
217 final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix2();
218 PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix2();
219 PolynomialFunctionMatrix E = HansenUtilities.buildIdentityMatrix2();
220
221 // The matrix that contains the coefficients at each step
222 final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix2();
223 a.setElem(0, 1, HansenUtilities.ONE);
224
225 // The generation process
226 for (int i = N0 + 2; i <= nMax; i++) {
227 // Collins 4-254 or Danielson 2.7.3-(7)
228 // Petre's paper
229 // The matrix of the current linear transformation is actualized
230 a.setMatrixLine(1, new PolynomialFunction[] {
231 b(i), a(i)
232 });
233
234 // composition of the linear transformations to calculate
235 // the polynomials associated to Hansen coefficients
236 A = A.multiply(a);
237 // store the polynomials associated to Hansen coefficients
238 this.mpvec[i] = A.getMatrixLine(1);
239 // composition of the linear transformations to calculate
240 // the polynomials associated to derivatives
241 // Danielson 3.2-(3b) and Petre's paper
242 D = D.multiply(a);
243 if (sliceCounter % SLICE != 0) {
244 a.setMatrixLine(1, new PolynomialFunction[] {
245 b(i - 1), a(i - 1)
246 });
247 E = E.multiply(a);
248 }
249
250 B.setElem(1, 0, d(i));
251 // F = E.prod(B);
252 D = D.add(E.multiply(B));
253 // store the polynomials associated to the derivatives
254 this.mpvecDeriv[i] = D.getMatrixLine(1);
255
256 if (++sliceCounter % SLICE == 0) {
257 // Re-Initialization of the matrices for linear transformations
258 // The final configuration of these matrices are obtained by composition
259 // of linear transformations
260 A = HansenUtilities.buildIdentityMatrix2();
261 D = HansenUtilities.buildZeroMatrix2();
262 E = HansenUtilities.buildIdentityMatrix2();
263 }
264 }
265 }
266
267 /**
268 * Compute the initial values (see Collins, 4-255, 4-256 and 4.259)
269 * <p>
270 * K₀<sup>s, s</sup> = (-1)<sup>s</sup> * ( (2*s+1)!! / (s+1)! )
271 * </p>
272 * <p>
273 * K₀<sup>s+1, s</sup> = (-1)<sup>s</sup> * ( (2*s+1)!! / (s+2)!
274 * ) * (2*s+3 - χ<sup>-2</sup>)
275 * </p>
276 * <p>
277 * dK₀<sup>s+1, s</sup> / dχ = = (-1)<sup>s</sup> * 2 * (
278 * (2*s+1)!! / (s+2)! ) * χ<sup>-3</sup>
279 * </p>
280 * @param chitm1 sqrt(1 - e²)
281 * @param chitm2 sqrt(1 - e²)²
282 * @param chitm3 sqrt(1 - e²)³
283 */
284 public void computeInitValues(final T chitm1, final T chitm2, final T chitm3) {
285 final Field<T> field = chitm2.getField();
286 final T zero = field.getZero();
287 this.hansenRoot[0][0] = zero.add(twosp1dfosp1f);
288 this.hansenRoot[0][1] = (chitm2.negate().add(this.twosp3)).multiply(this.twosp1dfosp2f);
289 this.hansenDerivRoot[0][0] = zero;
290 this.hansenDerivRoot[0][1] = chitm3.multiply(two2sp1dfosp2f);
291
292 for (int i = 1; i < numSlices; i++) {
293 for (int j = 0; j < 2; j++) {
294 // Get the required polynomials
295 final PolynomialFunction[] mv = mpvec[s + (i * SLICE) + j];
296 final PolynomialFunction[] sv = mpvecDeriv[s + (i * SLICE) + j];
297
298 //Compute the root derivatives
299 hansenDerivRoot[i][j] = mv[1].value(chitm1).multiply(hansenDerivRoot[i - 1][1]).
300 add(mv[0].value(chitm1).multiply(hansenDerivRoot[i - 1][0])).
301 add(sv[1].value(chitm1).multiply(hansenRoot[i - 1][1])).
302 add(sv[0].value(chitm1).multiply(hansenRoot[i - 1][0]));
303
304 //Compute the root Hansen coefficients
305 hansenRoot[i][j] = mv[1].value(chitm1).multiply(hansenRoot[i - 1][1]).
306 add(mv[0].value(chitm1).multiply(hansenRoot[i - 1][0]));
307 }
308 }
309 }
310
311 /**
312 * Compute the value of the Hansen coefficient K₀<sup>n, s</sup>.
313 *
314 * @param n n value
315 * @param chitm1 χ<sup>-1</sup>
316 * @return the coefficient K₀<sup>n, s</sup>
317 */
318 public T getValue(final int n, final T chitm1) {
319 //Compute the potential slice
320 int sliceNo = (n - s) / SLICE;
321 if (sliceNo < numSlices) {
322 //Compute the index within the slice
323 final int indexInSlice = (n - s) % SLICE;
324
325 //Check if a root must be returned
326 if (indexInSlice <= 1) {
327 return hansenRoot[sliceNo][indexInSlice];
328 }
329 } else {
330 //the value was a potential root for a slice, but that slice was not required
331 //Decrease the slice number
332 sliceNo--;
333 }
334
335 // Danielson 2.7.3-(6c)/Collins 4-242 and Petre's paper
336 final PolynomialFunction[] v = mpvec[n];
337 T ret = v[1].value(chitm1).multiply(hansenRoot[sliceNo][1]);
338 if (hansenRoot[sliceNo][0].getReal() != 0) {
339 ret = ret.add(v[0].value(chitm1).multiply(hansenRoot[sliceNo][0]));
340 }
341
342 return ret;
343
344 }
345
346 /**
347 * Compute the value of the Hansen coefficient dK₀<sup>n, s</sup> / dΧ.
348 *
349 * @param n n value
350 * @param chitm1 χ<sup>-1</sup>
351 * @return the coefficient dK₀<sup>n, s</sup> / dΧ
352 */
353 public T getDerivative(final int n, final T chitm1) {
354 //Compute the potential slice
355 int sliceNo = (n - s) / SLICE;
356 if (sliceNo < numSlices) {
357 //Compute the index within the slice
358 final int indexInSlice = (n - s) % SLICE;
359
360 //Check if a root must be returned
361 if (indexInSlice <= 1) {
362 return hansenDerivRoot[sliceNo][indexInSlice];
363 }
364 } else {
365 //the value was a potential root for a slice, but that slice was not required
366 //Decrease the slice number
367 sliceNo--;
368 }
369
370 final PolynomialFunction[] v = mpvec[n];
371 T ret = v[1].value(chitm1).multiply(hansenDerivRoot[sliceNo][1]);
372 if (hansenDerivRoot[sliceNo][0].getReal() != 0) {
373 ret = ret.add(v[0].value(chitm1).multiply(hansenDerivRoot[sliceNo][0]));
374 }
375
376 // Danielson 2.7.3-(7c)/Collins 4-254 and Petre's paper
377 final PolynomialFunction[] v1 = mpvecDeriv[n];
378 ret = ret.add(v1[1].value(chitm1).multiply(hansenRoot[sliceNo][1]));
379 if (hansenRoot[sliceNo][0].getReal() != 0) {
380 ret = ret.add(v1[0].value(chitm1).multiply(hansenRoot[sliceNo][0]));
381 }
382 return ret;
383
384 }
385
386 }