From 6041336783ba94b46fe5953e8415884bf0cef32c Mon Sep 17 00:00:00 2001
From: Luc Maisonobe
Date: Mon, 28 Nov 2011 10:20:51 +0000
Subject: [PATCH] Added init methods to StepHandler and EventHandler
interfaces.
The reset method in StepHandler interface has been renamed init and is
provided more information on the integration by the calling integrator.
A similar init method has been added to the EventHandler interface.
Jira: MATH-714
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1207054 13f79535-47bb-0310-9956-ffa450edef68
---
.../commons/math/ode/AbstractIntegrator.java | 21 +++++++--
.../math/ode/ContinuousOutputModel.java | 14 +++---
.../commons/math/ode/MultistepIntegrator.java | 2 +-
.../commons/math/ode/events/EventHandler.java | 12 +++++
.../nonstiff/AdamsBashforthIntegrator.java | 7 +--
.../ode/nonstiff/AdamsMoultonIntegrator.java | 7 +--
.../EmbeddedRungeKuttaIntegrator.java | 7 +--
.../GraggBulirschStoerIntegrator.java | 6 +--
.../ode/nonstiff/RungeKuttaIntegrator.java | 7 +--
.../math/ode/sampling/DummyStepHandler.java | 7 +--
.../math/ode/sampling/StepHandler.java | 46 +++++++++++--------
.../math/ode/sampling/StepNormalizer.java | 21 +++++----
src/site/xdoc/changes.xml | 5 ++
src/site/xdoc/userguide/ode.xml | 16 +++----
.../apache/commons/math/ode/TestProblem4.java | 6 +++
.../commons/math/ode/TestProblemHandler.java | 7 ++-
.../math/ode/events/EventStateTest.java | 5 ++
.../ode/events/OverlappingEventsTest.java | 4 ++
.../math/ode/events/ReappearingEventTest.java | 4 ++
.../ClassicalRungeKuttaIntegratorTest.java | 9 ++--
.../DormandPrince54IntegratorTest.java | 7 ++-
.../DormandPrince54StepInterpolatorTest.java | 4 +-
.../DormandPrince853IntegratorTest.java | 12 +++--
.../DormandPrince853StepInterpolatorTest.java | 2 +-
.../ode/nonstiff/EulerIntegratorTest.java | 2 +-
.../math/ode/nonstiff/GillIntegratorTest.java | 5 +-
.../GraggBulirschStoerIntegratorTest.java | 12 +++--
...raggBulirschStoerStepInterpolatorTest.java | 2 +-
.../nonstiff/HighamHall54IntegratorTest.java | 4 ++
.../HighamHall54StepInterpolatorTest.java | 2 +-
.../ode/nonstiff/MidpointIntegratorTest.java | 2 +-
.../math/ode/nonstiff/StepProblem.java | 3 ++
.../nonstiff/ThreeEighthesIntegratorTest.java | 4 +-
.../sampling/StepInterpolatorTestUtils.java | 2 +-
34 files changed, 160 insertions(+), 116 deletions(-)
diff --git a/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java b/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
index e09a92206..fe121c97d 100644
--- a/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
@@ -91,7 +91,7 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator {
statesInitialized = false;
evaluations = new Incrementor();
setMaxEvaluations(-1);
- resetEvaluations();
+ evaluations.resetCount();
}
/** Build an instance with a null name.
@@ -179,10 +179,25 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator {
return evaluations.getCount();
}
- /** Reset the number of evaluations to zero.
+ /** Prepare the start of an integration.
+ * @param t0 start value of the independent time variable
+ * @param y0 array containing the start value of the state vector
+ * @param t target time for the integration
*/
- protected void resetEvaluations() {
+ protected void initIntegration(final double t0, final double[] y0, final double t) {
+
evaluations.resetCount();
+
+ for (final EventState state : eventsStates) {
+ state.getEventHandler().init(t0, y0, t);
+ }
+
+ for (StepHandler handler : stepHandlers) {
+ handler.init(t0, y0, t);
+ }
+
+ setStateInitialized(false);
+
}
/** Set the equations.
diff --git a/src/main/java/org/apache/commons/math/ode/ContinuousOutputModel.java b/src/main/java/org/apache/commons/math/ode/ContinuousOutputModel.java
index e8c6416b6..b240206d8 100644
--- a/src/main/java/org/apache/commons/math/ode/ContinuousOutputModel.java
+++ b/src/main/java/org/apache/commons/math/ode/ContinuousOutputModel.java
@@ -112,7 +112,10 @@ public class ContinuousOutputModel
*/
public ContinuousOutputModel() {
steps = new ArrayList();
- reset();
+ initialTime = Double.NaN;
+ finalTime = Double.NaN;
+ forward = true;
+ index = 0;
}
/** Append another model at the end of the instance.
@@ -163,17 +166,14 @@ public class ContinuousOutputModel
}
- /** Reset the step handler.
- * Initialize the internal data as required before the first step is
- * handled.
- */
- public void reset() {
+ /** {@inheritDoc} */
+ public void init(double t0, double[] y0, double t) {
initialTime = Double.NaN;
finalTime = Double.NaN;
forward = true;
index = 0;
steps.clear();
- }
+ }
/** Handle the last accepted step.
* A copy of the information provided by the last step is stored in
diff --git a/src/main/java/org/apache/commons/math/ode/MultistepIntegrator.java b/src/main/java/org/apache/commons/math/ode/MultistepIntegrator.java
index cfeb906e5..094cc0be0 100644
--- a/src/main/java/org/apache/commons/math/ode/MultistepIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/MultistepIntegrator.java
@@ -382,7 +382,7 @@ public abstract class MultistepIntegrator extends AdaptiveStepsizeIntegrator {
}
/** {@inheritDoc} */
- public void reset() {
+ public void init(double t0, double[] y0, double t) {
// nothing to do
}
diff --git a/src/main/java/org/apache/commons/math/ode/events/EventHandler.java b/src/main/java/org/apache/commons/math/ode/events/EventHandler.java
index 63e94b866..83e7f6054 100644
--- a/src/main/java/org/apache/commons/math/ode/events/EventHandler.java
+++ b/src/main/java/org/apache/commons/math/ode/events/EventHandler.java
@@ -87,6 +87,18 @@ public interface EventHandler {
}
+ /** Initialize event handler at the start of an ODE integration.
+ *
+ * This method is called once at the start of the integration. It
+ * may be used by the event handler to initialize some internal data
+ * if needed.
+ *
+ * @param t0 start value of the independent time variable
+ * @param y0 array containing the start value of the state vector
+ * @param t target time for the integration
+ */
+ void init(double t0, double[] y0, double t);
+
/** Compute the value of the switching function.
*
The discrete events are generated when the sign of this
diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsBashforthIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsBashforthIntegrator.java
index f4208cea5..3d1433fa8 100644
--- a/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsBashforthIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsBashforthIntegrator.java
@@ -22,7 +22,6 @@ import org.apache.commons.math.exception.MathIllegalStateException;
import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.ode.ExpandableStatefulODE;
import org.apache.commons.math.ode.sampling.NordsieckStepInterpolator;
-import org.apache.commons.math.ode.sampling.StepHandler;
import org.apache.commons.math.util.FastMath;
@@ -194,7 +193,6 @@ public class AdamsBashforthIntegrator extends AdamsIntegrator {
sanityChecks(equations, t);
setEquations(equations);
- resetEvaluations();
final boolean forward = t > equations.getTime();
// initialize working arrays
@@ -208,10 +206,7 @@ public class AdamsBashforthIntegrator extends AdamsIntegrator {
equations.getPrimaryMapper(), equations.getSecondaryMappers());
// set up integration control objects
- for (StepHandler handler : stepHandlers) {
- handler.reset();
- }
- setStateInitialized(false);
+ initIntegration(equations.getTime(), y0, t);
// compute the initial Nordsieck vector using the configured starter integrator
start(equations.getTime(), y, t);
diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsMoultonIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsMoultonIntegrator.java
index 362deb2f2..ffe30c795 100644
--- a/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsMoultonIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/nonstiff/AdamsMoultonIntegrator.java
@@ -25,7 +25,6 @@ import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.linear.RealMatrixPreservingVisitor;
import org.apache.commons.math.ode.ExpandableStatefulODE;
import org.apache.commons.math.ode.sampling.NordsieckStepInterpolator;
-import org.apache.commons.math.ode.sampling.StepHandler;
import org.apache.commons.math.util.FastMath;
@@ -211,7 +210,6 @@ public class AdamsMoultonIntegrator extends AdamsIntegrator {
sanityChecks(equations, t);
setEquations(equations);
- resetEvaluations();
final boolean forward = t > equations.getTime();
// initialize working arrays
@@ -228,10 +226,7 @@ public class AdamsMoultonIntegrator extends AdamsIntegrator {
equations.getPrimaryMapper(), equations.getSecondaryMappers());
// set up integration control objects
- for (StepHandler handler : stepHandlers) {
- handler.reset();
- }
- setStateInitialized(false);
+ initIntegration(equations.getTime(), y0, t);
// compute the initial Nordsieck vector using the configured starter integrator
start(equations.getTime(), y, t);
diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java
index 34d2c0073..13ced27d7 100644
--- a/src/main/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/nonstiff/EmbeddedRungeKuttaIntegrator.java
@@ -20,7 +20,6 @@ package org.apache.commons.math.ode.nonstiff;
import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.MathIllegalStateException;
import org.apache.commons.math.ode.ExpandableStatefulODE;
-import org.apache.commons.math.ode.sampling.StepHandler;
import org.apache.commons.math.util.FastMath;
/**
@@ -194,7 +193,6 @@ public abstract class EmbeddedRungeKuttaIntegrator
sanityChecks(equations, t);
setEquations(equations);
- resetEvaluations();
final boolean forward = t > equations.getTime();
// create some internal working arrays
@@ -215,10 +213,7 @@ public abstract class EmbeddedRungeKuttaIntegrator
stepStart = equations.getTime();
double hNew = 0;
boolean firstTime = true;
- for (StepHandler handler : stepHandlers) {
- handler.reset();
- }
- setStateInitialized(false);
+ initIntegration(equations.getTime(), y0, t);
// main integration loop
isLastStep = false;
diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java
index 2e92c2e00..873f50ca0 100644
--- a/src/main/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/nonstiff/GraggBulirschStoerIntegrator.java
@@ -546,7 +546,6 @@ public class GraggBulirschStoerIntegrator extends AdaptiveStepsizeIntegrator {
sanityChecks(equations, t);
setEquations(equations);
- resetEvaluations();
final boolean forward = t > equations.getTime();
// create some internal working arrays
@@ -613,10 +612,7 @@ public class GraggBulirschStoerIntegrator extends AdaptiveStepsizeIntegrator {
boolean firstTime = true;
boolean newStep = true;
boolean firstStepAlreadyComputed = false;
- for (StepHandler handler : stepHandlers) {
- handler.reset();
- }
- setStateInitialized(false);
+ initIntegration(equations.getTime(), y0, t);
costPerTimeUnit[0] = 0;
isLastStep = false;
do {
diff --git a/src/main/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java b/src/main/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java
index c51620c17..39a810f16 100644
--- a/src/main/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java
+++ b/src/main/java/org/apache/commons/math/ode/nonstiff/RungeKuttaIntegrator.java
@@ -22,7 +22,6 @@ import org.apache.commons.math.exception.MathIllegalArgumentException;
import org.apache.commons.math.exception.MathIllegalStateException;
import org.apache.commons.math.ode.AbstractIntegrator;
import org.apache.commons.math.ode.ExpandableStatefulODE;
-import org.apache.commons.math.ode.sampling.StepHandler;
import org.apache.commons.math.util.FastMath;
/**
@@ -96,7 +95,6 @@ public abstract class RungeKuttaIntegrator extends AbstractIntegrator {
sanityChecks(equations, t);
setEquations(equations);
- resetEvaluations();
final boolean forward = t > equations.getTime();
// create some internal working arrays
@@ -119,10 +117,7 @@ public abstract class RungeKuttaIntegrator extends AbstractIntegrator {
// set up integration control objects
stepStart = equations.getTime();
stepSize = forward ? step : -step;
- for (StepHandler handler : stepHandlers) {
- handler.reset();
- }
- setStateInitialized(false);
+ initIntegration(equations.getTime(), y0, t);
// main integration loop
isLastStep = false;
diff --git a/src/main/java/org/apache/commons/math/ode/sampling/DummyStepHandler.java b/src/main/java/org/apache/commons/math/ode/sampling/DummyStepHandler.java
index b2f0e3273..0369053b7 100644
--- a/src/main/java/org/apache/commons/math/ode/sampling/DummyStepHandler.java
+++ b/src/main/java/org/apache/commons/math/ode/sampling/DummyStepHandler.java
@@ -50,11 +50,8 @@ public class DummyStepHandler implements StepHandler {
return LazyHolder.INSTANCE;
}
- /** Reset the step handler.
- * Initialize the internal data as required before the first step is
- * handled.
- */
- public void reset() {
+ /** {@inheritDoc} */
+ public void init(double t0, double[] y0, double t) {
}
/**
diff --git a/src/main/java/org/apache/commons/math/ode/sampling/StepHandler.java b/src/main/java/org/apache/commons/math/ode/sampling/StepHandler.java
index f15ba4cd6..b3ac9f590 100644
--- a/src/main/java/org/apache/commons/math/ode/sampling/StepHandler.java
+++ b/src/main/java/org/apache/commons/math/ode/sampling/StepHandler.java
@@ -40,26 +40,32 @@ package org.apache.commons.math.ode.sampling;
public interface StepHandler {
- /** Reset the step handler.
- * Initialize the internal data as required before the first step is
- * handled.
- */
- void reset();
+ /** Initialize step handler at the start of an ODE integration.
+ *
+ * This method is called once at the start of the integration. It
+ * may be used by the step handler to initialize some internal data
+ * if needed.
+ *
+ * @param t0 start value of the independent time variable
+ * @param y0 array containing the start value of the state vector
+ * @param t target time for the integration
+ */
+ void init(double t0, double[] y0, double t);
- /**
- * Handle the last accepted step
- * @param interpolator interpolator for the last accepted step. For
- * efficiency purposes, the various integrators reuse the same
- * object on each call, so if the instance wants to keep it across
- * all calls (for example to provide at the end of the integration a
- * continuous model valid throughout the integration range, as the
- * {@link org.apache.commons.math.ode.ContinuousOutputModel
- * ContinuousOutputModel} class does), it should build a local copy
- * using the clone method of the interpolator and store this copy.
- * Keeping only a reference to the interpolator and reusing it will
- * result in unpredictable behavior (potentially crashing the application).
- * @param isLast true if the step is the last one
- */
- void handleStep(StepInterpolator interpolator, boolean isLast);
+ /**
+ * Handle the last accepted step
+ * @param interpolator interpolator for the last accepted step. For
+ * efficiency purposes, the various integrators reuse the same
+ * object on each call, so if the instance wants to keep it across
+ * all calls (for example to provide at the end of the integration a
+ * continuous model valid throughout the integration range, as the
+ * {@link org.apache.commons.math.ode.ContinuousOutputModel
+ * ContinuousOutputModel} class does), it should build a local copy
+ * using the clone method of the interpolator and store this copy.
+ * Keeping only a reference to the interpolator and reusing it will
+ * result in unpredictable behavior (potentially crashing the application).
+ * @param isLast true if the step is the last one
+ */
+ void handleStep(StepInterpolator interpolator, boolean isLast);
}
diff --git a/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java b/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
index e3d43dc4b..9aa0a5954 100644
--- a/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
+++ b/src/main/java/org/apache/commons/math/ode/sampling/StepNormalizer.java
@@ -161,18 +161,19 @@ public class StepNormalizer implements StepHandler {
public StepNormalizer(final double h, final FixedStepHandler handler,
final StepNormalizerMode mode,
final StepNormalizerBounds bounds) {
- this.h = FastMath.abs(h);
- this.handler = handler;
- this.mode = mode;
- this.bounds = bounds;
- reset();
+ this.h = FastMath.abs(h);
+ this.handler = handler;
+ this.mode = mode;
+ this.bounds = bounds;
+ firstTime = Double.NaN;
+ lastTime = Double.NaN;
+ lastState = null;
+ lastDerivatives = null;
+ forward = true;
}
- /** Reset the step handler.
- * Initialize the internal data as required before the first step is
- * handled.
- */
- public void reset() {
+ /** {@inheritDoc} */
+ public void init(double t0, double[] y0, double t) {
firstTime = Double.NaN;
lastTime = Double.NaN;
lastState = null;
diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml
index bf71dcd30..7969b0b6d 100644
--- a/src/site/xdoc/changes.xml
+++ b/src/site/xdoc/changes.xml
@@ -52,6 +52,11 @@ The type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces!
-->
+
+ The reset method in StepHandler interface has been renamed init and is provided
+ more information on the integration by the calling integrator. A similar init method
+ has been added to the EventHandler interface.
+
Improved accuracy of Runge-Kutta based step interpolators near step start.
diff --git a/src/site/xdoc/userguide/ode.xml b/src/site/xdoc/userguide/ode.xml
index 86f5b37aa..84561b4f4 100644
--- a/src/site/xdoc/userguide/ode.xml
+++ b/src/site/xdoc/userguide/ode.xml
@@ -128,7 +128,8 @@ dp853.integrate(ode, 0.0, y, 16.0, y); // now y contains final state at time t=1