From 69273dca6188a3d7d629d0d32dcf9cdb5b6c1036 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Wed, 8 Oct 2014 14:25:05 +0200 Subject: [PATCH] fixed too long first step in fixed Runge-Kutta integrators. This change is similar to the one done two years ago for adaptive step sizes integrator. JIRA: MATH-727 --- .../ode/nonstiff/RungeKuttaIntegrator.java | 14 ++++++++++- .../ClassicalRungeKuttaIntegratorTest.java | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java index 68bd8b029..5f7d5d88a 100644 --- a/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java +++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaIntegrator.java @@ -119,7 +119,19 @@ public abstract class RungeKuttaIntegrator extends AbstractIntegrator { // set up integration control objects stepStart = equations.getTime(); - stepSize = forward ? step : -step; + if (forward) { + if (stepStart + step >= t) { + stepSize = t - stepStart; + } else { + stepSize = step; + } + } else { + if (stepStart - step <= t) { + stepSize = t - stepStart; + } else { + stepSize = -step; + } + } initIntegration(equations.getTime(), y0, t); // main integration loop diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java index 8136596f9..c52768052 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java @@ -310,4 +310,28 @@ public class ClassicalRungeKuttaIntegratorTest { }, 0.0, new double[] { 0.0 }, 5.0, new double[1]); } + @Test + public void testTooLargeFirstStep() { + + RungeKuttaIntegrator integ = new ClassicalRungeKuttaIntegrator(0.5); + final double start = 0.0; + final double end = 0.001; + FirstOrderDifferentialEquations equations = new FirstOrderDifferentialEquations() { + + public int getDimension() { + return 1; + } + + public void computeDerivatives(double t, double[] y, double[] yDot) { + Assert.assertTrue(t >= FastMath.nextAfter(start, Double.NEGATIVE_INFINITY)); + Assert.assertTrue(t <= FastMath.nextAfter(end, Double.POSITIVE_INFINITY)); + yDot[0] = -100.0 * y[0]; + } + + }; + + integ.integrate(equations, start, new double[] { 1.0 }, end, new double[1]); + + } + }