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;
19  
20  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
21  import org.apache.commons.math4.legacy.exception.MaxCountExceededException;
22  import org.apache.commons.math4.legacy.exception.NoBracketingException;
23  import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
24  import org.apache.commons.math4.legacy.ode.nonstiff.ClassicalRungeKuttaIntegrator;
25  import org.apache.commons.math4.core.jdkmath.JdkMath;
26  import org.junit.Assert;
27  import org.junit.Test;
28  
29  
30  public class FirstOrderConverterTest {
31  
32    @Test
33    public void testDoubleDimension() {
34      for (int i = 1; i < 10; ++i) {
35        SecondOrderDifferentialEquations eqn2 = new Equations(i, 0.2);
36        FirstOrderConverter eqn1 = new FirstOrderConverter(eqn2);
37        Assert.assertEquals(eqn1.getDimension(), 2 * eqn2.getDimension());
38      }
39    }
40  
41    @Test
42    public void testDecreasingSteps()
43        throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
44  
45      double previousError = Double.NaN;
46      for (int i = 0; i < 10; ++i) {
47  
48        double step  = JdkMath.pow(2.0, -(i + 1));
49        double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, step)
50                     - JdkMath.sin(4.0);
51        if (i > 0) {
52          Assert.assertTrue(JdkMath.abs(error) < JdkMath.abs(previousError));
53        }
54        previousError = error;
55      }
56    }
57  
58    @Test
59    public void testSmallStep()
60        throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
61      double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 1.0e-4)
62                     - JdkMath.sin(4.0);
63      Assert.assertTrue(JdkMath.abs(error) < 1.0e-10);
64    }
65  
66    @Test
67    public void testBigStep()
68        throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
69      double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 0.5)
70                     - JdkMath.sin(4.0);
71      Assert.assertTrue(JdkMath.abs(error) > 0.1);
72    }
73  
74    private static final class Equations
75      implements SecondOrderDifferentialEquations {
76  
77       private int n;
78  
79        private double omega2;
80  
81        Equations(int n, double omega) {
82          this.n = n;
83          omega2 = omega * omega;
84        }
85  
86        @Override
87      public int getDimension() {
88          return n;
89        }
90  
91        @Override
92      public void computeSecondDerivatives(double t, double[] y, double[] yDot,
93                                             double[] yDDot) {
94          for (int i = 0; i < n; ++i) {
95            yDDot[i] = -omega2 * y[i];
96          }
97      }
98    }
99  
100   private double integrateWithSpecifiedStep(double omega,
101                                             double t0, double t,
102                                             double step) throws DimensionMismatchException, NumberIsTooSmallException, MaxCountExceededException, NoBracketingException {
103     double[] y0 = new double[2];
104     y0[0] = JdkMath.sin(omega * t0);
105     y0[1] = omega * JdkMath.cos(omega * t0);
106     ClassicalRungeKuttaIntegrator i = new ClassicalRungeKuttaIntegrator(step);
107     double[] y = new double[2];
108     i.integrate(new FirstOrderConverter(new Equations(1, omega)), t0, y0, t, y);
109     return y[0];
110   }
111 }