1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.numerical.cr3bp;
18
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.stream.Stream;
22
23 import org.hipparchus.Field;
24 import org.hipparchus.CalculusFieldElement;
25 import org.hipparchus.analysis.differentiation.DSFactory;
26 import org.hipparchus.analysis.differentiation.DerivativeStructure;
27 import org.hipparchus.analysis.differentiation.FDSFactory;
28 import org.hipparchus.analysis.differentiation.FieldDerivativeStructure;
29 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
30 import org.hipparchus.geometry.euclidean.threed.Vector3D;
31 import org.hipparchus.util.FastMath;
32 import org.orekit.bodies.CR3BPSystem;
33 import org.orekit.forces.AbstractForceModel;
34 import org.orekit.propagation.FieldSpacecraftState;
35 import org.orekit.propagation.SpacecraftState;
36 import org.orekit.propagation.events.EventDetector;
37 import org.orekit.propagation.events.FieldEventDetector;
38 import org.orekit.utils.ParameterDriver;
39
40
41
42
43
44
45 public class CR3BPForceModel extends AbstractForceModel {
46
47
48 public static final String MASS_RATIO_SUFFIX = "CR3BP System Mass Ratio";
49
50
51
52
53
54
55
56
57 private static final double MU_SCALE = FastMath.scalb(1.0, 32);
58
59
60 private final ParameterDriver muParameterDriver;
61
62
63
64
65 public CR3BPForceModel(final CR3BPSystem cr3bp) {
66 muParameterDriver = new ParameterDriver(cr3bp.getName() + MASS_RATIO_SUFFIX,
67 cr3bp.getMassRatio(), MU_SCALE, 0.0,
68 Double.POSITIVE_INFINITY);
69 }
70
71
72 public Vector3D acceleration(final SpacecraftState s,
73 final double[] parameters) {
74
75
76 final double vx = s.getPVCoordinates().getVelocity().getX();
77 final double vy = s.getPVCoordinates().getVelocity().getY();
78
79
80 final DerivativeStructure potential = getPotential(s);
81
82
83 final double[] dU = potential.getAllDerivatives();
84
85
86 final int idX = potential.getFactory().getCompiler().getPartialDerivativeIndex(1, 0, 0);
87 final int idY = potential.getFactory().getCompiler().getPartialDerivativeIndex(0, 1, 0);
88 final int idZ = potential.getFactory().getCompiler().getPartialDerivativeIndex(0, 0, 1);
89
90
91 final double accx = dU[idX] + 2.0 * vy;
92 final double accy = dU[idY] - 2.0 * vx;
93 final double accz = dU[idZ];
94
95
96 return new Vector3D(accx, accy, accz);
97
98 }
99
100
101 public <T extends CalculusFieldElement<T>> FieldVector3D<T> acceleration(final FieldSpacecraftState<T> s,
102 final T[] parameters) {
103
104
105 final T vx = s.getPVCoordinates().getVelocity().getX();
106 final T vy = s.getPVCoordinates().getVelocity().getY();
107
108
109 final FieldDerivativeStructure<T> fieldPotential = getPotential(s);
110
111 final T[] dU = fieldPotential.getAllDerivatives();
112
113
114 final int idX = fieldPotential.getFactory().getCompiler().getPartialDerivativeIndex(1, 0, 0);
115 final int idY = fieldPotential.getFactory().getCompiler().getPartialDerivativeIndex(0, 1, 0);
116 final int idZ = fieldPotential.getFactory().getCompiler().getPartialDerivativeIndex(0, 0, 1);
117
118
119 final T accx = dU[idX].add(vy.multiply(2.0));
120 final T accy = dU[idY].subtract(vx.multiply(2.0));
121 final T accz = dU[idZ];
122
123
124 return new FieldVector3D<>(accx, accy, accz);
125
126 }
127
128
129
130
131
132
133 public DerivativeStructure getPotential(final SpacecraftState s) {
134
135
136 final double x = s.getPVCoordinates().getPosition().getX();
137 final double y = s.getPVCoordinates().getPosition().getY();
138 final double z = s.getPVCoordinates().getPosition().getZ();
139
140 final DSFactory factoryP = new DSFactory(3, 2);
141 final DerivativeStructure fpx = factoryP.variable(0, x);
142 final DerivativeStructure fpy = factoryP.variable(1, y);
143 final DerivativeStructure fpz = factoryP.variable(2, z);
144
145 final DerivativeStructure zero = fpx.getField().getZero();
146
147
148 final DerivativeStructure mu = zero.add(muParameterDriver.getValue());
149
150
151 final DerivativeStructure d1 = mu;
152 final DerivativeStructure d2 = mu.negate().add(1.0);
153
154
155 final DerivativeStructure r1 =
156 FastMath.sqrt((fpx.add(d1)).multiply(fpx.add(d1)).add(fpy.multiply(fpy))
157 .add(fpz.multiply(fpz)));
158
159
160 final DerivativeStructure r2 =
161 FastMath.sqrt((fpx.subtract(d2)).multiply(fpx.subtract(d2))
162 .add(fpy.multiply(fpy)).add(fpz.multiply(fpz)));
163
164
165 return (mu.negate().add(1.0).divide(r1)).add(mu.divide(r2))
166 .add(fpx.multiply(fpx).add(fpy.multiply(fpy)).multiply(0.5)).add(d1.multiply(d2).multiply(0.5));
167 }
168
169
170
171
172
173
174
175 public <T extends CalculusFieldElement<T>> FieldDerivativeStructure<T> getPotential(final FieldSpacecraftState<T> s) {
176
177
178 final T x = s.getPVCoordinates().getPosition().getX();
179 final T y = s.getPVCoordinates().getPosition().getY();
180 final T z = s.getPVCoordinates().getPosition().getZ();
181
182 final FDSFactory<T> factoryP = new FDSFactory<>(s.getDate().getField(), 3, 2);
183 final FieldDerivativeStructure<T> fpx = factoryP.variable(0, x);
184 final FieldDerivativeStructure<T> fpy = factoryP.variable(1, y);
185 final FieldDerivativeStructure<T> fpz = factoryP.variable(2, z);
186 final FieldDerivativeStructure<T> zero = fpx.getField().getZero();
187
188
189 final FieldDerivativeStructure<T> mu = zero.add(muParameterDriver.getValue());
190
191
192 final FieldDerivativeStructure<T> d1 = mu;
193 final FieldDerivativeStructure<T> d2 = mu.negate().add(1.0);
194
195
196 final FieldDerivativeStructure<T> r1 =
197 FastMath.sqrt((fpx.add(d1)).multiply(fpx.add(d1)).add(fpy.multiply(fpy))
198 .add(fpz.multiply(fpz)));
199
200
201 final FieldDerivativeStructure<T> r2 =
202 FastMath.sqrt((fpx.subtract(d2)).multiply(fpx.subtract(d2))
203 .add(fpy.multiply(fpy)).add(fpz.multiply(fpz)));
204
205
206 return (mu.negate().add(1.0).divide(r1)).add(mu.divide(r2))
207 .add(fpx.multiply(fpx).add(fpy.multiply(fpy)).multiply(0.5)).add(d1.multiply(d2).multiply(0.5));
208 }
209
210
211 public Stream<EventDetector> getEventsDetectors() {
212 return Stream.empty();
213 }
214
215 @Override
216
217 public <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventsDetectors(final Field<T> field) {
218 return Stream.empty();
219 }
220
221
222 public List<ParameterDriver> getParametersDrivers() {
223 return Collections.singletonList(muParameterDriver);
224 }
225
226
227 public boolean dependsOnPositionOnly() {
228 return true;
229 }
230 }