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 java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.ObjectInputStream;
25  import java.io.ObjectOutputStream;
26  import java.util.Random;
27  
28  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
29  import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
30  import org.apache.commons.math4.legacy.exception.NoBracketingException;
31  import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
32  import org.apache.commons.math4.legacy.ode.ContinuousOutputModel;
33  import org.apache.commons.math4.legacy.ode.EquationsMapper;
34  import org.apache.commons.math4.legacy.ode.TestProblem1;
35  import org.apache.commons.math4.legacy.ode.TestProblem3;
36  import org.apache.commons.math4.legacy.ode.sampling.StepHandler;
37  import org.apache.commons.math4.legacy.ode.sampling.StepInterpolatorTestUtils;
38  import org.apache.commons.math4.core.jdkmath.JdkMath;
39  import org.junit.Assert;
40  import org.junit.Test;
41  
42  public class EulerStepInterpolatorTest {
43  
44    @Test
45    public void noReset() throws MaxCountExceededException {
46  
47      double[]   y    =   { 0.0, 1.0, -2.0 };
48      double[][] yDot = { { 1.0, 2.0, -2.0 } };
49      EulerStepInterpolator interpolator = new EulerStepInterpolator();
50      interpolator.reinitialize(new DummyIntegrator(interpolator), y, yDot, true,
51                                new EquationsMapper(0, y.length),
52                                new EquationsMapper[0]);
53      interpolator.storeTime(0);
54      interpolator.shift();
55      interpolator.storeTime(1);
56  
57      double[] result = interpolator.getInterpolatedState();
58      for (int i = 0; i < result.length; ++i) {
59        Assert.assertTrue(JdkMath.abs(result[i] - y[i]) < 1.0e-10);
60      }
61    }
62  
63    @Test
64    public void interpolationAtBounds() throws MaxCountExceededException {
65  
66      double   t0 = 0;
67      double[] y0 = {0.0, 1.0, -2.0};
68  
69      double[] y = y0.clone();
70      double[][] yDot = { new double[y0.length] };
71      EulerStepInterpolator interpolator = new EulerStepInterpolator();
72      interpolator.reinitialize(new DummyIntegrator(interpolator), y, yDot, true,
73                                new EquationsMapper(0, y.length),
74                                new EquationsMapper[0]);
75      interpolator.storeTime(t0);
76  
77      double dt = 1.0;
78      interpolator.shift();
79      y[0] =  1.0;
80      y[1] =  3.0;
81      y[2] = -4.0;
82      yDot[0][0] = (y[0] - y0[0]) / dt;
83      yDot[0][1] = (y[1] - y0[1]) / dt;
84      yDot[0][2] = (y[2] - y0[2]) / dt;
85      interpolator.storeTime(t0 + dt);
86  
87      interpolator.setInterpolatedTime(interpolator.getPreviousTime());
88      double[] result = interpolator.getInterpolatedState();
89      for (int i = 0; i < result.length; ++i) {
90          Assert.assertTrue(JdkMath.abs(result[i] - y0[i]) < 1.0e-10);
91      }
92  
93      interpolator.setInterpolatedTime(interpolator.getCurrentTime());
94      result = interpolator.getInterpolatedState();
95      for (int i = 0; i < result.length; ++i) {
96        Assert.assertTrue(JdkMath.abs(result[i] - y[i]) < 1.0e-10);
97      }
98    }
99  
100   @Test
101   public void interpolationInside() throws MaxCountExceededException {
102 
103     double[]   y    =   { 0.0, 1.0, -2.0 };
104     double[][] yDot = { { 1.0, 2.0, -2.0 } };
105     EulerStepInterpolator interpolator = new EulerStepInterpolator();
106     interpolator.reinitialize(new DummyIntegrator(interpolator), y, yDot, true,
107                               new EquationsMapper(0, y.length),
108                               new EquationsMapper[0]);
109     interpolator.storeTime(0);
110     interpolator.shift();
111     y[0] =  1.0;
112     y[1] =  3.0;
113     y[2] = -4.0;
114     interpolator.storeTime(1);
115 
116     interpolator.setInterpolatedTime(0.1);
117     double[] result = interpolator.getInterpolatedState();
118     Assert.assertTrue(JdkMath.abs(result[0] - 0.1) < 1.0e-10);
119     Assert.assertTrue(JdkMath.abs(result[1] - 1.2) < 1.0e-10);
120     Assert.assertTrue(JdkMath.abs(result[2] + 2.2) < 1.0e-10);
121 
122     interpolator.setInterpolatedTime(0.5);
123     result = interpolator.getInterpolatedState();
124     Assert.assertTrue(JdkMath.abs(result[0] - 0.5) < 1.0e-10);
125     Assert.assertTrue(JdkMath.abs(result[1] - 2.0) < 1.0e-10);
126     Assert.assertTrue(JdkMath.abs(result[2] + 3.0) < 1.0e-10);
127   }
128 
129   @Test
130   public void derivativesConsistency()
131       throws DimensionMismatchException, NumberIsTooSmallException,
132              MaxCountExceededException, NoBracketingException {
133     TestProblem3 pb = new TestProblem3();
134     double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.001;
135     EulerIntegrator integ = new EulerIntegrator(step);
136     StepInterpolatorTestUtils.checkDerivativesConsistency(integ, pb, 0.01, 5.1e-12);
137   }
138 
139   @Test
140   public void serialization()
141     throws IOException, ClassNotFoundException,
142            DimensionMismatchException, NumberIsTooSmallException,
143            MaxCountExceededException, NoBracketingException {
144 
145     TestProblem1 pb = new TestProblem1();
146     double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.001;
147     EulerIntegrator integ = new EulerIntegrator(step);
148     integ.addStepHandler(new ContinuousOutputModel());
149     integ.integrate(pb,
150                     pb.getInitialTime(), pb.getInitialState(),
151                     pb.getFinalTime(), new double[pb.getDimension()]);
152 
153     ByteArrayOutputStream bos = new ByteArrayOutputStream();
154     ObjectOutputStream    oos = new ObjectOutputStream(bos);
155     for (StepHandler handler : integ.getStepHandlers()) {
156         oos.writeObject(handler);
157     }
158 
159     ByteArrayInputStream  bis = new ByteArrayInputStream(bos.toByteArray());
160     ObjectInputStream     ois = new ObjectInputStream(bis);
161     ContinuousOutputModel cm  = (ContinuousOutputModel) ois.readObject();
162 
163     Random random = new Random(347588535632L);
164     double maxError = 0.0;
165     for (int i = 0; i < 1000; ++i) {
166       double r = random.nextDouble();
167       double time = r * pb.getInitialTime() + (1.0 - r) * pb.getFinalTime();
168       cm.setInterpolatedTime(time);
169       double[] interpolatedY = cm.getInterpolatedState ();
170       double[] theoreticalY  = pb.computeTheoreticalState(time);
171       double dx = interpolatedY[0] - theoreticalY[0];
172       double dy = interpolatedY[1] - theoreticalY[1];
173       double error = dx * dx + dy * dy;
174       if (error > maxError) {
175         maxError = error;
176       }
177     }
178     Assert.assertTrue(maxError < 0.001);
179   }
180 
181   private static final class DummyIntegrator extends RungeKuttaIntegrator {
182 
183 
184       protected DummyIntegrator(RungeKuttaStepInterpolator prototype) {
185           super("dummy", new double[0], new double[0][0], new double[0], prototype, Double.NaN);
186       }
187   }
188 }