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