1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.forces.gravity;
18
19
20 import org.hipparchus.dfp.Dfp;
21 import org.hipparchus.dfp.DfpField;
22 import org.hipparchus.dfp.DfpMath;
23 import org.hipparchus.geometry.euclidean.threed.Vector3D;
24 import org.hipparchus.util.FastMath;
25 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider;
26 import org.orekit.forces.gravity.potential.NormalizedSphericalHarmonicsProvider.NormalizedSphericalHarmonics;
27 import org.orekit.forces.gravity.potential.RawSphericalHarmonicsProvider;
28 import org.orekit.forces.gravity.potential.RawSphericalHarmonicsProvider.RawSphericalHarmonics;
29 import org.orekit.forces.gravity.potential.SphericalHarmonicsProvider;
30 import org.orekit.forces.gravity.potential.TideSystem;
31 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
32 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
33 import org.orekit.time.AbsoluteDate;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 class ReferenceFieldModel {
68
69 private final DfpField dfpField;
70 private final SphericalHarmonicsProvider provider;
71 private final AssociatedLegendreFunction[][] alf;
72
73 public ReferenceFieldModel(NormalizedSphericalHarmonicsProvider provider, int digits) {
74 this.dfpField = new DfpField(digits);
75 this.provider = provider;
76 this.alf = createAlf(provider.getMaxDegree(), provider.getMaxOrder(), true, dfpField);
77 }
78
79 public ReferenceFieldModel(UnnormalizedSphericalHarmonicsProvider provider, int digits) {
80 this.dfpField = new DfpField(digits);
81 this.provider = provider;
82 this.alf = createAlf(provider.getMaxDegree(), provider.getMaxOrder(), false, dfpField);
83 }
84
85 private static AssociatedLegendreFunction[][] createAlf(int degree, int order, boolean isNormalized,
86 DfpField dfpField) {
87 AssociatedLegendreFunction[][] alf = new AssociatedLegendreFunction[degree + 1][];
88 for (int n = 2; n < alf.length; ++n) {
89 alf[n] = new AssociatedLegendreFunction[FastMath.min(n, order) + 1];
90 for (int m = 0; m < alf[n].length; ++m) {
91 alf[n][m] = new AssociatedLegendreFunction(true, n, m, dfpField);
92 }
93 }
94 return alf;
95 }
96
97 public Dfp nonCentralPart(final AbsoluteDate date, final Vector3D position)
98 {
99
100 int degree = provider.getMaxDegree();
101 int order = provider.getMaxOrder();
102
103 final RawSphericalHarmonics harmonics = raw(provider).onDate(date);
104
105 Dfp x = dfpField.newDfp(position.getX());
106 Dfp y = dfpField.newDfp(position.getY());
107 Dfp z = dfpField.newDfp(position.getZ());
108
109 Dfp rho2 = x.square().add(y.square());
110 Dfp rho = rho2.sqrt();
111 Dfp r2 = rho2.add(z.square());
112 Dfp r = r2.sqrt();
113 Dfp aOr = dfpField.newDfp(provider.getAe()).divide(r);
114 Dfp lambda = position.getX() > 0 ?
115 dfpField.getTwo().multiply(DfpMath.atan(y.divide(rho.add(x)))) :
116 dfpField.getPi().subtract(dfpField.getTwo().multiply(DfpMath.atan(y.divide(rho.subtract(x)))));
117 Dfp cosTheta = z.divide(r);
118
119 Dfp value = dfpField.getZero();
120 Dfp aOrN = aOr;
121 for (int n = 2; n <= degree; ++n) {
122 Dfp sum = dfpField.getZero();
123 for (int m = 0; m <= FastMath.min(n, order); ++m) {
124 double cnm = harmonics.getRawCnm(n, m);
125 double snm = harmonics.getRawSnm(n, m);
126 Dfp mLambda = lambda.multiply(m);
127 Dfp c = DfpMath.cos(mLambda).multiply(dfpField.newDfp(cnm));
128 Dfp s = DfpMath.sin(mLambda).multiply(dfpField.newDfp(snm));
129 Dfp pnm = alf[n][m].value(cosTheta);
130 sum = sum.add(pnm.multiply(c.add(s)));
131 }
132 aOrN = aOrN.multiply(aOr);
133 value = value.add(aOrN.multiply(sum));
134 }
135
136 return value.multiply(dfpField.newDfp(provider.getMu())).divide(r);
137
138 }
139
140
141
142
143
144
145
146
147 private RawSphericalHarmonicsProvider raw(final SphericalHarmonicsProvider provider) {
148 if (provider instanceof RawSphericalHarmonicsProvider) {
149 return (RawSphericalHarmonicsProvider) provider;
150 } else if (provider instanceof NormalizedSphericalHarmonicsProvider) {
151 return new RawerSphericalHarmonicsProvider(provider) {
152 @Override
153 public RawSphericalHarmonics onDate(final AbsoluteDate date)
154 {
155 final NormalizedSphericalHarmonics normalized =
156 ((NormalizedSphericalHarmonicsProvider) provider).onDate(date);
157 return new RawSphericalHarmonics() {
158 @Override
159 public double getRawCnm(int n, int m) {
160 return normalized.getNormalizedCnm(n, m);
161 }
162
163 @Override
164 public double getRawSnm(int n, int m) {
165 return normalized.getNormalizedSnm(n, m);
166 }
167
168 @Override
169 public AbsoluteDate getDate() {
170 return date;
171 }
172 };
173 }
174 };
175 } else if (provider instanceof UnnormalizedSphericalHarmonicsProvider) {
176 return new RawerSphericalHarmonicsProvider(provider) {
177 @Override
178 public RawSphericalHarmonics onDate(final AbsoluteDate date)
179 {
180 final UnnormalizedSphericalHarmonics unnormalized =
181 ((UnnormalizedSphericalHarmonicsProvider) provider).onDate(date);
182 return new RawSphericalHarmonics() {
183 @Override
184 public double getRawCnm(int n, int m) {
185 return unnormalized.getUnnormalizedCnm(n, m);
186 }
187
188 @Override
189 public double getRawSnm(int n, int m) {
190 return unnormalized.getUnnormalizedSnm(n, m);
191 }
192
193 @Override
194 public AbsoluteDate getDate() {
195 return date;
196 }
197 };
198 }
199 };
200 } else {
201 throw new RuntimeException("Unknown harmonics provider type: " + provider);
202 }
203 }
204
205
206 public static abstract class RawerSphericalHarmonicsProvider
207 implements RawSphericalHarmonicsProvider {
208
209
210 private final SphericalHarmonicsProvider provider;
211
212
213
214
215
216
217 public RawerSphericalHarmonicsProvider(SphericalHarmonicsProvider provider) {
218 this.provider = provider;
219 }
220
221 public int getMaxDegree() {
222 return provider.getMaxDegree();
223 }
224
225 public int getMaxOrder() {
226 return provider.getMaxOrder();
227 }
228
229 public double getMu() {
230 return provider.getMu();
231 }
232
233 public double getAe() {
234 return provider.getAe();
235 }
236
237 public AbsoluteDate getReferenceDate() {
238 return provider.getReferenceDate();
239 }
240
241 public TideSystem getTideSystem() {
242 return provider.getTideSystem();
243 }
244 }
245 }