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