001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.ode;
019    
020    import org.apache.commons.math.ode.DerivativeException;
021    import org.apache.commons.math.ode.FirstOrderConverter;
022    import org.apache.commons.math.ode.IntegratorException;
023    import org.apache.commons.math.ode.SecondOrderDifferentialEquations;
024    import org.apache.commons.math.ode.nonstiff.ClassicalRungeKuttaIntegrator;
025    
026    import junit.framework.*;
027    
028    public class FirstOrderConverterTest
029      extends TestCase {
030    
031      public FirstOrderConverterTest(String name) {
032        super(name);
033      }
034    
035      public void testDoubleDimension() {
036        for (int i = 1; i < 10; ++i) {
037          SecondOrderDifferentialEquations eqn2 = new Equations(i, 0.2);
038          FirstOrderConverter eqn1 = new FirstOrderConverter(eqn2);
039          assertTrue(eqn1.getDimension() == (2 * eqn2.getDimension()));
040        }
041      }
042      
043      public void testDecreasingSteps()
044        throws DerivativeException, IntegratorException {
045          
046        double previousError = Double.NaN;
047        for (int i = 0; i < 10; ++i) {
048    
049          double step  = Math.pow(2.0, -(i + 1));
050          double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, step)
051                       - Math.sin(4.0);
052          if (i > 0) {
053            assertTrue(Math.abs(error) < Math.abs(previousError));
054          }
055          previousError = error;
056          
057        }
058      }
059    
060      public void testSmallStep()
061        throws DerivativeException, IntegratorException {
062        double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 1.0e-4)
063                       - Math.sin(4.0);
064        assertTrue(Math.abs(error) < 1.0e-10);
065      }
066    
067      public void testBigStep()
068        throws DerivativeException, IntegratorException {
069        double error = integrateWithSpecifiedStep(4.0, 0.0, 1.0, 0.5)
070                       - Math.sin(4.0);
071        assertTrue(Math.abs(error) > 0.1);
072      }
073      
074      public static Test suite() {
075        return new TestSuite(FirstOrderConverterTest.class);
076      }
077    
078      private static class Equations
079        implements SecondOrderDifferentialEquations {
080          
081         private int n;
082    
083          private double omega2;
084          
085          public Equations(int n, double omega) {
086            this.n = n;
087            omega2 = omega * omega;
088          }
089          
090          public int getDimension() {
091            return n;
092          }
093          
094          public void computeSecondDerivatives(double t, double[] y, double[] yDot,
095                                               double[] yDDot) {
096            for (int i = 0; i < n; ++i) {
097              yDDot[i] = -omega2 * y[i];
098            }
099        }
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    }