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 }