View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math4.legacy.ode.nonstiff;
19  
20  
21  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
22  import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
23  import org.apache.commons.math4.legacy.exception.NoBracketingException;
24  import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
25  import org.apache.commons.math4.legacy.ode.FirstOrderDifferentialEquations;
26  import org.apache.commons.math4.legacy.ode.FirstOrderIntegrator;
27  import org.apache.commons.math4.legacy.ode.TestProblem1;
28  import org.apache.commons.math4.legacy.ode.TestProblem2;
29  import org.apache.commons.math4.legacy.ode.TestProblem3;
30  import org.apache.commons.math4.legacy.ode.TestProblem4;
31  import org.apache.commons.math4.legacy.ode.TestProblem5;
32  import org.apache.commons.math4.legacy.ode.TestProblem6;
33  import org.apache.commons.math4.legacy.ode.TestProblemAbstract;
34  import org.apache.commons.math4.legacy.ode.TestProblemHandler;
35  import org.apache.commons.math4.legacy.ode.events.EventHandler;
36  import org.apache.commons.math4.legacy.ode.sampling.StepHandler;
37  import org.apache.commons.math4.legacy.ode.sampling.StepInterpolator;
38  import org.apache.commons.math4.core.jdkmath.JdkMath;
39  import org.junit.Assert;
40  import org.junit.Test;
41  
42  public class EulerIntegratorTest {
43  
44    @Test(expected=DimensionMismatchException.class)
45    public void testDimensionCheck()
46        throws DimensionMismatchException, NumberIsTooSmallException,
47               MaxCountExceededException, NoBracketingException {
48        TestProblem1 pb = new TestProblem1();
49        new EulerIntegrator(0.01).integrate(pb,
50                                            0.0, new double[pb.getDimension()+10],
51                                            1.0, new double[pb.getDimension()+10]);
52          Assert.fail("an exception should have been thrown");
53    }
54  
55    @Test
56    public void testDecreasingSteps()
57        throws DimensionMismatchException, NumberIsTooSmallException,
58               MaxCountExceededException, NoBracketingException {
59  
60        for (TestProblemAbstract pb : new TestProblemAbstract[] {
61            new TestProblem1(), new TestProblem2(), new TestProblem3(),
62            new TestProblem4(), new TestProblem5(), new TestProblem6()
63        }) {
64  
65        double previousValueError = Double.NaN;
66        double previousTimeError = Double.NaN;
67        for (int i = 4; i < 8; ++i) {
68  
69          double step = (pb.getFinalTime() - pb.getInitialTime()) * JdkMath.pow(2.0, -i);
70  
71          FirstOrderIntegrator integ = new EulerIntegrator(step);
72          TestProblemHandler handler = new TestProblemHandler(pb, integ);
73          integ.addStepHandler(handler);
74          EventHandler[] functions = pb.getEventsHandlers();
75          for (int l = 0; l < functions.length; ++l) {
76            integ.addEventHandler(functions[l],
77                                       Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000);
78          }
79          double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(),
80                                            pb.getFinalTime(), new double[pb.getDimension()]);
81          if (functions.length == 0) {
82              Assert.assertEquals(pb.getFinalTime(), stopTime, 1.0e-10);
83          }
84  
85          double valueError = handler.getMaximalValueError();
86          if (i > 4) {
87            Assert.assertTrue(valueError < JdkMath.abs(previousValueError));
88          }
89          previousValueError = valueError;
90  
91          double timeError = handler.getMaximalTimeError();
92          if (i > 4) {
93            Assert.assertTrue(timeError <= JdkMath.abs(previousTimeError));
94          }
95          previousTimeError = timeError;
96        }
97      }
98    }
99  
100   @Test
101   public void testSmallStep()
102       throws DimensionMismatchException, NumberIsTooSmallException,
103              MaxCountExceededException, NoBracketingException {
104 
105     TestProblem1 pb  = new TestProblem1();
106     double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.001;
107 
108     FirstOrderIntegrator integ = new EulerIntegrator(step);
109     TestProblemHandler handler = new TestProblemHandler(pb, integ);
110     integ.addStepHandler(handler);
111     integ.integrate(pb,
112                     pb.getInitialTime(), pb.getInitialState(),
113                     pb.getFinalTime(), new double[pb.getDimension()]);
114 
115    Assert.assertTrue(handler.getLastError() < 2.0e-4);
116    Assert.assertTrue(handler.getMaximalValueError() < 1.0e-3);
117    Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-12);
118    Assert.assertEquals("Euler", integ.getName());
119   }
120 
121   @Test
122   public void testBigStep()
123       throws DimensionMismatchException, NumberIsTooSmallException,
124              MaxCountExceededException, NoBracketingException {
125 
126     TestProblem1 pb  = new TestProblem1();
127     double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.2;
128 
129     FirstOrderIntegrator integ = new EulerIntegrator(step);
130     TestProblemHandler handler = new TestProblemHandler(pb, integ);
131     integ.addStepHandler(handler);
132     integ.integrate(pb,
133                     pb.getInitialTime(), pb.getInitialState(),
134                     pb.getFinalTime(), new double[pb.getDimension()]);
135 
136     Assert.assertTrue(handler.getLastError() > 0.01);
137     Assert.assertTrue(handler.getMaximalValueError() > 0.2);
138     Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-12);
139   }
140 
141   @Test
142   public void testBackward()
143       throws DimensionMismatchException, NumberIsTooSmallException,
144              MaxCountExceededException, NoBracketingException {
145 
146       TestProblem5 pb = new TestProblem5();
147       double step = JdkMath.abs(pb.getFinalTime() - pb.getInitialTime()) * 0.001;
148 
149       FirstOrderIntegrator integ = new EulerIntegrator(step);
150       TestProblemHandler handler = new TestProblemHandler(pb, integ);
151       integ.addStepHandler(handler);
152       integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(),
153                       pb.getFinalTime(), new double[pb.getDimension()]);
154 
155       Assert.assertTrue(handler.getLastError() < 0.45);
156       Assert.assertTrue(handler.getMaximalValueError() < 0.45);
157       Assert.assertEquals(0, handler.getMaximalTimeError(), 1.0e-12);
158       Assert.assertEquals("Euler", integ.getName());
159   }
160 
161   @Test
162   public void testStepSize()
163       throws DimensionMismatchException, NumberIsTooSmallException,
164              MaxCountExceededException, NoBracketingException {
165       final double step = 1.23456;
166       FirstOrderIntegrator integ = new EulerIntegrator(step);
167       integ.addStepHandler(new StepHandler() {
168         @Override
169         public void handleStep(StepInterpolator interpolator, boolean isLast) {
170             if (! isLast) {
171                 Assert.assertEquals(step,
172                              interpolator.getCurrentTime() - interpolator.getPreviousTime(),
173                              1.0e-12);
174             }
175         }
176         @Override
177         public void init(double t0, double[] y0, double t) {
178         }
179       });
180       integ.integrate(new FirstOrderDifferentialEquations() {
181                           @Override
182                         public void computeDerivatives(double t, double[] y, double[] dot) {
183                               dot[0] = 1.0;
184                           }
185                           @Override
186                         public int getDimension() {
187                               return 1;
188                           }
189                       }, 0.0, new double[] { 0.0 }, 5.0, new double[1]);
190   }
191 }