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.nonstiff; 019 020 import junit.framework.*; 021 022 import org.apache.commons.math.ode.DerivativeException; 023 import org.apache.commons.math.ode.FirstOrderDifferentialEquations; 024 import org.apache.commons.math.ode.FirstOrderIntegrator; 025 import org.apache.commons.math.ode.IntegratorException; 026 import org.apache.commons.math.ode.TestProblem1; 027 import org.apache.commons.math.ode.TestProblem5; 028 import org.apache.commons.math.ode.TestProblemAbstract; 029 import org.apache.commons.math.ode.TestProblemFactory; 030 import org.apache.commons.math.ode.TestProblemHandler; 031 import org.apache.commons.math.ode.events.EventHandler; 032 import org.apache.commons.math.ode.nonstiff.EulerIntegrator; 033 import org.apache.commons.math.ode.sampling.StepHandler; 034 import org.apache.commons.math.ode.sampling.StepInterpolator; 035 036 public class EulerIntegratorTest 037 extends TestCase { 038 039 public EulerIntegratorTest(String name) { 040 super(name); 041 } 042 043 public void testDimensionCheck() { 044 try { 045 TestProblem1 pb = new TestProblem1(); 046 new EulerIntegrator(0.01).integrate(pb, 047 0.0, new double[pb.getDimension()+10], 048 1.0, new double[pb.getDimension()+10]); 049 fail("an exception should have been thrown"); 050 } catch(DerivativeException de) { 051 fail("wrong exception caught"); 052 } catch(IntegratorException ie) { 053 } 054 } 055 056 public void testDecreasingSteps() 057 throws DerivativeException, IntegratorException { 058 059 TestProblemAbstract[] problems = TestProblemFactory.getProblems(); 060 for (int k = 0; k < problems.length; ++k) { 061 062 double previousError = Double.NaN; 063 for (int i = 4; i < 10; ++i) { 064 065 TestProblemAbstract pb = problems[k].copy(); 066 double step = (pb.getFinalTime() - pb.getInitialTime()) 067 * Math.pow(2.0, -i); 068 069 FirstOrderIntegrator integ = new EulerIntegrator(step); 070 TestProblemHandler handler = new TestProblemHandler(pb, integ); 071 integ.addStepHandler(handler); 072 EventHandler[] functions = pb.getEventsHandlers(); 073 for (int l = 0; l < functions.length; ++l) { 074 integ.addEventHandler(functions[l], 075 Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); 076 } 077 double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), 078 pb.getFinalTime(), new double[pb.getDimension()]); 079 if (functions.length == 0) { 080 assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); 081 } 082 083 double error = handler.getMaximalValueError(); 084 if (i > 4) { 085 assertTrue(error < Math.abs(previousError)); 086 } 087 previousError = error; 088 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12); 089 090 } 091 092 } 093 094 } 095 096 public void testSmallStep() 097 throws DerivativeException, IntegratorException { 098 099 TestProblem1 pb = new TestProblem1(); 100 double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.001; 101 102 FirstOrderIntegrator integ = new EulerIntegrator(step); 103 TestProblemHandler handler = new TestProblemHandler(pb, integ); 104 integ.addStepHandler(handler); 105 integ.integrate(pb, 106 pb.getInitialTime(), pb.getInitialState(), 107 pb.getFinalTime(), new double[pb.getDimension()]); 108 109 assertTrue(handler.getLastError() < 2.0e-4); 110 assertTrue(handler.getMaximalValueError() < 1.0e-3); 111 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12); 112 assertEquals("Euler", integ.getName()); 113 114 } 115 116 public void testBigStep() 117 throws DerivativeException, IntegratorException { 118 119 TestProblem1 pb = new TestProblem1(); 120 double step = (pb.getFinalTime() - pb.getInitialTime()) * 0.2; 121 122 FirstOrderIntegrator integ = new EulerIntegrator(step); 123 TestProblemHandler handler = new TestProblemHandler(pb, integ); 124 integ.addStepHandler(handler); 125 integ.integrate(pb, 126 pb.getInitialTime(), pb.getInitialState(), 127 pb.getFinalTime(), new double[pb.getDimension()]); 128 129 assertTrue(handler.getLastError() > 0.01); 130 assertTrue(handler.getMaximalValueError() > 0.2); 131 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12); 132 133 } 134 135 public void testBackward() 136 throws DerivativeException, IntegratorException { 137 138 TestProblem5 pb = new TestProblem5(); 139 double step = Math.abs(pb.getFinalTime() - pb.getInitialTime()) * 0.001; 140 141 FirstOrderIntegrator integ = new EulerIntegrator(step); 142 TestProblemHandler handler = new TestProblemHandler(pb, integ); 143 integ.addStepHandler(handler); 144 integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), 145 pb.getFinalTime(), new double[pb.getDimension()]); 146 147 assertTrue(handler.getLastError() < 0.45); 148 assertTrue(handler.getMaximalValueError() < 0.45); 149 assertEquals(0, handler.getMaximalTimeError(), 1.0e-12); 150 assertEquals("Euler", integ.getName()); 151 } 152 153 public void testStepSize() 154 throws DerivativeException, IntegratorException { 155 final double step = 1.23456; 156 FirstOrderIntegrator integ = new EulerIntegrator(step); 157 integ.addStepHandler(new StepHandler() { 158 public void handleStep(StepInterpolator interpolator, boolean isLast) { 159 if (! isLast) { 160 assertEquals(step, 161 interpolator.getCurrentTime() - interpolator.getPreviousTime(), 162 1.0e-12); 163 } 164 } 165 public boolean requiresDenseOutput() { 166 return false; 167 } 168 public void reset() { 169 } 170 }); 171 integ.integrate(new FirstOrderDifferentialEquations() { 172 private static final long serialVersionUID = 0L; 173 public void computeDerivatives(double t, double[] y, double[] dot) { 174 dot[0] = 1.0; 175 } 176 public int getDimension() { 177 return 1; 178 } 179 }, 0.0, new double[] { 0.0 }, 5.0, new double[1]); 180 } 181 182 public static Test suite() { 183 return new TestSuite(EulerIntegratorTest.class); 184 } 185 186 }