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.sampling;
19  
20  import org.junit.Assert;
21  
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
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.FirstOrderDifferentialEquations;
30  import org.apache.commons.math4.legacy.ode.FirstOrderIntegrator;
31  import org.apache.commons.math4.legacy.ode.nonstiff.GraggBulirschStoerIntegrator;
32  import org.junit.Test;
33  
34  /** Base class for step normalizer output tests. */
35  public abstract class StepNormalizerOutputTestBase
36      implements FirstOrderDifferentialEquations, FixedStepHandler {
37  
38      /** The normalized output time values. */
39      private List<Double> output;
40  
41      /**
42       * Returns the start time.
43       * @return the start time
44       */
45      protected abstract double getStart();
46  
47      /**
48       * Returns the end time.
49       * @return the end time
50       */
51      protected abstract double getEnd();
52  
53      /**
54       * Returns the expected normalized output time values for increment mode.
55       * @return the expected normalized output time values for increment mode
56       */
57      protected abstract double[] getExpInc();
58  
59      /**
60       * Returns the expected reversed normalized output time values for
61       * increment mode.
62       * @return the expected reversed normalized output time values for
63       * increment mode
64       */
65      protected abstract double[] getExpIncRev();
66  
67      /**
68       * Returns the expected normalized output time values for multiples mode.
69       * @return the expected normalized output time values for multiples mode
70       */
71      protected abstract double[] getExpMul();
72  
73      /**
74       * Returns the expected reversed normalized output time values for
75       * multiples mode.
76       * @return the expected reversed normalized output time values for
77       * multiples mode
78       */
79      protected abstract double[] getExpMulRev();
80  
81      /**
82       * Returns the offsets for the unit tests below, in the order they are
83       * given below. For each test, the left and right offsets are returned.
84       * @return the offsets for the unit tests below, in the order they are
85       * given below
86       */
87      protected abstract int[][] getO();
88  
89      /**
90       * Get the array, given left and right offsets.
91       * @param a the input array
92       * @param offsetL the left side offset
93       * @param offsetR the right side offset
94       * @return the modified array
95       */
96      private double[] getArray(double[] a, int offsetL, int offsetR) {
97          double[] copy = new double[a.length - offsetR - offsetL];
98          System.arraycopy(a, offsetL, copy, 0, copy.length);
99          return copy;
100     }
101 
102     @Test
103     public void testIncNeither()
104         throws DimensionMismatchException, NumberIsTooSmallException,
105                MaxCountExceededException, NoBracketingException {
106         double[] exp = getArray(getExpInc(), getO()[0][0], getO()[0][1]);
107         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.NEITHER, exp, false);
108     }
109 
110     @Test
111     public void testIncNeitherRev()
112         throws DimensionMismatchException, NumberIsTooSmallException,
113                MaxCountExceededException, NoBracketingException {
114         double[] exp = getArray(getExpIncRev(), getO()[1][0], getO()[1][1]);
115         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.NEITHER, exp, true);
116     }
117 
118     @Test
119     public void testIncFirst()
120         throws DimensionMismatchException, NumberIsTooSmallException,
121                MaxCountExceededException, NoBracketingException {
122         double[] exp = getArray(getExpInc(), getO()[2][0], getO()[2][1]);
123         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.FIRST, exp, false);
124     }
125 
126     @Test
127     public void testIncFirstRev()
128         throws DimensionMismatchException, NumberIsTooSmallException,
129                MaxCountExceededException, NoBracketingException {
130         double[] exp = getArray(getExpIncRev(), getO()[3][0], getO()[3][1]);
131         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.FIRST, exp, true);
132     }
133 
134     @Test
135     public void testIncLast()
136         throws DimensionMismatchException, NumberIsTooSmallException,
137                MaxCountExceededException, NoBracketingException {
138         double[] exp = getArray(getExpInc(), getO()[4][0], getO()[4][1]);
139         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.LAST, exp, false);
140     }
141 
142     @Test
143     public void testIncLastRev()
144         throws DimensionMismatchException, NumberIsTooSmallException,
145                MaxCountExceededException, NoBracketingException {
146         double[] exp = getArray(getExpIncRev(), getO()[5][0], getO()[5][1]);
147         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.LAST, exp, true);
148     }
149 
150     @Test
151     public void testIncBoth()
152         throws DimensionMismatchException, NumberIsTooSmallException,
153                MaxCountExceededException, NoBracketingException {
154         double[] exp = getArray(getExpInc(), getO()[6][0], getO()[6][1]);
155         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.BOTH, exp, false);
156     }
157 
158     @Test
159     public void testIncBothRev()
160         throws DimensionMismatchException, NumberIsTooSmallException,
161                MaxCountExceededException, NoBracketingException {
162         double[] exp = getArray(getExpIncRev(), getO()[7][0], getO()[7][1]);
163         doTest(StepNormalizerMode.INCREMENT, StepNormalizerBounds.BOTH, exp, true);
164     }
165 
166     @Test
167     public void testMulNeither()
168         throws DimensionMismatchException, NumberIsTooSmallException,
169                MaxCountExceededException, NoBracketingException {
170         double[] exp = getArray(getExpMul(), getO()[8][0], getO()[8][1]);
171         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.NEITHER, exp, false);
172     }
173 
174     @Test
175     public void testMulNeitherRev()
176         throws DimensionMismatchException, NumberIsTooSmallException,
177                MaxCountExceededException, NoBracketingException {
178         double[] exp = getArray(getExpMulRev(), getO()[9][0], getO()[9][1]);
179         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.NEITHER, exp, true);
180     }
181 
182     @Test
183     public void testMulFirst()
184         throws DimensionMismatchException, NumberIsTooSmallException,
185                MaxCountExceededException, NoBracketingException {
186         double[] exp = getArray(getExpMul(), getO()[10][0], getO()[10][1]);
187         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.FIRST, exp, false);
188     }
189 
190     @Test
191     public void testMulFirstRev()
192         throws DimensionMismatchException, NumberIsTooSmallException,
193                MaxCountExceededException, NoBracketingException {
194         double[] exp = getArray(getExpMulRev(), getO()[11][0], getO()[11][1]);
195         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.FIRST, exp, true);
196     }
197 
198     @Test
199     public void testMulLast()
200         throws DimensionMismatchException, NumberIsTooSmallException,
201                MaxCountExceededException, NoBracketingException {
202         double[] exp = getArray(getExpMul(), getO()[12][0], getO()[12][1]);
203         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.LAST, exp, false);
204     }
205 
206     @Test
207     public void testMulLastRev()
208         throws DimensionMismatchException, NumberIsTooSmallException,
209                MaxCountExceededException, NoBracketingException {
210         double[] exp = getArray(getExpMulRev(), getO()[13][0], getO()[13][1]);
211         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.LAST, exp, true);
212     }
213 
214     @Test
215     public void testMulBoth()
216         throws DimensionMismatchException, NumberIsTooSmallException,
217                MaxCountExceededException, NoBracketingException {
218         double[] exp = getArray(getExpMul(), getO()[14][0], getO()[14][1]);
219         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.BOTH, exp, false);
220     }
221 
222     @Test
223     public void testMulBothRev()
224         throws DimensionMismatchException, NumberIsTooSmallException,
225                MaxCountExceededException, NoBracketingException {
226         double[] exp = getArray(getExpMulRev(), getO()[15][0], getO()[15][1]);
227         doTest(StepNormalizerMode.MULTIPLES, StepNormalizerBounds.BOTH, exp, true);
228     }
229 
230     /**
231      * The actual step normalizer output test code, shared by all the unit
232      * tests.
233      *
234      * @param mode the step normalizer mode to use
235      * @param bounds the step normalizer bounds setting to use
236      * @param expected the expected output (normalized time points)
237      * @param reverse whether to reverse the integration direction
238      * @throws NoBracketingException
239      * @throws MaxCountExceededException
240      * @throws NumberIsTooSmallException
241      * @throws DimensionMismatchException
242      */
243     private void doTest(StepNormalizerMode mode, StepNormalizerBounds bounds,
244                         double[] expected, boolean reverse)
245         throws DimensionMismatchException, NumberIsTooSmallException,
246                MaxCountExceededException, NoBracketingException {
247         // Forward test.
248         FirstOrderIntegrator integ = new GraggBulirschStoerIntegrator(
249                                                         1e-8, 1.0, 1e-5, 1e-5);
250         integ.addStepHandler(new StepNormalizer(0.5, this, mode, bounds));
251         double[] y   = {0.0};
252         double start = reverse ? getEnd()   : getStart();
253         double end   = reverse ? getStart() : getEnd();
254         output       = new ArrayList<>();
255         integ.integrate(this, start, y, end, y);
256         double[] actual = new double[output.size()];
257         for(int i = 0; i < actual.length; i++) {
258             actual[i] = output.get(i);
259         }
260         Assert.assertArrayEquals(expected, actual, 1e-5);
261     }
262 
263     /** {@inheritDoc} */
264     @Override
265     public int getDimension() {
266         return 1;
267     }
268 
269     /** {@inheritDoc} */
270     @Override
271     public void computeDerivatives(double t, double[] y, double[] yDot) {
272         yDot[0] = y[0];
273     }
274 
275     /** {@inheritDoc} */
276     @Override
277     public void init(double t0, double[] y0, double t) {
278     }
279 
280     /** {@inheritDoc} */
281     @Override
282     public void handleStep(double t, double[] y, double[] yDot, boolean isLast) {
283         output.add(t);
284     }
285 }