1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.hipparchus.ode.nonstiff;
19
20 import org.hipparchus.ode.EquationsMapper;
21 import org.hipparchus.ode.ODEStateAndDerivative;
22 import org.hipparchus.ode.sampling.AbstractODEStateInterpolator;
23 import org.hipparchus.util.FastMath;
24
25
26
27
28
29
30
31
32
33
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
68
69
70
71 class GraggBulirschStoerStateInterpolator
72 extends AbstractODEStateInterpolator {
73
74
75 private static final long serialVersionUID = 20160329L;
76
77
78
79
80 private final double[][] yMidDots;
81
82
83 private final double[][] polynomials;
84
85
86 private final double[] errfac;
87
88
89 private final int currentDegree;
90
91
92
93
94
95
96
97
98
99
100
101
102 GraggBulirschStoerStateInterpolator(final boolean forward,
103 final ODEStateAndDerivative globalPreviousState,
104 final ODEStateAndDerivative globalCurrentState,
105 final ODEStateAndDerivative softPreviousState,
106 final ODEStateAndDerivative softCurrentState,
107 final EquationsMapper mapper,
108 final double[][] yMidDots,
109 final int mu) {
110 super(forward,
111 globalPreviousState, globalCurrentState, softPreviousState, softCurrentState,
112 mapper);
113
114 this.yMidDots = yMidDots.clone();
115 this.currentDegree = mu + 4;
116 this.polynomials = new double[currentDegree + 1][getCurrentState().getCompleteStateDimension()];
117
118
119 if (currentDegree <= 4) {
120 errfac = null;
121 } else {
122 errfac = new double[currentDegree - 4];
123 for (int i = 0; i < errfac.length; ++i) {
124 final int ip5 = i + 5;
125 errfac[i] = 1.0 / (ip5 * ip5);
126 final double e = 0.5 * FastMath.sqrt (((double) (i + 1)) / ip5);
127 for (int j = 0; j <= i; ++j) {
128 errfac[i] *= e / (j + 1);
129 }
130 }
131 }
132
133
134 computeCoefficients(mu);
135
136 }
137
138
139 @Override
140 protected GraggBulirschStoerStateInterpolator create(final boolean newForward,
141 final ODEStateAndDerivative newGlobalPreviousState,
142 final ODEStateAndDerivative newGlobalCurrentState,
143 final ODEStateAndDerivative newSoftPreviousState,
144 final ODEStateAndDerivative newSoftCurrentState,
145 final EquationsMapper newMapper) {
146 return new GraggBulirschStoerStateInterpolator(newForward,
147 newGlobalPreviousState, newGlobalCurrentState,
148 newSoftPreviousState, newSoftCurrentState,
149 newMapper, yMidDots, currentDegree - 4);
150 }
151
152
153
154
155 private void computeCoefficients(final int mu) {
156
157 final double[] y0Dot = getGlobalPreviousState().getCompleteDerivative();
158 final double[] y1Dot = getGlobalCurrentState().getCompleteDerivative();
159 final double[] y1 = getGlobalCurrentState().getCompleteState();
160
161 final double[] previousState = getGlobalPreviousState().getCompleteState();
162 final double h = getGlobalCurrentState().getTime() - getGlobalPreviousState().getTime();
163 for (int i = 0; i < previousState.length; ++i) {
164
165 final double yp0 = h * y0Dot[i];
166 final double yp1 = h * y1Dot[i];
167 final double ydiff = y1[i] - previousState[i];
168 final double aspl = ydiff - yp1;
169 final double bspl = yp0 - ydiff;
170
171 polynomials[0][i] = previousState[i];
172 polynomials[1][i] = ydiff;
173 polynomials[2][i] = aspl;
174 polynomials[3][i] = bspl;
175
176 if (mu < 0) {
177 return;
178 }
179
180
181 final double ph0 = 0.5 * (previousState[i] + y1[i]) + 0.125 * (aspl + bspl);
182 polynomials[4][i] = 16 * (yMidDots[0][i] - ph0);
183
184 if (mu > 0) {
185 final double ph1 = ydiff + 0.25 * (aspl - bspl);
186 polynomials[5][i] = 16 * (yMidDots[1][i] - ph1);
187
188 if (mu > 1) {
189 final double ph2 = yp1 - yp0;
190 polynomials[6][i] = 16 * (yMidDots[2][i] - ph2 + polynomials[4][i]);
191
192 if (mu > 2) {
193 final double ph3 = 6 * (bspl - aspl);
194 polynomials[7][i] = 16 * (yMidDots[3][i] - ph3 + 3 * polynomials[5][i]);
195
196 for (int j = 4; j <= mu; ++j) {
197 final double fac1 = 0.5 * j * (j - 1);
198 final double fac2 = 2 * fac1 * (j - 2) * (j - 3);
199 polynomials[j+4][i] =
200 16 * (yMidDots[j][i] + fac1 * polynomials[j+2][i] - fac2 * polynomials[j][i]);
201 }
202
203 }
204 }
205 }
206 }
207
208 }
209
210
211
212
213
214 public double estimateError(final double[] scale) {
215 double error = 0;
216 if (currentDegree >= 5) {
217 for (int i = 0; i < scale.length; ++i) {
218 final double e = polynomials[currentDegree][i] / scale[i];
219 error += e * e;
220 }
221 error = FastMath.sqrt(error / scale.length) * errfac[currentDegree - 5];
222 }
223 return error;
224 }
225
226
227 @Override
228 protected ODEStateAndDerivative computeInterpolatedStateAndDerivatives(final EquationsMapper mapper,
229 final double time, final double theta,
230 final double thetaH, final double oneMinusThetaH) {
231
232 final int dimension = mapper.getTotalDimension();
233
234 final double h = thetaH / theta;
235 final double oneMinusTheta = 1.0 - theta;
236 final double theta05 = theta - 0.5;
237 final double tOmT = theta * oneMinusTheta;
238 final double t4 = tOmT * tOmT;
239 final double t4Dot = 2 * tOmT * (1 - 2 * theta);
240 final double dot1 = 1.0 / h;
241 final double dot2 = theta * (2 - 3 * theta) / h;
242 final double dot3 = ((3 * theta - 4) * theta + 1) / h;
243
244 final double[] interpolatedState = new double[dimension];
245 final double[] interpolatedDerivatives = new double[dimension];
246 for (int i = 0; i < dimension; ++i) {
247
248 final double p0 = polynomials[0][i];
249 final double p1 = polynomials[1][i];
250 final double p2 = polynomials[2][i];
251 final double p3 = polynomials[3][i];
252 interpolatedState[i] = p0 + theta * (p1 + oneMinusTheta * (p2 * theta + p3 * oneMinusTheta));
253 interpolatedDerivatives[i] = dot1 * p1 + dot2 * p2 + dot3 * p3;
254
255 if (currentDegree > 3) {
256 double cDot = 0;
257 double c = polynomials[currentDegree][i];
258 for (int j = currentDegree - 1; j > 3; --j) {
259 final double d = 1.0 / (j - 3);
260 cDot = d * (theta05 * cDot + c);
261 c = polynomials[j][i] + c * d * theta05;
262 }
263 interpolatedState[i] += t4 * c;
264 interpolatedDerivatives[i] += (t4 * cDot + t4Dot * c) / h;
265 }
266
267 }
268
269 if (h == 0) {
270
271
272 System.arraycopy(yMidDots[1], 0, interpolatedDerivatives, 0, dimension);
273 }
274
275 return mapper.mapStateAndDerivative(time, interpolatedState, interpolatedDerivatives);
276
277 }
278
279 }