1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math.ode;
19
20 import java.io.ObjectInput;
21 import java.io.ObjectOutput;
22 import java.io.IOException;
23
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
72
73
74 class GraggBulirschStoerStepInterpolator
75 extends AbstractStepInterpolator {
76
77
78 private double[] y0Dot;
79
80
81 private double[] y1;
82
83
84 private double[] y1Dot;
85
86
87
88
89 private double[][] yMidDots;
90
91
92 private double[][] polynoms;
93
94
95 private double[] errfac;
96
97
98 private int currentDegree;
99
100
101
102
103
104
105 private void resetTables(int maxDegree) {
106
107 if (maxDegree < 0) {
108 polynoms = null;
109 errfac = null;
110 currentDegree = -1;
111 } else {
112
113 double[][] newPols = new double[maxDegree + 1][];
114 if (polynoms != null) {
115 System.arraycopy(polynoms, 0, newPols, 0, polynoms.length);
116 for (int i = polynoms.length; i < newPols.length; ++i) {
117 newPols[i] = new double[currentState.length];
118 }
119 } else {
120 for (int i = 0; i < newPols.length; ++i) {
121 newPols[i] = new double[currentState.length];
122 }
123 }
124 polynoms = newPols;
125
126
127 if (maxDegree <= 4) {
128 errfac = null;
129 } else {
130 errfac = new double[maxDegree - 4];
131 for (int i = 0; i < errfac.length; ++i) {
132 int ip5 = i + 5;
133 errfac[i] = 1.0 / (ip5 * ip5);
134 double e = 0.5 * Math.sqrt (((double) (i + 1)) / ip5);
135 for (int j = 0; j <= i; ++j) {
136 errfac[i] *= e / (j + 1);
137 }
138 }
139 }
140
141 currentDegree = 0;
142
143 }
144
145 }
146
147
148
149
150
151 public GraggBulirschStoerStepInterpolator() {
152 y0Dot = null;
153 y1 = null;
154 y1Dot = null;
155 yMidDots = null;
156 resetTables(-1);
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171 public GraggBulirschStoerStepInterpolator(double[] y, double[] y0Dot,
172 double[] y1, double[] y1Dot,
173 double[][] yMidDots,
174 boolean forward) {
175
176 super(y, forward);
177 this.y0Dot = y0Dot;
178 this.y1 = y1;
179 this.y1Dot = y1Dot;
180 this.yMidDots = yMidDots;
181
182 resetTables(yMidDots.length + 4);
183
184 }
185
186
187
188
189
190
191 public GraggBulirschStoerStepInterpolator
192 (GraggBulirschStoerStepInterpolator interpolator) {
193
194 super(interpolator);
195
196 int dimension = currentState.length;
197
198
199
200 y0Dot = null;
201 y1 = null;
202 y1Dot = null;
203 yMidDots = null;
204
205
206 if (interpolator.polynoms == null) {
207 polynoms = null;
208 currentDegree = -1;
209 } else {
210 resetTables(interpolator.currentDegree);
211 for (int i = 0; i < polynoms.length; ++i) {
212 polynoms[i] = new double[dimension];
213 System.arraycopy(interpolator.polynoms[i], 0,
214 polynoms[i], 0, dimension);
215 }
216 currentDegree = interpolator.currentDegree;
217 }
218
219 }
220
221
222
223
224 protected StepInterpolator doCopy() {
225 return new GraggBulirschStoerStepInterpolator(this);
226 }
227
228
229
230
231
232
233 public void computeCoefficients(int mu, double h) {
234
235 if ((polynoms == null) || (polynoms.length <= (mu + 4))) {
236 resetTables(mu + 4);
237 }
238
239 currentDegree = mu + 4;
240
241 for (int i = 0; i < currentState.length; ++i) {
242
243 double yp0 = h * y0Dot[i];
244 double yp1 = h * y1Dot[i];
245 double ydiff = y1[i] - currentState[i];
246 double aspl = ydiff - yp1;
247 double bspl = yp0 - ydiff;
248
249 polynoms[0][i] = currentState[i];
250 polynoms[1][i] = ydiff;
251 polynoms[2][i] = aspl;
252 polynoms[3][i] = bspl;
253
254 if (mu < 0) {
255 return;
256 }
257
258
259 double ph0 = 0.5 * (currentState[i] + y1[i]) + 0.125 * (aspl + bspl);
260 polynoms[4][i] = 16 * (yMidDots[0][i] - ph0);
261
262 if (mu > 0) {
263 double ph1 = ydiff + 0.25 * (aspl - bspl);
264 polynoms[5][i] = 16 * (yMidDots[1][i] - ph1);
265
266 if (mu > 1) {
267 double ph2 = yp1 - yp0;
268 polynoms[6][i] = 16 * (yMidDots[2][i] - ph2 + polynoms[4][i]);
269
270 if (mu > 2) {
271 double ph3 = 6 * (bspl - aspl);
272 polynoms[7][i] = 16 * (yMidDots[3][i] - ph3 + 3 * polynoms[5][i]);
273
274 for (int j = 4; j <= mu; ++j) {
275 double fac1 = 0.5 * j * (j - 1);
276 double fac2 = 2 * fac1 * (j - 2) * (j - 3);
277 polynoms[j+4][i] =
278 16 * (yMidDots[j][i] + fac1 * polynoms[j+2][i] - fac2 * polynoms[j][i]);
279 }
280
281 }
282 }
283 }
284 }
285
286 }
287
288
289
290
291
292 public double estimateError(double[] scale) {
293 double error = 0;
294 if (currentDegree >= 5) {
295 for (int i = 0; i < currentState.length; ++i) {
296 double e = polynoms[currentDegree][i] / scale[i];
297 error += e * e;
298 }
299 error = Math.sqrt(error / currentState.length) * errfac[currentDegree-5];
300 }
301 return error;
302 }
303
304
305
306
307
308
309
310
311
312
313
314 protected void computeInterpolatedState(double theta,
315 double oneMinusThetaH)
316 throws DerivativeException {
317
318 int dimension = currentState.length;
319
320 double oneMinusTheta = 1.0 - theta;
321 double theta05 = theta - 0.5;
322 double t4 = theta * oneMinusTheta;
323 t4 = t4 * t4;
324
325 for (int i = 0; i < dimension; ++i) {
326 interpolatedState[i] = polynoms[0][i] +
327 theta * (polynoms[1][i] +
328 oneMinusTheta * (polynoms[2][i] * theta +
329 polynoms[3][i] * oneMinusTheta));
330
331 if (currentDegree > 3) {
332 double c = polynoms[currentDegree][i];
333 for (int j = currentDegree - 1; j > 3; --j) {
334 c = polynoms[j][i] + c * theta05 / (j - 3);
335 }
336 interpolatedState[i] += t4 * c;
337 }
338 }
339
340 }
341
342
343
344
345
346 public void writeExternal(ObjectOutput out)
347 throws IOException {
348
349 int dimension = currentState.length;
350
351
352 writeBaseExternal(out);
353
354
355 out.writeInt(currentDegree);
356 for (int k = 0; k <= currentDegree; ++k) {
357 for (int l = 0; l < dimension; ++l) {
358 out.writeDouble(polynoms[k][l]);
359 }
360 }
361
362 }
363
364
365
366
367
368 public void readExternal(ObjectInput in)
369 throws IOException {
370
371
372 double t = readBaseExternal(in);
373 int dimension = currentState.length;
374
375
376 int degree = in.readInt();
377 resetTables(degree);
378 currentDegree = degree;
379
380 for (int k = 0; k <= currentDegree; ++k) {
381 for (int l = 0; l < dimension; ++l) {
382 polynoms[k][l] = in.readDouble();
383 }
384 }
385
386 try {
387
388 setInterpolatedTime(t);
389 } catch (DerivativeException e) {
390 throw new IOException(e.getMessage());
391 }
392
393 }
394
395
396 private static final long serialVersionUID = 7320613236731409847L;
397
398 }