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 org.apache.commons.math.ode.DerivativeException;
21 import org.apache.commons.math.ode.FirstOrderIntegrator;
22 import org.apache.commons.math.ode.GraggBulirschStoerIntegrator;
23 import org.apache.commons.math.ode.IntegratorException;
24 import org.apache.commons.math.ode.StepHandler;
25 import org.apache.commons.math.ode.StepInterpolator;
26 import org.apache.commons.math.ode.SwitchingFunction;
27
28 import junit.framework.*;
29
30 public class GraggBulirschStoerIntegratorTest
31 extends TestCase {
32
33 public GraggBulirschStoerIntegratorTest(String name) {
34 super(name);
35 }
36
37 public void testDimensionCheck() {
38 try {
39 TestProblem1 pb = new TestProblem1();
40 AdaptiveStepsizeIntegrator integrator =
41 new GraggBulirschStoerIntegrator(0.0, 1.0, 1.0e-10, 1.0e-10);
42 integrator.integrate(pb,
43 0.0, new double[pb.getDimension()+10],
44 1.0, new double[pb.getDimension()+10]);
45 fail("an exception should have been thrown");
46 } catch(DerivativeException de) {
47 fail("wrong exception caught");
48 } catch(IntegratorException ie) {
49 }
50 }
51
52 public void testNullIntervalCheck() {
53 try {
54 TestProblem1 pb = new TestProblem1();
55 GraggBulirschStoerIntegrator integrator =
56 new GraggBulirschStoerIntegrator(0.0, 1.0, 1.0e-10, 1.0e-10);
57 integrator.integrate(pb,
58 0.0, new double[pb.getDimension()],
59 0.0, new double[pb.getDimension()]);
60 fail("an exception should have been thrown");
61 } catch(DerivativeException de) {
62 fail("wrong exception caught");
63 } catch(IntegratorException ie) {
64 }
65 }
66
67 public void testMinStep()
68 throws DerivativeException, IntegratorException {
69
70 try {
71 TestProblem5 pb = new TestProblem5();
72 double minStep = 0.1 * Math.abs(pb.getFinalTime() - pb.getInitialTime());
73 double maxStep = Math.abs(pb.getFinalTime() - pb.getInitialTime());
74 double[] vecAbsoluteTolerance = { 1.0e-20, 1.0e-21 };
75 double[] vecRelativeTolerance = { 1.0e-20, 1.0e-21 };
76
77 FirstOrderIntegrator integ =
78 new GraggBulirschStoerIntegrator(minStep, maxStep,
79 vecAbsoluteTolerance, vecRelativeTolerance);
80 TestProblemHandler handler = new TestProblemHandler(pb, integ);
81 integ.setStepHandler(handler);
82 integ.integrate(pb,
83 pb.getInitialTime(), pb.getInitialState(),
84 pb.getFinalTime(), new double[pb.getDimension()]);
85 fail("an exception should have been thrown");
86 } catch(DerivativeException de) {
87 fail("wrong exception caught");
88 } catch(IntegratorException ie) {
89 }
90
91 }
92
93 public void testIncreasingTolerance()
94 throws DerivativeException, IntegratorException {
95
96 int previousCalls = Integer.MAX_VALUE;
97 for (int i = -12; i < -4; ++i) {
98 TestProblem1 pb = new TestProblem1();
99 double minStep = 0;
100 double maxStep = pb.getFinalTime() - pb.getInitialTime();
101 double absTolerance = Math.pow(10.0, i);
102 double relTolerance = absTolerance;
103
104 FirstOrderIntegrator integ =
105 new GraggBulirschStoerIntegrator(minStep, maxStep,
106 absTolerance, relTolerance);
107 TestProblemHandler handler = new TestProblemHandler(pb, integ);
108 integ.setStepHandler(handler);
109 integ.integrate(pb,
110 pb.getInitialTime(), pb.getInitialState(),
111 pb.getFinalTime(), new double[pb.getDimension()]);
112
113
114
115
116 double ratio = handler.getMaximalValueError() / absTolerance;
117 assertTrue(ratio < 2.4);
118 assertTrue(ratio > 0.02);
119 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12);
120
121 int calls = pb.getCalls();
122 assertTrue(calls <= previousCalls);
123 previousCalls = calls;
124
125 }
126
127 }
128
129 public void testIntegratorControls()
130 throws DerivativeException, IntegratorException {
131
132 TestProblem3 pb = new TestProblem3(0.999);
133 GraggBulirschStoerIntegrator integ =
134 new GraggBulirschStoerIntegrator(0, pb.getFinalTime() - pb.getInitialTime(),
135 1.0e-8, 1.0e-10);
136
137 double errorWithDefaultSettings = getMaxError(integ, pb);
138
139
140 integ.setStabilityCheck(true, 2, 1, 0.99);
141 assertTrue(errorWithDefaultSettings < getMaxError(integ, pb));
142 integ.setStabilityCheck(true, -1, -1, -1);
143
144 integ.setStepsizeControl(0.5, 0.99, 0.1, 2.5);
145 assertTrue(errorWithDefaultSettings < getMaxError(integ, pb));
146 integ.setStepsizeControl(-1, -1, -1, -1);
147
148 integ.setOrderControl(10, 0.7, 0.95);
149 assertTrue(errorWithDefaultSettings < getMaxError(integ, pb));
150 integ.setOrderControl(-1, -1, -1);
151
152 integ.setInterpolationControl(true, 3);
153 assertTrue(errorWithDefaultSettings < getMaxError(integ, pb));
154 integ.setInterpolationControl(true, -1);
155
156 }
157
158 private double getMaxError(FirstOrderIntegrator integrator, TestProblemAbstract pb)
159 throws DerivativeException, IntegratorException {
160 TestProblemHandler handler = new TestProblemHandler(pb, integrator);
161 integrator.setStepHandler(handler);
162 integrator.integrate(pb,
163 pb.getInitialTime(), pb.getInitialState(),
164 pb.getFinalTime(), new double[pb.getDimension()]);
165 return handler.getMaximalValueError();
166 }
167
168 public void testSwitchingFunctions()
169 throws DerivativeException, IntegratorException {
170
171 TestProblem4 pb = new TestProblem4();
172 double minStep = 0;
173 double maxStep = pb.getFinalTime() - pb.getInitialTime();
174 double scalAbsoluteTolerance = 1.0e-10;
175 double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
176
177 FirstOrderIntegrator integ = new GraggBulirschStoerIntegrator(minStep, maxStep,
178 scalAbsoluteTolerance,
179 scalRelativeTolerance);
180 TestProblemHandler handler = new TestProblemHandler(pb, integ);
181 integ.setStepHandler(handler);
182 SwitchingFunction[] functions = pb.getSwitchingFunctions();
183 for (int l = 0; l < functions.length; ++l) {
184 integ.addSwitchingFunction(functions[l],
185 Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000);
186 }
187 integ.integrate(pb,
188 pb.getInitialTime(), pb.getInitialState(),
189 pb.getFinalTime(), new double[pb.getDimension()]);
190
191 assertTrue(handler.getMaximalValueError() < 5.0e-8);
192 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12);
193 assertEquals(12.0, handler.getLastTime(), 1.0e-8 * maxStep);
194
195 }
196
197 public void testKepler()
198 throws DerivativeException, IntegratorException {
199
200 final TestProblem3 pb = new TestProblem3(0.9);
201 double minStep = 0;
202 double maxStep = pb.getFinalTime() - pb.getInitialTime();
203 double absTolerance = 1.0e-6;
204 double relTolerance = 1.0e-6;
205
206 FirstOrderIntegrator integ =
207 new GraggBulirschStoerIntegrator(minStep, maxStep,
208 absTolerance, relTolerance);
209 integ.setStepHandler(new KeplerStepHandler(pb));
210 integ.integrate(pb,
211 pb.getInitialTime(), pb.getInitialState(),
212 pb.getFinalTime(), new double[pb.getDimension()]);
213
214 assertTrue(pb.getCalls() < 2150);
215
216 }
217
218 public void testVariableSteps()
219 throws DerivativeException, IntegratorException {
220
221 final TestProblem3 pb = new TestProblem3(0.9);
222 double minStep = 0;
223 double maxStep = pb.getFinalTime() - pb.getInitialTime();
224 double absTolerance = 1.0e-8;
225 double relTolerance = 1.0e-8;
226 FirstOrderIntegrator integ =
227 new GraggBulirschStoerIntegrator(minStep, maxStep,
228 absTolerance, relTolerance);
229 integ.setStepHandler(new VariableStepHandler());
230 integ.integrate(pb,
231 pb.getInitialTime(), pb.getInitialState(),
232 pb.getFinalTime(), new double[pb.getDimension()]);
233 assertEquals("Gragg-Bulirsch-Stoer", integ.getName());
234 }
235
236 public void testUnstableDerivative()
237 throws DerivativeException, IntegratorException {
238 final StepProblem stepProblem = new StepProblem(0.0, 1.0, 2.0);
239 FirstOrderIntegrator integ =
240 new GraggBulirschStoerIntegrator(0.1, 10, 1.0e-12, 0.0);
241 integ.addSwitchingFunction(stepProblem, 1.0, 1.0e-12, 1000);
242 double[] y = { Double.NaN };
243 integ.integrate(stepProblem, 0.0, new double[] { 0.0 }, 10.0, y);
244 assertEquals(8.0, y[0], 1.0e-12);
245 }
246
247 private static class KeplerStepHandler implements StepHandler {
248 public KeplerStepHandler(TestProblem3 pb) {
249 this.pb = pb;
250 reset();
251 }
252 public boolean requiresDenseOutput() {
253 return true;
254 }
255 public void reset() {
256 nbSteps = 0;
257 maxError = 0;
258 }
259 public void handleStep(StepInterpolator interpolator,
260 boolean isLast)
261 throws DerivativeException {
262
263 ++nbSteps;
264 for (int a = 1; a < 100; ++a) {
265
266 double prev = interpolator.getPreviousTime();
267 double curr = interpolator.getCurrentTime();
268 double interp = ((100 - a) * prev + a * curr) / 100;
269 interpolator.setInterpolatedTime(interp);
270
271 double[] interpolatedY = interpolator.getInterpolatedState ();
272 double[] theoreticalY = pb.computeTheoreticalState(interpolator.getInterpolatedTime());
273 double dx = interpolatedY[0] - theoreticalY[0];
274 double dy = interpolatedY[1] - theoreticalY[1];
275 double error = dx * dx + dy * dy;
276 if (error > maxError) {
277 maxError = error;
278 }
279 }
280 if (isLast) {
281 assertTrue(maxError < 2.7e-6);
282 assertTrue(nbSteps < 80);
283 }
284 }
285 private int nbSteps;
286 private double maxError;
287 private TestProblem3 pb;
288 }
289
290 public static class VariableStepHandler implements StepHandler {
291 public VariableStepHandler() {
292 reset();
293 }
294 public boolean requiresDenseOutput() {
295 return false;
296 }
297 public void reset() {
298 firstTime = true;
299 minStep = 0;
300 maxStep = 0;
301 }
302 public void handleStep(StepInterpolator interpolator,
303 boolean isLast) {
304
305 double step = Math.abs(interpolator.getCurrentTime()
306 - interpolator.getPreviousTime());
307 if (firstTime) {
308 minStep = Math.abs(step);
309 maxStep = minStep;
310 firstTime = false;
311 } else {
312 if (step < minStep) {
313 minStep = step;
314 }
315 if (step > maxStep) {
316 maxStep = step;
317 }
318 }
319
320 if (isLast) {
321 assertTrue(minStep < 8.2e-3);
322 assertTrue(maxStep > 1.7);
323 }
324 }
325 private boolean firstTime;
326 private double minStep;
327 private double maxStep;
328 }
329 public static Test suite() {
330 return new TestSuite(GraggBulirschStoerIntegratorTest.class);
331 }
332
333 }