diff --git a/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java b/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java index ad6f0fa14..b3864262f 100644 --- a/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java +++ b/src/java/org/apache/commons/math/ode/AdaptiveStepsizeIntegrator.java @@ -330,9 +330,9 @@ public abstract class AdaptiveStepsizeIntegrator } /** {@inheritDoc} */ - public abstract void integrate (FirstOrderDifferentialEquations equations, - double t0, double[] y0, - double t, double[] y) + public abstract double integrate (FirstOrderDifferentialEquations equations, + double t0, double[] y0, + double t, double[] y) throws DerivativeException, IntegratorException; /** {@inheritDoc} */ diff --git a/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java b/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java index beaded737..64e265064 100644 --- a/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java +++ b/src/java/org/apache/commons/math/ode/FirstOrderIntegrator.java @@ -96,13 +96,15 @@ public interface FirstOrderIntegrator extends Serializable { * (can be set to a value smaller than t0 for backward integration) * @param y placeholder where to put the state vector at each successful * step (and hence at the end of integration), can be the same object as y0 + * @return stop time, will be the same as target time if integration reached its + * target, but may be different if some {@link EventHandler} stops it at some point. * @throws IntegratorException if the integrator cannot perform integration * @throws DerivativeException this exception is propagated to the caller if * the underlying user function triggers one */ - public void integrate (FirstOrderDifferentialEquations equations, - double t0, double[] y0, - double t, double[] y) + public double integrate (FirstOrderDifferentialEquations equations, + double t0, double[] y0, + double t, double[] y) throws DerivativeException, IntegratorException; /** Get the current value of the step start time ti. diff --git a/src/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java b/src/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java index 26addc210..77df0c6b2 100644 --- a/src/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java +++ b/src/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java @@ -161,9 +161,9 @@ public abstract class EmbeddedRungeKuttaIntegrator } /** {@inheritDoc} */ - public void integrate(final FirstOrderDifferentialEquations equations, - final double t0, final double[] y0, - final double t, final double[] y) + public double integrate(final FirstOrderDifferentialEquations equations, + final double t0, final double[] y0, + final double t, final double[] y) throws DerivativeException, IntegratorException { sanityChecks(equations, t0, y0, t, y); @@ -318,7 +318,9 @@ public abstract class EmbeddedRungeKuttaIntegrator } while (! lastStep); + final double stopTime = stepStart; resetInternalState(); + return stopTime; } diff --git a/src/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java b/src/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java index d3fa565eb..c48b3d3c8 100644 --- a/src/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java +++ b/src/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java @@ -508,8 +508,8 @@ public class GraggBulirschStoerIntegrator } /** {@inheritDoc} */ - public void integrate(final FirstOrderDifferentialEquations equations, - final double t0, final double[] y0, final double t, final double[] y) + public double integrate(final FirstOrderDifferentialEquations equations, + final double t0, final double[] y0, final double t, final double[] y) throws DerivativeException, IntegratorException { sanityChecks(equations, t0, y0, t, y); @@ -941,6 +941,8 @@ public class GraggBulirschStoerIntegrator } + return stepStart; + } /** maximal order. */ diff --git a/src/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java b/src/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java index 3403af0a6..087f5aa99 100644 --- a/src/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java +++ b/src/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java @@ -145,9 +145,9 @@ public abstract class RungeKuttaIntegrator } /** {@inheritDoc} */ - public void integrate(final FirstOrderDifferentialEquations equations, - final double t0, final double[] y0, - final double t, final double[] y) + public double integrate(final FirstOrderDifferentialEquations equations, + final double t0, final double[] y0, + final double t, final double[] y) throws DerivativeException, IntegratorException { sanityChecks(equations, t0, y0, t, y); @@ -257,7 +257,9 @@ public abstract class RungeKuttaIntegrator } + final double stopTime = stepStart; resetInternalState(); + return stopTime; } diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index d765cd86b..d085235b6 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -39,6 +39,15 @@ The type attribute can be add,update,fix,remove. + + Changed return type for FirstOrderIntegrator.integrate() to double + in order to retrieve exact stop time. This allows to handle properly + integration interruption due to an EventHandler instance asking to + stop the integration when its associated event is triggered. The state + was already set to the current state at interruption time, but it was + difficult to get the corresponding time (it involved setting a step + handler monitoring the last step specially). + Clarified the ODE package by breaking in into several sub-packages and renaming classes (SwitchingFunctions/EventHandler, SwitchingFunctionsHandler/CombinedEventsManager) diff --git a/src/test/org/apache/commons/math/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java index d3a6da0e3..4cbdd884e 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/ClassicalRungeKuttaIntegratorTest.java @@ -77,8 +77,7 @@ public class ClassicalRungeKuttaIntegratorTest for (int i = 4; i < 10; ++i) { TestProblemAbstract pb = (TestProblemAbstract) problems[k].clone(); - double step = (pb.getFinalTime() - pb.getInitialTime()) - * Math.pow(2.0, -i); + double step = (pb.getFinalTime() - pb.getInitialTime()) * Math.pow(2.0, -i); FirstOrderIntegrator integ = new ClassicalRungeKuttaIntegrator(step); TestProblemHandler handler = new TestProblemHandler(pb, integ); @@ -89,8 +88,11 @@ public class ClassicalRungeKuttaIntegratorTest Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } assertEquals(functions.length, integ.getEventsHandlers().size()); - integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + if (functions.length == 0) { + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); + } double error = handler.getMaximalValueError(); if (i > 4) { diff --git a/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince54IntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince54IntegratorTest.java index 4bc1e1cb2..a3717d643 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince54IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince54IntegratorTest.java @@ -241,9 +241,9 @@ public class DormandPrince54IntegratorTest scalAbsoluteTolerance, scalRelativeTolerance); integ.setStepHandler(new VariableHandler()); - integ.integrate(pb, - pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); } private static class KeplerHandler implements StepHandler { diff --git a/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java index 1d68cd0f9..8ea28e2fa 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/DormandPrince853IntegratorTest.java @@ -191,9 +191,10 @@ public class DormandPrince853IntegratorTest scalAbsoluteTolerance, scalRelativeTolerance); integ.setStepHandler(new VariableHandler()); - integ.integrate(pb, - pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); assertEquals("Dormand-Prince 8 (5, 3)", integ.getName()); } diff --git a/src/test/org/apache/commons/math/ode/nonstiff/EulerIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/EulerIntegratorTest.java index 7b9c6b63e..ce9da9ee3 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/EulerIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/EulerIntegratorTest.java @@ -66,9 +66,11 @@ public class EulerIntegratorTest integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } - integ.integrate(pb, - pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + if (functions.length == 0) { + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); + } double error = handler.getMaximalValueError(); if (i > 4) { diff --git a/src/test/org/apache/commons/math/ode/nonstiff/GillIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/GillIntegratorTest.java index 2621abd27..1ef0d9db0 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/GillIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/GillIntegratorTest.java @@ -68,8 +68,11 @@ public class GillIntegratorTest integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } - integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + if (functions.length == 0) { + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); + } double error = handler.getMaximalValueError(); if (i > 5) { diff --git a/src/test/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegratorTest.java index 4b3ac5dc9..128e80ac8 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegratorTest.java @@ -231,9 +231,10 @@ public class GraggBulirschStoerIntegratorTest new GraggBulirschStoerIntegrator(minStep, maxStep, absTolerance, relTolerance); integ.setStepHandler(new VariableStepHandler()); - integ.integrate(pb, - pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); assertEquals("Gragg-Bulirsch-Stoer", integ.getName()); } diff --git a/src/test/org/apache/commons/math/ode/nonstiff/MidpointIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/MidpointIntegratorTest.java index 9e0ff2c08..e77bbc132 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/MidpointIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/MidpointIntegratorTest.java @@ -65,9 +65,12 @@ public class MidpointIntegratorTest integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } - integ.integrate(pb, - pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, + pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + if (functions.length == 0) { + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); + } double error = handler.getMaximalValueError(); if (i > 4) { diff --git a/src/test/org/apache/commons/math/ode/nonstiff/ThreeEighthesIntegratorTest.java b/src/test/org/apache/commons/math/ode/nonstiff/ThreeEighthesIntegratorTest.java index 032e3a9af..f0089fc97 100644 --- a/src/test/org/apache/commons/math/ode/nonstiff/ThreeEighthesIntegratorTest.java +++ b/src/test/org/apache/commons/math/ode/nonstiff/ThreeEighthesIntegratorTest.java @@ -68,8 +68,11 @@ public class ThreeEighthesIntegratorTest integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, 1.0e-6 * step, 1000); } - integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), - pb.getFinalTime(), new double[pb.getDimension()]); + double stopTime = integ.integrate(pb, pb.getInitialTime(), pb.getInitialState(), + pb.getFinalTime(), new double[pb.getDimension()]); + if (functions.length == 0) { + assertEquals(pb.getFinalTime(), stopTime, 1.0e-10); + } double error = handler.getMaximalValueError(); if (i > 4) {