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 }