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 java.util.Map;
20 import java.util.TreeMap;
21
22 import org.hipparchus.Field;
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.analysis.polynomials.PolynomialFunction;
25 import org.hipparchus.analysis.polynomials.PolynomialsUtils;
26 import org.hipparchus.complex.Complex;
27 import org.hipparchus.exception.NullArgumentException;
28 import org.hipparchus.random.MersenneTwister;
29 import org.hipparchus.util.CombinatoricsUtils;
30 import org.hipparchus.util.Decimal64Field;
31 import org.hipparchus.util.FastMath;
32 import org.hipparchus.util.MathArrays;
33 import org.junit.Assert;
34 import org.junit.Test;
35 import org.orekit.errors.OrekitException;
36 import org.orekit.propagation.semianalytical.dsst.utilities.CoefficientsFactory.NSKey;
37
38 public class CoefficientFactoryTest {
39
40 private static final double eps0 = 0.;
41 private static final double eps10 = 1e-10;
42 private static final double eps12 = 1e-12;
43
44
45 private static Map<NSKey, PolynomialFunction> QNS_MAP = new TreeMap<NSKey, PolynomialFunction>();
46
47 @Test
48 public void testVns() {
49 final int order = 100;
50 TreeMap<NSKey, Double> Vns = CoefficientsFactory.computeVns(order);
51
52
53 for (int i = 0; i < order; i++) {
54 for (int j = 0; j < i + 1; j++) {
55 if ((i - j) % 2 != 0) {
56 Assert.assertEquals(0d, Vns.get(new NSKey(i, j)), eps0);
57 }
58 }
59 }
60
61
62 Assert.assertEquals(1, Vns.get(new NSKey(0, 0)), eps0);
63 Assert.assertEquals(0.5, Vns.get(new NSKey(1, 1)), eps0);
64 Assert.assertEquals(-0.5, Vns.get(new NSKey(2, 0)), eps0);
65 Assert.assertEquals(1 / 8d, Vns.get(new NSKey(2, 2)), eps0);
66 Assert.assertEquals(-1 / 8d, Vns.get(new NSKey(3, 1)), eps0);
67 Assert.assertEquals(1 / 48d, Vns.get(new NSKey(3, 3)), eps0);
68 Assert.assertEquals(3 / 8d, Vns.get(new NSKey(4, 0)), eps0);
69 Assert.assertEquals(-1 / 48d, Vns.get(new NSKey(4, 2)), eps0);
70 Assert.assertEquals(1 / 384d, Vns.get(new NSKey(4, 4)), eps0);
71 Assert.assertEquals(1 / 16d, Vns.get(new NSKey(5, 1)), eps0);
72 Assert.assertEquals(-1 / 384d, Vns.get(new NSKey(5, 3)), eps0);
73 Assert.assertEquals(1 / 3840d, Vns.get(new NSKey(5, 5)), eps0);
74 Assert.assertEquals(Vns.lastKey().getN(), order - 1);
75 Assert.assertEquals(Vns.lastKey().getS(), order - 1);
76 }
77
78
79
80
81
82 @Test
83 public void testVmns() {
84 Assert.assertEquals(getVmns2(0, 0, 0), CoefficientsFactory.getVmns(0, 0, 0), eps0);
85 Assert.assertEquals(getVmns2(0, 1, 1), CoefficientsFactory.getVmns(0, 1, 1), eps0);
86 Assert.assertEquals(getVmns2(0, 2, 2), CoefficientsFactory.getVmns(0, 2, 2), eps0);
87 Assert.assertEquals(getVmns2(0, 3, 1), CoefficientsFactory.getVmns(0, 3, 1), eps0);
88 Assert.assertEquals(getVmns2(0, 3, 3), CoefficientsFactory.getVmns(0, 3, 3), eps0);
89 Assert.assertEquals(getVmns2(2, 2, 2), CoefficientsFactory.getVmns(2, 2, 2), eps0);
90 final double vmnsp = getVmns2(12, 26, 20);
91 Assert.assertEquals(vmnsp,
92 CoefficientsFactory.getVmns(12, 26, 20),
93 FastMath.abs(eps12 * vmnsp));
94 final double vmnsm = getVmns2(12, 27, -21);
95 Assert.assertEquals(vmnsm,
96 CoefficientsFactory.getVmns(12, 27, -21),
97 Math.abs(eps12 * vmnsm));
98 }
99
100
101 @Test(expected = OrekitException.class)
102 public void testVmnsError() {
103
104 CoefficientsFactory.getVmns(3, 2, 1);
105 }
106
107 @Test
108 public void testKey() {
109
110 NSKey key21 = new NSKey(2, 1);
111 Assert.assertEquals(key21, key21);
112 Assert.assertEquals(key21, new NSKey(2, 1));
113 Assert.assertNotEquals(key21, null);
114 Assert.assertNotEquals(key21, new NSKey(2, 0));
115 Assert.assertNotEquals(key21, new NSKey(3, 1));
116 Assert.assertEquals(-1719365209, key21.hashCode());
117 Assert.assertEquals(-1719365465, new NSKey(3, 1).hashCode());
118 }
119
120
121
122
123
124 @Test
125 public void testQns() {
126 Assert.assertEquals(1., getQnsPolynomialValue(0, 0, 0), 0.);
127
128 final int nmax = 10;
129 final int smax = 10;
130 final MersenneTwister random = new MersenneTwister(123456789);
131 for (int g = 0; g < 1000; g++) {
132 final double gamma = random.nextDouble();
133 double[][] qns = CoefficientsFactory.computeQns(gamma, nmax, smax);
134 for (int n = 0; n <= nmax; n++) {
135 final int sdim = FastMath.min(smax + 2, n);
136 for (int s = 0; s <= sdim; s++) {
137 final double qp = getQnsPolynomialValue(gamma, n, s);
138 Assert.assertEquals(qns[n][s], qp, FastMath.abs(eps10 * qns[n][s]));
139 }
140 }
141 }
142 }
143
144 @Test
145 public void testQnsField() {
146 doTestQnsField(Decimal64Field.getInstance());
147 }
148
149
150
151
152
153 private <T extends CalculusFieldElement<T>> void doTestQnsField(Field<T> field) {
154 final T zero = field.getZero();
155 Assert.assertEquals(1., getQnsPolynomialValue(0, 0, 0), 0.);
156
157 final int nmax = 10;
158 final int smax = 10;
159 final MersenneTwister random = new MersenneTwister(123456789);
160 for (int g = 0; g < 1000; g++) {
161 final T gamma = zero.add(random.nextDouble());
162 T[][] qns = CoefficientsFactory.computeQns(gamma, nmax, smax);
163 for (int n = 0; n <= nmax; n++) {
164 final int sdim = FastMath.min(smax + 2, n);
165 for (int s = 0; s <= sdim; s++) {
166 final T qp = getQnsPolynomialValue(gamma, n, s);
167 Assert.assertEquals(qns[n][s].getReal(), qp.getReal(), FastMath.abs(qns[n][s].multiply(eps10)).getReal());
168 }
169 }
170 }
171 }
172
173
174
175
176 @Test
177 public void testGsHs() {
178 final int s = 50;
179 final MersenneTwister random = new MersenneTwister(123456789);
180 for (int i = 0; i < 10; i++) {
181 final double k = random.nextDouble();
182 final double h = random.nextDouble();
183 final double a = random.nextDouble();
184 final double b = random.nextDouble();
185 final double[][] GH = CoefficientsFactory.computeGsHs(k, h, a, b, s);
186 for (int j = 1; j < s; j++) {
187 final double[] GsHs = getGsHs(k, h, a, b, j);
188 Assert.assertEquals(GsHs[0], GH[0][j], FastMath.abs(eps12 * GsHs[0]));
189 Assert.assertEquals(GsHs[1], GH[1][j], FastMath.abs(eps12 * GsHs[1]));
190 }
191 }
192 }
193
194 @Test
195 public void testGsHsField() {
196 doTestGsHsField(Decimal64Field.getInstance());
197 }
198
199
200
201
202 private <T extends CalculusFieldElement<T>> void doTestGsHsField(Field<T> field) {
203 final T zero = field.getZero();
204 final int s = 50;
205 final MersenneTwister random = new MersenneTwister(123456789);
206 for (int i = 0; i < 10; i++) {
207 final T k = zero.add(random.nextDouble());
208 final T h = zero.add(random.nextDouble());
209 final T a = zero.add(random.nextDouble());
210 final T b = zero.add(random.nextDouble());
211 final T[][] GH = CoefficientsFactory.computeGsHs(k, h, a, b, s, field);
212 for (int j = 1; j < s; j++) {
213 final T[] GsHs = getGsHs(k, h, a, b, j, field);
214 Assert.assertEquals(GsHs[0].getReal(), GH[0][j].getReal(), FastMath.abs(GsHs[0].multiply(eps12)).getReal());
215 Assert.assertEquals(GsHs[1].getReal(), GH[1][j].getReal(), FastMath.abs(GsHs[1].multiply(eps12)).getReal());
216 }
217 }
218 }
219
220
221
222
223 private static double getVmns2(final int m,
224 final int n,
225 final int s) {
226 double vmsn = 0d;
227 if ((n - s) % 2 == 0) {
228 final int coef = (s > 0 || s % 2 == 0) ? 1 : -1;
229 final int ss = (s > 0) ? s : -s;
230 final double num = FastMath.pow(-1, (n - ss) / 2) *
231 CombinatoricsUtils.factorialDouble(n + ss) *
232 CombinatoricsUtils.factorialDouble(n - ss);
233 final double den = FastMath.pow(2, n) *
234 CombinatoricsUtils.factorialDouble(n - m) *
235 CombinatoricsUtils.factorialDouble((n + ss) / 2) *
236 CombinatoricsUtils.factorialDouble((n - ss) / 2);
237 vmsn = coef * num / den;
238 }
239 return vmsn;
240 }
241
242
243
244
245
246
247
248
249
250
251
252 private static double getQnsPolynomialValue(final double gamma, final int n, final int s) {
253 PolynomialFunction derivative;
254 if (QNS_MAP.containsKey(new NSKey(n, s))) {
255 derivative = QNS_MAP.get(new NSKey(n, s));
256 } else {
257 final PolynomialFunction legendre = PolynomialsUtils.createLegendrePolynomial(n);
258 derivative = legendre;
259 for (int i = 0; i < s; i++) {
260 derivative = (PolynomialFunction) derivative.polynomialDerivative();
261 }
262 QNS_MAP.put(new NSKey(n, s), derivative);
263 }
264 return derivative.value(gamma);
265 }
266
267
268
269
270
271
272
273
274
275
276
277 private static <T extends CalculusFieldElement<T>> T getQnsPolynomialValue(final T gamma, final int n, final int s) {
278 PolynomialFunction derivative;
279 if (QNS_MAP.containsKey(new NSKey(n, s))) {
280 derivative = QNS_MAP.get(new NSKey(n, s));
281 } else {
282 final PolynomialFunction legendre = PolynomialsUtils.createLegendrePolynomial(n);
283 derivative = legendre;
284 for (int i = 0; i < s; i++) {
285 derivative = (PolynomialFunction) derivative.polynomialDerivative();
286 }
287 QNS_MAP.put(new NSKey(n, s), derivative);
288 }
289 return derivative.value(gamma);
290 }
291
292
293
294
295
296
297
298
299
300
301
302 private static double[] getGsHs(final double k, final double h,
303 final double a, final double b, final int s) {
304 final Complex as = new Complex(k, h).pow(s);
305 final Complex bs = new Complex(a, -b).pow(s);
306 final Complex asbs = as.multiply(bs);
307 return new double[] {asbs.getReal(), asbs.getImaginary()};
308 }
309
310
311
312
313
314
315
316
317
318
319
320 private static <T extends CalculusFieldElement<T>> T[] getGsHs(final T k, final T h,
321 final T a, final T b, final int s,
322 final Field<T> field) {
323 final FieldComplex<T> as = new FieldComplex<>(k, h).pow(s);
324 final FieldComplex<T> bs = new FieldComplex<>(a, b.negate()).pow(s);
325 final FieldComplex<T> asbs = as.multiply(bs);
326 final T[] values = MathArrays.buildArray(field, 2);
327 values[0] = asbs.getReal();
328 values[1] = asbs.getImaginary();
329 return values;
330 }
331
332 private static class FieldComplex <T extends CalculusFieldElement<T>> {
333
334
335 private final T imaginary;
336
337
338 private final T real;
339
340
341
342
343
344
345
346 FieldComplex(final T real, final T imaginary) {
347 this.real = real;
348 this.imaginary = imaginary;
349 }
350
351
352
353
354
355
356 public T getReal() {
357 return real;
358 }
359
360
361
362
363
364
365 public T getImaginary() {
366 return imaginary;
367 }
368
369
370
371
372
373
374
375
376
377
378 protected FieldComplex<T> createComplex(final T realPart, final T imaginaryPart) {
379 return new FieldComplex<>(realPart, imaginaryPart);
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public FieldComplex<T> multiply(final FieldComplex<T> factor) throws NullArgumentException {
398 return createComplex(real.multiply(factor.real).subtract(imaginary.multiply(factor.imaginary)),
399 real.multiply(factor.imaginary).add(imaginary.multiply(factor.real)));
400 }
401
402
403
404
405
406
407
408
409
410 public FieldComplex<T> multiply(final int factor) {
411 return createComplex(real.multiply(factor), imaginary.multiply(factor));
412 }
413
414
415
416
417
418
419
420
421 public FieldComplex<T> pow(int x) {
422 return this.log().multiply(x).exp();
423 }
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459 public FieldComplex<T> log() {
460 return createComplex(FastMath.log(abs()),
461 FastMath.atan2(imaginary, real));
462 }
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495 public FieldComplex<T> exp() {
496 T expReal = FastMath.exp(real);
497 return createComplex(expReal.multiply(FastMath.cos(imaginary)),
498 expReal.multiply(FastMath.sin(imaginary)));
499 }
500
501
502
503
504
505
506
507
508
509 public T abs() {
510 if (FastMath.abs(real).getReal() < FastMath.abs(imaginary).getReal()) {
511 if (imaginary.getReal() == 0.0) {
512 return FastMath.abs(real);
513 }
514 T q = real.divide(imaginary);
515 return FastMath.abs(imaginary).multiply(FastMath.sqrt(q.multiply(q).add(1.)));
516 } else {
517 if (real.getReal() == 0.0) {
518 return FastMath.abs(imaginary);
519 }
520 T q = imaginary.divide(real);
521 return FastMath.abs(real).multiply(FastMath.sqrt(q.multiply(q).add(1.)));
522 }
523 }
524
525 }
526 }