1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.ode.nonstiff;
19
20
21 import java.io.ObjectInput;
22 import java.io.ObjectOutput;
23
24 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
25 import org.apache.commons.math4.legacy.exception.MathIllegalStateException;
26 import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
27 import org.apache.commons.math4.legacy.exception.NoBracketingException;
28 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
29 import org.apache.commons.math4.legacy.ode.AbstractIntegrator;
30 import org.apache.commons.math4.legacy.ode.ExpandableStatefulODE;
31 import org.apache.commons.math4.legacy.ode.FirstOrderIntegrator;
32 import org.apache.commons.math4.legacy.ode.MultistepIntegrator;
33 import org.apache.commons.math4.legacy.ode.TestProblem1;
34 import org.apache.commons.math4.legacy.ode.TestProblem5;
35 import org.apache.commons.math4.legacy.ode.TestProblem6;
36 import org.apache.commons.math4.legacy.ode.TestProblemAbstract;
37 import org.apache.commons.math4.legacy.ode.TestProblemHandler;
38 import org.apache.commons.math4.legacy.ode.sampling.StepHandler;
39 import org.apache.commons.math4.legacy.ode.sampling.StepInterpolator;
40 import org.apache.commons.math4.core.jdkmath.JdkMath;
41 import org.junit.Assert;
42 import org.junit.Test;
43
44 public class AdamsBashforthIntegratorTest {
45
46 @Test(expected=DimensionMismatchException.class)
47 public void dimensionCheck() throws NumberIsTooSmallException, DimensionMismatchException, MaxCountExceededException, NoBracketingException {
48 TestProblem1 pb = new TestProblem1();
49 FirstOrderIntegrator integ =
50 new AdamsBashforthIntegrator(2, 0.0, 1.0, 1.0e-10, 1.0e-10);
51 integ.integrate(pb,
52 0.0, new double[pb.getDimension()+10],
53 1.0, new double[pb.getDimension()+10]);
54 }
55
56 @Test(expected=NumberIsTooSmallException.class)
57 public void testMinStep() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
58
59 TestProblem1 pb = new TestProblem1();
60 double minStep = 0.1 * (pb.getFinalTime() - pb.getInitialTime());
61 double maxStep = pb.getFinalTime() - pb.getInitialTime();
62 double[] vecAbsoluteTolerance = { 1.0e-15, 1.0e-16 };
63 double[] vecRelativeTolerance = { 1.0e-15, 1.0e-16 };
64
65 FirstOrderIntegrator integ = new AdamsBashforthIntegrator(4, minStep, maxStep,
66 vecAbsoluteTolerance,
67 vecRelativeTolerance);
68 TestProblemHandler handler = new TestProblemHandler(pb, integ);
69 integ.addStepHandler(handler);
70 integ.integrate(pb,
71 pb.getInitialTime(), pb.getInitialState(),
72 pb.getFinalTime(), new double[pb.getDimension()]);
73 }
74
75 @Test
76 public void testIncreasingTolerance() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
77
78 int previousCalls = Integer.MAX_VALUE;
79 for (int i = -12; i < -2; ++i) {
80 TestProblem1 pb = new TestProblem1();
81 double minStep = 0;
82 double maxStep = pb.getFinalTime() - pb.getInitialTime();
83 double scalAbsoluteTolerance = JdkMath.pow(10.0, i);
84 double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
85
86 FirstOrderIntegrator integ = new AdamsBashforthIntegrator(4, minStep, maxStep,
87 scalAbsoluteTolerance,
88 scalRelativeTolerance);
89 TestProblemHandler handler = new TestProblemHandler(pb, integ);
90 integ.addStepHandler(handler);
91 integ.integrate(pb,
92 pb.getInitialTime(), pb.getInitialState(),
93 pb.getFinalTime(), new double[pb.getDimension()]);
94
95
96
97
98 Assert.assertTrue(handler.getMaximalValueError() > (2.6 * scalAbsoluteTolerance));
99 Assert.assertTrue(handler.getMaximalValueError() < (122 * scalAbsoluteTolerance));
100
101 int calls = pb.getCalls();
102 Assert.assertEquals(integ.getEvaluations(), calls);
103 Assert.assertTrue(calls <= previousCalls);
104 previousCalls = calls;
105 }
106 }
107
108 @Test(expected = MaxCountExceededException.class)
109 public void exceedMaxEvaluations() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
110
111 TestProblem1 pb = new TestProblem1();
112 double range = pb.getFinalTime() - pb.getInitialTime();
113
114 AdamsBashforthIntegrator integ = new AdamsBashforthIntegrator(2, 0, range, 1.0e-12, 1.0e-12);
115 TestProblemHandler handler = new TestProblemHandler(pb, integ);
116 integ.addStepHandler(handler);
117 integ.setMaxEvaluations(650);
118 integ.integrate(pb,
119 pb.getInitialTime(), pb.getInitialState(),
120 pb.getFinalTime(), new double[pb.getDimension()]);
121 }
122
123 @Test
124 public void backward() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
125
126 TestProblem5 pb = new TestProblem5();
127 double range = JdkMath.abs(pb.getFinalTime() - pb.getInitialTime());
128
129 AdamsBashforthIntegrator integ = new AdamsBashforthIntegrator(4, 0, range, 1.0e-12, 1.0e-12);
130 integ.setStarterIntegrator(new PerfectStarter(pb, (integ.getNSteps() + 5) / 2));
131 TestProblemHandler handler = new TestProblemHandler(pb, integ);
132 integ.addStepHandler(handler);
133 integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(),
134 pb.getFinalTime(), new double[pb.getDimension()]);
135
136 Assert.assertEquals(0.0, handler.getLastError(), 4.3e-8);
137 Assert.assertEquals(0.0, handler.getMaximalValueError(), 4.3e-8);
138 Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-16);
139 Assert.assertEquals("Adams-Bashforth", integ.getName());
140 }
141
142 @Test
143 public void polynomial() throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
144 TestProblem6 pb = new TestProblem6();
145 double range = JdkMath.abs(pb.getFinalTime() - pb.getInitialTime());
146
147 for (int nSteps = 2; nSteps < 8; ++nSteps) {
148 AdamsBashforthIntegrator integ =
149 new AdamsBashforthIntegrator(nSteps, 1.0e-6 * range, 0.1 * range, 1.0e-4, 1.0e-4);
150 integ.setStarterIntegrator(new PerfectStarter(pb, nSteps));
151 TestProblemHandler handler = new TestProblemHandler(pb, integ);
152 integ.addStepHandler(handler);
153 integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(),
154 pb.getFinalTime(), new double[pb.getDimension()]);
155 if (nSteps < 5) {
156 Assert.assertTrue(handler.getMaximalValueError() > 0.005);
157 } else {
158 Assert.assertTrue(handler.getMaximalValueError() < 5.0e-10);
159 }
160 }
161 }
162
163 @Test(expected=MathIllegalStateException.class)
164 public void testStartFailure() {
165 TestProblem1 pb = new TestProblem1();
166 double minStep = 0.0001 * (pb.getFinalTime() - pb.getInitialTime());
167 double maxStep = pb.getFinalTime() - pb.getInitialTime();
168 double scalAbsoluteTolerance = 1.0e-6;
169 double scalRelativeTolerance = 1.0e-7;
170
171 MultistepIntegrator integ =
172 new AdamsBashforthIntegrator(6, minStep, maxStep,
173 scalAbsoluteTolerance,
174 scalRelativeTolerance);
175 integ.setStarterIntegrator(new DormandPrince853Integrator(0.5 * (pb.getFinalTime() - pb.getInitialTime()),
176 pb.getFinalTime() - pb.getInitialTime(),
177 0.1, 0.1));
178 TestProblemHandler handler = new TestProblemHandler(pb, integ);
179 integ.addStepHandler(handler);
180 integ.integrate(pb,
181 pb.getInitialTime(), pb.getInitialState(),
182 pb.getFinalTime(), new double[pb.getDimension()]);
183 }
184
185 private static final class PerfectStarter extends AbstractIntegrator {
186
187 private final PerfectInterpolator interpolator;
188 private final int nbSteps;
189
190 PerfectStarter(final TestProblemAbstract problem, final int nbSteps) {
191 this.interpolator = new PerfectInterpolator(problem);
192 this.nbSteps = nbSteps;
193 }
194
195 @Override
196 public void integrate(ExpandableStatefulODE equations, double t) {
197 double tStart = equations.getTime() + 0.01 * (t - equations.getTime());
198 getCounter().increment(nbSteps);
199 for (int i = 0; i < nbSteps; ++i) {
200 double tK = ((nbSteps - 1 - (i + 1)) * equations.getTime() + (i + 1) * tStart) / (nbSteps - 1);
201 interpolator.setPreviousTime(interpolator.getCurrentTime());
202 interpolator.setCurrentTime(tK);
203 interpolator.setInterpolatedTime(tK);
204 for (StepHandler handler : getStepHandlers()) {
205 handler.handleStep(interpolator, i == nbSteps - 1);
206 }
207 }
208 }
209 }
210
211 private static final class PerfectInterpolator implements StepInterpolator {
212 private static final long serialVersionUID = 1;
213 private final TestProblemAbstract problem;
214 private double previousTime;
215 private double currentTime;
216 private double interpolatedTime;
217
218 PerfectInterpolator(final TestProblemAbstract problem) {
219 this.problem = problem;
220 this.previousTime = problem.getInitialTime();
221 this.currentTime = problem.getInitialTime();
222 this.interpolatedTime = problem.getInitialTime();
223 }
224
225 @Override
226 public void readExternal(ObjectInput arg0) {
227 }
228
229 @Override
230 public void writeExternal(ObjectOutput arg0) {
231 }
232
233 @Override
234 public double getPreviousTime() {
235 return previousTime;
236 }
237
238 public void setPreviousTime(double time) {
239 previousTime = time;
240 }
241
242 @Override
243 public double getCurrentTime() {
244 return currentTime;
245 }
246
247 public void setCurrentTime(double time) {
248 currentTime = time;
249 }
250
251 @Override
252 public double getInterpolatedTime() {
253 return interpolatedTime;
254 }
255
256 @Override
257 public void setInterpolatedTime(double time) {
258 interpolatedTime = time;
259 }
260
261 @Override
262 public double[] getInterpolatedState() {
263 return problem.computeTheoreticalState(interpolatedTime);
264 }
265
266 @Override
267 public double[] getInterpolatedDerivatives() {
268 double[] y = problem.computeTheoreticalState(interpolatedTime);
269 double[] yDot = new double[y.length];
270 problem.computeDerivatives(interpolatedTime, y, yDot);
271 return yDot;
272 }
273
274 @Override
275 public double[] getInterpolatedSecondaryState(int index) {
276 return null;
277 }
278
279 @Override
280 public double[] getInterpolatedSecondaryDerivatives(int index) {
281 return null;
282 }
283
284 @Override
285 public boolean isForward() {
286 return problem.getFinalTime() > problem.getInitialTime();
287 }
288
289 @Override
290 public StepInterpolator copy() {
291 return this;
292 }
293 }
294 }