1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.semianalytical.dsst.forces;
18
19 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
20 import org.apache.commons.math3.util.FastMath;
21 import org.apache.commons.math3.util.MathUtils;
22 import org.apache.commons.math3.util.Precision;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.forces.SphericalSpacecraft;
25 import org.orekit.forces.radiation.RadiationSensitive;
26 import org.orekit.forces.radiation.SolarRadiationPressure;
27 import org.orekit.propagation.SpacecraftState;
28 import org.orekit.propagation.events.EventDetector;
29 import org.orekit.utils.PVCoordinatesProvider;
30
31
32
33
34
35
36
37
38
39
40
41 public class DSSTSolarRadiationPressure extends AbstractGaussianContribution {
42
43
44 private static final double D_REF = 149597870000.0;
45
46
47 private static final double P_REF = 4.56e-6;
48
49
50 private static final double GAUSS_THRESHOLD = 1.0e-15;
51
52
53 private static final double S_ZERO = 1.0e-6;
54
55
56 private final PVCoordinatesProvider sun;
57
58
59 private final double ae;
60
61
62 private final RadiationSensitive spacecraft;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public DSSTSolarRadiationPressure(final double cr, final double area,
84 final PVCoordinatesProvider sun,
85 final double equatorialRadius) {
86 this(D_REF, P_REF, cr, area, sun, equatorialRadius);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 public DSSTSolarRadiationPressure(final PVCoordinatesProvider sun,
104 final double equatorialRadius,
105 final RadiationSensitive spacecraft) {
106 this(D_REF, P_REF, sun, equatorialRadius, spacecraft);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public DSSTSolarRadiationPressure(final double dRef, final double pRef,
126 final double cr, final double area,
127 final PVCoordinatesProvider sun,
128 final double equatorialRadius) {
129
130
131
132
133
134 this(dRef, pRef, sun, equatorialRadius, new SphericalSpacecraft(
135 area, 0.0, 0.0, 3.25 - 2.25 * cr));
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public DSSTSolarRadiationPressure(final double dRef, final double pRef,
154 final PVCoordinatesProvider sun, final double equatorialRadius,
155 final RadiationSensitive spacecraft) {
156
157
158 super(GAUSS_THRESHOLD, new SolarRadiationPressure(
159 dRef, pRef, sun, equatorialRadius, spacecraft));
160
161 this.sun = sun;
162 this.ae = equatorialRadius;
163 this.spacecraft = spacecraft;
164 }
165
166
167
168
169 public RadiationSensitive getSpacecraft() {
170 return spacecraft;
171 }
172
173
174 public EventDetector[] getEventsDetectors() {
175
176 return null;
177 }
178
179
180 protected double[] getLLimits(final SpacecraftState state) throws OrekitException {
181
182 final double[] ll = {-FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0),
183 FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0)};
184
185
186 final Vector3D sunDir = sun.getPVCoordinates(state.getDate(), state.getFrame()).getPosition().normalize();
187 final double alpha = sunDir.dotProduct(f);
188 final double beta = sunDir.dotProduct(g);
189 final double gamma = sunDir.dotProduct(w);
190
191
192 if (FastMath.abs(gamma * a * (1. - ecc)) < ae) {
193
194
195 final double bet2 = beta * beta;
196 final double h2 = h * h;
197 final double k2 = k * k;
198 final double m = ae / (a * B);
199 final double m2 = m * m;
200 final double m4 = m2 * m2;
201 final double bb = alpha * beta + m2 * h * k;
202 final double b2 = bb * bb;
203 final double cc = alpha * alpha - bet2 + m2 * (k2 - h2);
204 final double dd = 1. - bet2 - m2 * (1. + h2);
205 final double[] a = new double[5];
206 a[0] = 4. * b2 + cc * cc;
207 a[1] = 8. * bb * m2 * h + 4. * cc * m2 * k;
208 a[2] = -4. * b2 + 4. * m4 * h2 - 2. * cc * dd + 4. * m4 * k2;
209 a[3] = -8. * bb * m2 * h - 4. * dd * m2 * k;
210 a[4] = -4. * m4 * h2 + dd * dd;
211
212 final double[] roots = new double[4];
213 final int nbRoots = realQuarticRoots(a, roots);
214 if (nbRoots > 0) {
215
216 boolean entryFound = false;
217 boolean exitFound = false;
218
219 for (int i = 0; i < nbRoots; i++) {
220 final double cosL = roots[i];
221 final double sL = FastMath.sqrt((1. - cosL) * (1. + cosL));
222
223 for (int j = -1; j <= 1; j += 2) {
224 final double sinL = j * sL;
225 final double cPhi = alpha * cosL + beta * sinL;
226
227 if (cPhi < 0.) {
228 final double range = 1. + k * cosL + h * sinL;
229 final double S = 1. - m2 * range * range - cPhi * cPhi;
230
231 if (FastMath.abs(S) < S_ZERO) {
232
233 final double dSdL = m2 * range * (k * sinL - h * cosL) + cPhi * (alpha * sinL - beta * cosL);
234 if (dSdL > 0.) {
235
236 exitFound = true;
237 ll[0] = FastMath.atan2(sinL, cosL);
238 } else {
239
240 entryFound = true;
241 ll[1] = FastMath.atan2(sinL, cosL);
242 }
243 }
244 }
245 }
246 }
247
248 if (!(entryFound == exitFound)) {
249
250 ll[0] = -FastMath.PI;
251 ll[1] = FastMath.PI;
252 }
253
254 if (ll[0] > ll[1]) {
255
256 if (ll[1] < 0.) {
257 ll[1] += 2. * FastMath.PI;
258 } else {
259 ll[0] -= 2. * FastMath.PI;
260 }
261 }
262 }
263 }
264 return ll;
265 }
266
267
268
269
270 public double getEquatorialRadius() {
271 return ae;
272 }
273
274
275
276
277
278
279
280
281
282
283
284
285 private int realQuarticRoots(final double[] a, final double[] y) {
286
287 if (Precision.equals(a[0], 0.)) {
288 final double[] aa = new double[a.length - 1];
289 System.arraycopy(a, 1, aa, 0, aa.length);
290 return realCubicRoots(aa, y);
291 }
292
293
294 final double b = a[1] / a[0];
295 final double c = a[2] / a[0];
296 final double d = a[3] / a[0];
297 final double e = a[4] / a[0];
298 final double bh = b * 0.5;
299
300
301 final double[] z3 = new double[3];
302 final int i3 = realCubicRoots(new double[] {1.0, -c, b * d - 4. * e, e * (4. * c - b * b) - d * d}, z3);
303 if (i3 == 0) {
304 return 0;
305 }
306
307
308 final double z = z3[0];
309
310
311 final double zh = z * 0.5;
312 final double p = FastMath.max(z + bh * bh - c, 0.);
313 final double q = FastMath.max(zh * zh - e, 0.);
314 final double r = bh * z - d;
315 final double pp = FastMath.sqrt(p);
316 final double qq = FastMath.copySign(FastMath.sqrt(q), r);
317
318
319 final double[] y1 = new double[2];
320 final int n1 = realQuadraticRoots(new double[] {1.0, bh - pp, zh - qq}, y1);
321 final double[] y2 = new double[2];
322 final int n2 = realQuadraticRoots(new double[] {1.0, bh + pp, zh + qq}, y2);
323
324 if (n1 == 2) {
325 if (n2 == 2) {
326 y[0] = y1[0];
327 y[1] = y1[1];
328 y[2] = y2[0];
329 y[3] = y2[1];
330 return 4;
331 } else {
332 y[0] = y1[0];
333 y[1] = y1[1];
334 return 2;
335 }
336 } else {
337 if (n2 == 2) {
338 y[0] = y2[0];
339 y[1] = y2[1];
340 return 2;
341 } else {
342 return 0;
343 }
344 }
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358 private int realCubicRoots(final double[] a, final double[] y) {
359 if (Precision.equals(a[0], 0.)) {
360
361 final double[] aa = new double[a.length - 1];
362 System.arraycopy(a, 1, aa, 0, aa.length);
363 return realQuadraticRoots(aa, y);
364 }
365
366
367 final double b = -a[1] / (3. * a[0]);
368 final double c = a[2] / a[0];
369 final double d = a[3] / a[0];
370 final double b2 = b * b;
371 final double p = b2 - c / 3.;
372 final double q = b * (b2 - c * 0.5) - d * 0.5;
373
374
375 final double disc = p * p * p - q * q;
376
377 if (disc < 0.) {
378
379 final double alpha = q + FastMath.copySign(FastMath.sqrt(-disc), q);
380 final double cbrtAl = FastMath.cbrt(alpha);
381 final double cbrtBe = p / cbrtAl;
382
383 if (p < 0.) {
384 y[0] = b + 2. * q / (cbrtAl * cbrtAl + cbrtBe * cbrtBe - p);
385 } else if (p > 0.) {
386 y[0] = b + cbrtAl + cbrtBe;
387 } else {
388 y[0] = b + cbrtAl;
389 }
390
391 return 1;
392
393 } else if (disc > 0.) {
394
395 final double phi = FastMath.atan2(FastMath.sqrt(disc), q) / 3.;
396 final double sqP = 2.0 * FastMath.sqrt(p);
397
398 y[0] = b + sqP * FastMath.cos(phi);
399 y[1] = b - sqP * FastMath.cos(FastMath.PI / 3. + phi);
400 y[2] = b - sqP * FastMath.cos(FastMath.PI / 3. - phi);
401
402 return 3;
403
404 } else {
405
406 final double cbrtQ = FastMath.cbrt(q);
407 final double root1 = b + 2. * cbrtQ;
408 final double root2 = b - cbrtQ;
409 if (q < 0.) {
410 y[0] = root2;
411 y[1] = root2;
412 y[2] = root1;
413 } else {
414 y[0] = root1;
415 y[1] = root2;
416 y[2] = root2;
417 }
418
419 return 3;
420 }
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434 private int realQuadraticRoots(final double[] a, final double[] y) {
435 if (Precision.equals(a[0], 0.)) {
436
437 if (Precision.equals(a[1], 0.)) {
438
439 return 0;
440 }
441
442 y[0] = -a[2] / a[1];
443 return 1;
444 }
445
446
447 final double b = -0.5 * a[1] / a[0];
448 final double c = a[2] / a[0];
449
450
451 final double d = b * b - c;
452
453 if (d < 0.) {
454
455 return 0;
456 } else if (d > 0.) {
457
458 final double y0 = b + FastMath.copySign(FastMath.sqrt(d), b);
459 final double y1 = c / y0;
460 y[0] = FastMath.max(y0, y1);
461 y[1] = FastMath.min(y0, y1);
462 return 2;
463 } else {
464
465 y[0] = b;
466 y[1] = b;
467 return 2;
468 }
469 }
470 }