1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst.utilities;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.util.CombinatoricsUtils;
22 import org.hipparchus.util.FastMath;
23 import org.hipparchus.util.MathArrays;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26
27 import java.util.SortedMap;
28 import java.util.concurrent.ConcurrentSkipListMap;
29
30
31
32
33
34
35 public class CoefficientsFactory {
36
37
38 private static SortedMap<NSKey, Double> VNS = new ConcurrentSkipListMap<>();
39
40
41 private static int LAST_VNS_ORDER = 2;
42
43
44 static {
45
46 VNS.put(new NSKey(0, 0), 1.);
47 VNS.put(new NSKey(1, 0), 0.);
48 VNS.put(new NSKey(1, 1), 0.5);
49 }
50
51
52
53 private CoefficientsFactory() {
54 }
55
56
57
58
59
60
61
62
63
64
65
66 public static double[][] computeQns(final double gamma, final int nMax, final int sMax) {
67
68
69 final int sDim = FastMath.min(sMax + 1, nMax) + 1;
70 final int rows = nMax + 1;
71 final double[][] Qns = new double[rows][];
72 for (int i = 0; i <= nMax; i++) {
73 final int snDim = FastMath.min(i + 1, sDim);
74 Qns[i] = new double[snDim];
75 }
76
77
78 Qns[0][0] = 1;
79
80 for (int n = 1; n <= nMax; n++) {
81 final int snDim = FastMath.min(n + 1, sDim);
82 for (int s = 0; s < snDim; s++) {
83 if (n == s) {
84 Qns[n][s] = (2. * s - 1.) * Qns[s - 1][s - 1];
85 } else if (n == (s + 1)) {
86 Qns[n][s] = (2. * s + 1.) * gamma * Qns[s][s];
87 } else {
88 Qns[n][s] = (2. * n - 1.) * gamma * Qns[n - 1][s] - (n + s - 1.) * Qns[n - 2][s];
89 Qns[n][s] /= n - s;
90 }
91 }
92 }
93
94 return Qns;
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 public static <T extends CalculusFieldElement<T>> T[][] computeQns(final T gamma, final int nMax, final int sMax) {
109
110
111 final int sDim = FastMath.min(sMax + 1, nMax) + 1;
112 final int rows = nMax + 1;
113 final T[][] Qns = MathArrays.buildArray(gamma.getField(), rows, FastMath.min(nMax + 1, sDim) - 1);
114 for (int i = 0; i <= nMax; i++) {
115 final int snDim = FastMath.min(i + 1, sDim);
116 Qns[i] = MathArrays.buildArray(gamma.getField(), snDim);
117 }
118
119
120 Qns[0][0] = gamma.subtract(gamma).add(1.);
121
122 for (int n = 1; n <= nMax; n++) {
123 final int snDim = FastMath.min(n + 1, sDim);
124 for (int s = 0; s < snDim; s++) {
125 if (n == s) {
126 Qns[n][s] = Qns[s - 1][s - 1].multiply(2. * s - 1.);
127 } else if (n == (s + 1)) {
128 Qns[n][s] = Qns[s][s].multiply(gamma).multiply(2. * s + 1.);
129 } else {
130 Qns[n][s] = Qns[n - 1][s].multiply(gamma).multiply(2. * n - 1.).subtract(Qns[n - 2][s].multiply(n + s - 1.));
131 Qns[n][s] = Qns[n][s].divide(n - s);
132 }
133 }
134 }
135
136 return Qns;
137 }
138
139
140
141
142
143
144
145
146
147
148
149 public static double[][] computeGsHs(final double k, final double h,
150 final double alpha, final double beta,
151 final int order) {
152
153 final double hamkb = h * alpha - k * beta;
154 final double kaphb = k * alpha + h * beta;
155
156 final double[][] GsHs = new double[2][order + 1];
157 GsHs[0][0] = 1.;
158 GsHs[1][0] = 0.;
159
160 for (int s = 1; s <= order; s++) {
161
162 GsHs[0][s] = kaphb * GsHs[0][s - 1] - hamkb * GsHs[1][s - 1];
163
164 GsHs[1][s] = hamkb * GsHs[0][s - 1] + kaphb * GsHs[1][s - 1];
165 }
166
167 return GsHs;
168 }
169
170
171
172
173
174
175
176
177
178
179
180
181
182 public static <T extends CalculusFieldElement<T>> T[][] computeGsHs(final T k, final T h,
183 final T alpha, final T beta,
184 final int order, final Field<T> field) {
185
186 final T zero = field.getZero();
187
188
189 final T hamkb = h.multiply(alpha).subtract(k.multiply(beta));
190 final T kaphb = k.multiply(alpha).add(h.multiply(beta));
191
192 final T[][] GsHs = MathArrays.buildArray(field, 2, order + 1);
193 GsHs[0][0] = zero.newInstance(1.);
194 GsHs[1][0] = zero;
195
196 for (int s = 1; s <= order; s++) {
197
198 GsHs[0][s] = kaphb.multiply(GsHs[0][s - 1]).subtract(hamkb.multiply(GsHs[1][s - 1]));
199
200 GsHs[1][s] = hamkb.multiply(GsHs[0][s - 1]).add(kaphb.multiply(GsHs[1][s - 1]));
201 }
202
203 return GsHs;
204 }
205
206
207
208
209
210
211 public static SortedMap<NSKey, Double> computeVns(final int order) {
212
213 if (order > LAST_VNS_ORDER) {
214
215
216 final int min = FastMath.max(LAST_VNS_ORDER - 2, 0);
217 for (int n = min; n < order; n++) {
218 for (int s = 0; s < n + 1; s++) {
219 if ((n - s) % 2 != 0) {
220 VNS.put(new NSKey(n, s), 0.);
221 } else {
222
223 if (n == s && (s + 1) < order) {
224 VNS.put(new NSKey(s + 1, s + 1), VNS.get(new NSKey(s, s)) / (2 * s + 2.));
225 }
226
227 if ((n + 2) < order) {
228 VNS.put(new NSKey(n + 2, s), VNS.get(new NSKey(n, s)) * (-n + s - 1.) / (n + s + 2.));
229 }
230 }
231 }
232 }
233 LAST_VNS_ORDER = order;
234 }
235 return new ConcurrentSkipListMap<>(VNS);
236 }
237
238
239
240
241
242
243
244
245 public static double getVmns(final int m, final int n, final int s) {
246 if (m > n) {
247 throw new OrekitException(OrekitMessages.DSST_VMNS_COEFFICIENT_ERROR_MS, m, n);
248 }
249 final double fns = CombinatoricsUtils.factorialDouble(n + FastMath.abs(s));
250 final double fnm = CombinatoricsUtils.factorialDouble(n - m);
251
252 double result = 0;
253
254 if ((n - s) % 2 == 0) {
255
256 if ((n + 1) > LAST_VNS_ORDER) {
257 computeVns(n + 1);
258 }
259 if (s >= 0) {
260 result = fns * VNS.get(new NSKey(n, s)) / fnm;
261 } else {
262
263 final int mops = (s % 2 == 0) ? 1 : -1;
264 result = mops * fns * VNS.get(new NSKey(n, -s)) / fnm;
265 }
266 }
267 return result;
268 }
269
270
271 public static class NSKey implements Comparable<NSKey> {
272
273
274 private final int n;
275
276
277 private final int s;
278
279
280
281
282
283 public NSKey(final int n, final int s) {
284 this.n = n;
285 this.s = s;
286 }
287
288
289
290
291 public int getN() {
292 return n;
293 }
294
295
296
297
298 public int getS() {
299 return s;
300 }
301
302
303 public int compareTo(final NSKey key) {
304 int result = 1;
305 if (n == key.n) {
306 if (s < key.s) {
307 result = -1;
308 } else if (s == key.s) {
309 result = 0;
310 }
311 } else if (n < key.n) {
312 result = -1;
313 }
314 return result;
315 }
316
317
318 public boolean equals(final Object key) {
319
320 if (key == this) {
321
322 return true;
323 }
324
325 if (key instanceof NSKey) {
326 return n == ((NSKey) key).n && s == ((NSKey) key).s;
327 }
328
329 return false;
330
331 }
332
333
334 public int hashCode() {
335 return 0x998493a6 ^ (n << 8) ^ s;
336 }
337
338 }
339
340 }