1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst.utilities.hansen;
18
19 import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
20 import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
21 import org.apache.commons.math3.util.FastMath;
22 import org.orekit.propagation.semianalytical.dsst.utilities.NewcombOperators;
23
24
25
26
27
28
29
30
31
32
33
34
35 public class HansenTesseralLinear {
36
37
38 private static final int SLICE = 10;
39
40
41
42
43
44 private PolynomialFunction[][] mpvec;
45
46
47 private PolynomialFunction[][] mpvecDeriv;
48
49
50 private double[][] hansenRoot;
51
52
53 private double[][] hansenDerivRoot;
54
55
56 private int Nmin;
57
58
59 private int N0;
60
61
62 private int s;
63
64
65 private int j;
66
67
68 private int numSlices;
69
70
71
72
73
74 private int offset;
75
76
77 private HansenCoefficientsBySeries[] hansenInit;
78
79
80
81
82
83
84
85
86
87
88 public HansenTesseralLinear(final int nMax, final int s, final int j, final int n0, final int maxHansen) {
89
90 this.offset = nMax + 1;
91 this.Nmin = -nMax - 1;
92 this.N0 = -n0 - 4;
93 this.s = s;
94 this.j = j;
95
96
97 final int maxRoots = FastMath.min(4, N0 - Nmin + 4);
98 this.hansenInit = new HansenCoefficientsBySeries[maxRoots];
99 for (int i = 0; i < maxRoots; i++) {
100 this.hansenInit[i] = new HansenCoefficientsBySeries(N0 - i + 3, s, j, maxHansen);
101 }
102
103
104 final int size = N0 - Nmin;
105 this.numSlices = (int) FastMath.max(FastMath.ceil(((double) size) / SLICE), 1);
106 hansenRoot = new double[numSlices][4];
107 hansenDerivRoot = new double[numSlices][4];
108 if (size > 0) {
109 mpvec = new PolynomialFunction[size][];
110 mpvecDeriv = new PolynomialFunction[size][];
111
112
113 generatePolynomials();
114 }
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 private PolynomialFunction a(final int mnm1) {
133
134 final double r1 = (mnm1 + 2.) * (2. * mnm1 + 5.);
135 final double r2 = (2. + mnm1 + s) * (2. + mnm1 - s);
136 return new PolynomialFunction(new double[] {
137 0.0, 0.0, r1 / r2
138 });
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 private PolynomialFunction b(final int mnm1) {
157
158 final double r2 = (2. + mnm1 + s) * (2. + mnm1 - s);
159 final double d1 = (mnm1 + 3.) * 2. * j * s / (r2 * (mnm1 + 4.));
160 final double d2 = (mnm1 + 3.) * (mnm1 + 2.) / r2;
161 return new PolynomialFunction(new double[] {
162 0.0, -d1, -d2
163 });
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 private PolynomialFunction c(final int mnm1) {
182
183 final double r1 = j * j * (mnm1 + 2.);
184 final double r2 = (mnm1 + 4.) * (2. + mnm1 + s) * (2. + mnm1 - s);
185
186 return new PolynomialFunction(new double[] {
187 0.0, 0.0, r1 / r2
188 });
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205 private PolynomialFunction d(final int mnm1) {
206
207 return new PolynomialFunction(new double[] {
208 0.0, 0.0, 1.0
209 });
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226 private PolynomialFunction f(final int n) {
227
228 final double r1 = (n + 3.0) * j * s;
229 final double r2 = (n + 4.0) * (2.0 + n + s) * (2.0 + n - s);
230 return new PolynomialFunction(new double[] {
231 0.0, 0.0, 0.0, r1 / r2
232 });
233 }
234
235
236
237
238
239
240
241
242 private void generatePolynomials() {
243
244
245
246
247
248
249
250
251 PolynomialFunctionMatrix A = HansenUtilities.buildIdentityMatrix4();
252
253
254 final PolynomialFunctionMatrix B = HansenUtilities.buildZeroMatrix4();
255 PolynomialFunctionMatrix D = HansenUtilities.buildZeroMatrix4();
256 final PolynomialFunctionMatrix a = HansenUtilities.buildZeroMatrix4();
257
258
259 a.setMatrixLine(0, new PolynomialFunction[] {
260 HansenUtilities.ZERO, HansenUtilities.ONE, HansenUtilities.ZERO, HansenUtilities.ZERO
261 });
262 a.setMatrixLine(1, new PolynomialFunction[] {
263 HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ONE, HansenUtilities.ZERO
264 });
265 a.setMatrixLine(2, new PolynomialFunction[] {
266 HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ZERO, HansenUtilities.ONE
267 });
268
269 int index;
270 int sliceCounter = 0;
271 for (int i = N0 - 1; i > Nmin - 1; i--) {
272 index = i + this.offset;
273
274
275 a.setMatrixLine(3, new PolynomialFunction[] {
276 c(i), HansenUtilities.ZERO, b(i), a(i)
277 });
278
279
280
281
282 A = A.multiply(a);
283
284 mpvec[index] = A.getMatrixLine(3);
285
286
287
288 D = D.multiply(a);
289
290
291 B.setMatrixLine(3, new PolynomialFunction[] {
292 HansenUtilities.ZERO, f(i),
293 HansenUtilities.ZERO, d(i)
294 });
295 D = D.add(A.multiply(B));
296
297
298
299 mpvecDeriv[index] = D.getMatrixLine(3);
300
301 if (++sliceCounter % SLICE == 0) {
302
303
304
305 A = HansenUtilities.buildIdentityMatrix4();
306 D = HansenUtilities.buildZeroMatrix4();
307 }
308 }
309 }
310
311
312
313
314
315
316
317
318 public void computeInitValues(final double e2, final double chi, final double chi2) {
319
320
321
322 final int maxRoots = FastMath.min(4, N0 - Nmin + 4);
323 for (int i = 0; i < maxRoots; i++) {
324 final DerivativeStructure hansenKernel = hansenInit[i].getValue(e2, chi, chi2);
325 this.hansenRoot[0][i] = hansenKernel.getValue();
326 this.hansenDerivRoot[0][i] = hansenKernel.getPartialDerivative(1);
327 }
328
329 for (int i = 1; i < numSlices; i++) {
330 for (int k = 0; k < 4; k++) {
331 final PolynomialFunction[] mv = mpvec[N0 - (i * SLICE) - k + 3 + offset];
332 final PolynomialFunction[] sv = mpvecDeriv[N0 - (i * SLICE) - k + 3 + offset];
333
334 hansenDerivRoot[i][k] = mv[3].value(chi) * hansenDerivRoot[i - 1][3] +
335 mv[2].value(chi) * hansenDerivRoot[i - 1][2] +
336 mv[1].value(chi) * hansenDerivRoot[i - 1][1] +
337 mv[0].value(chi) * hansenDerivRoot[i - 1][0] +
338 sv[3].value(chi) * hansenRoot[i - 1][3] +
339 sv[2].value(chi) * hansenRoot[i - 1][2] +
340 sv[1].value(chi) * hansenRoot[i - 1][1] +
341 sv[0].value(chi) * hansenRoot[i - 1][0];
342
343 hansenRoot[i][k] = mv[3].value(chi) * hansenRoot[i - 1][3] +
344 mv[2].value(chi) * hansenRoot[i - 1][2] +
345 mv[1].value(chi) * hansenRoot[i - 1][1] +
346 mv[0].value(chi) * hansenRoot[i - 1][0];
347 }
348 }
349 }
350
351
352
353
354
355
356
357
358 public double getValue(final int mnm1, final double chi) {
359
360 final int n = -mnm1 - 1;
361
362
363 int sliceNo = (n + N0 + 4) / SLICE;
364 if (sliceNo < numSlices) {
365
366 final int indexInSlice = (n + N0 + 4) % SLICE;
367
368
369 if (indexInSlice <= 3) {
370 return hansenRoot[sliceNo][indexInSlice];
371 }
372 } else {
373
374
375 sliceNo--;
376 }
377
378
379
380 final PolynomialFunction[] v = mpvec[mnm1 + offset];
381 return v[3].value(chi) * hansenRoot[sliceNo][3] +
382 v[2].value(chi) * hansenRoot[sliceNo][2] +
383 v[1].value(chi) * hansenRoot[sliceNo][1] +
384 v[0].value(chi) * hansenRoot[sliceNo][0];
385
386 }
387
388
389
390
391
392
393
394
395 public double getDerivative(final int mnm1, final double chi) {
396
397
398 final int n = -mnm1 - 1;
399
400
401 int sliceNo = (n + N0 + 4) / SLICE;
402 if (sliceNo < numSlices) {
403
404 final int indexInSlice = (n + N0 + 4) % SLICE;
405
406
407 if (indexInSlice <= 3) {
408 return hansenDerivRoot[sliceNo][indexInSlice];
409 }
410 } else {
411
412
413 sliceNo--;
414 }
415
416
417
418 final PolynomialFunction[] v = mpvec[mnm1 + this.offset];
419 final PolynomialFunction[] vv = mpvecDeriv[mnm1 + this.offset];
420
421 return v[3].value(chi) * hansenDerivRoot[sliceNo][3] +
422 v[2].value(chi) * hansenDerivRoot[sliceNo][2] +
423 v[1].value(chi) * hansenDerivRoot[sliceNo][1] +
424 v[0].value(chi) * hansenDerivRoot[sliceNo][0] +
425 vv[3].value(chi) * hansenRoot[sliceNo][3] +
426 vv[2].value(chi) * hansenRoot[sliceNo][2] +
427 vv[1].value(chi) * hansenRoot[sliceNo][1] +
428 vv[0].value(chi) * hansenRoot[sliceNo][0];
429
430 }
431
432
433
434
435
436
437
438
439
440
441 private static class HansenCoefficientsBySeries {
442
443
444 private final int mnm1;
445
446
447 private final int s;
448
449
450 private final int j;
451
452
453 private final int maxNewcomb;
454
455
456 private PolynomialFunction polynomial;
457
458
459
460
461
462
463
464
465
466 public HansenCoefficientsBySeries(final int mnm1, final int s,
467 final int j, final int maxHansen) {
468 this.mnm1 = mnm1;
469 this.s = s;
470 this.j = j;
471 this.maxNewcomb = maxHansen;
472 this.polynomial = generatePolynomial();
473 }
474
475
476
477
478
479
480
481
482
483
484
485 public DerivativeStructure getValue(final double e2, final double chi, final double chi2) {
486
487
488 final DerivativeStructure serie = polynomial.value(
489 new DerivativeStructure(1, 1, 0, e2));
490
491 final double value = FastMath.pow(chi2, -mnm1 - 1) * serie.getValue() / chi;
492 final double coef = -(mnm1 + 1.5);
493 final double derivative = coef * chi2 * value +
494 FastMath.pow(chi2, -mnm1 - 1) * serie.getPartialDerivative(1) / chi;
495 return new DerivativeStructure(1, 1, value, derivative);
496 }
497
498
499
500
501
502
503
504
505
506
507 private PolynomialFunction generatePolynomial() {
508
509 final int aHT = FastMath.max(j - s, 0);
510 final int bHT = FastMath.max(s - j, 0);
511
512 final double[] coefficients = new double[maxNewcomb + 1];
513
514
515 for (int alphaHT = 0; alphaHT <= maxNewcomb; alphaHT++) {
516 coefficients[alphaHT] =
517 NewcombOperators.getValue(alphaHT + aHT, alphaHT + bHT, mnm1, s);
518 }
519
520
521 return new PolynomialFunction(coefficients);
522 }
523 }
524
525 }