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
This commit is contained in:
Luc Maisonobe 2011-11-28 10:20:51 +00:00
parent b789d44c4c
commit 6041336783
34 changed files with 160 additions and 116 deletions

View File

@ -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 <i>time</i> 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.

View File

@ -112,7 +112,10 @@ public class ContinuousOutputModel
*/
public ContinuousOutputModel() {
steps = new ArrayList<StepInterpolator>();
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

View File

@ -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
}

View File

@ -87,6 +87,18 @@ public interface EventHandler {
}
/** Initialize event handler at the start of an ODE integration.
* <p>
* 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.
* </p>
* @param t0 start value of the independent <i>time</i> 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.
* <p>The discrete events are generated when the sign of this

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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) {
}
/**

View File

@ -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.
* <p>
* 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.
* </p>
* @param t0 start value of the independent <i>time</i> 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);
}

View File

@ -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;

View File

@ -52,6 +52,11 @@ The <action> type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces!
-->
<release version="3.0" date="TBD" description="TBD">
<action dev="luc" type="add" issue="MATH-714">
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.
</action>
<action dev="luc" type="fix" issue="MATH-705">
Improved accuracy of Runge-Kutta based step interpolators near step start.
</action>

View File

@ -128,7 +128,8 @@ dp853.integrate(ode, 0.0, y, 16.0, y); // now y contains final state at time t=1
</p>
<source>
StepHandler stepHandler = new StepHandler() {
public void reset() {}
public void init(double t0, double[] y0, double t) {
}
public void handleStep(StepInterpolator interpolator, boolean isLast) {
double t = interpolator.getCurrentTime();
@ -182,15 +183,10 @@ integrator.addStepHandler(stepHandler);
a simple <a href="../apidocs/org/apache/commons/math/ode/events/EventHandler.html">g(t, y)</a>
function depending on the current time and state. The integrator will monitor
the value of the function throughout integration range and will trigger the
event when its sign changes. The magnitude of the value is almost irrelevant,
it should however be continuous (but not necessarily smooth) for the sake of
root finding. The steps are shortened as needed to ensure the events occur
at step boundaries (even if the integrator is a fixed-step integrator). Note that
g function signs changes at the very beginning of the integration (from t<sub>0</sub>
to t<sub>0</sub> + &#x3b5; where &#x3b5; is the events detection convergence threshold)
are explicitely ignored. This prevents having the integration stuck at its
initial point when a new integration is restarted just at the same point a
previous one had been stopped by an event.
event when its sign changes. The magnitude of the value is almost irrelevant.
For the sake of root finding, it should however be continuous (but not necessarily smooth)
at least in the roots vicinity. The steps are shortened as needed to ensure the events occur
at step boundaries (even if the integrator is a fixed-step integrator).
</p>
<p>
When an event is triggered, the event time, current state and an indicator

View File

@ -115,6 +115,9 @@ public TestProblem4 copy() {
sign = +1;
}
public void init(double t0, double[] y0, double t) {
}
public double g(double t, double[] y) {
return sign * y[0];
}
@ -137,6 +140,9 @@ public TestProblem4 copy() {
public Stop() {
}
public void init(double t0, double[] y0, double t) {
}
public double g(double t, double[] y) {
return t - 12.0;
}

View File

@ -55,10 +55,13 @@ public class TestProblemHandler
public TestProblemHandler(TestProblemAbstract problem, ODEIntegrator integrator) {
this.problem = problem;
this.integrator = integrator;
reset();
maxValueError = 0;
maxTimeError = 0;
lastError = 0;
expectedStepStart = Double.NaN;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
maxValueError = 0;
maxTimeError = 0;
lastError = 0;

View File

@ -36,6 +36,8 @@ public class EventStateTest {
final double r2 = 135.0;
final double gap = r2 - r1;
EventHandler closeEventsGenerator = new EventHandler() {
public void init(double t0, double[] y0, double t) {
}
public void resetState(double t, double[] y) {
}
public double g(double t, double[] y) {
@ -112,6 +114,9 @@ public class EventStateTest {
this.tEvent = tEvent;
}
public void init(double t0, double[] y0, double t) {
}
public double g(double t, double[] y) {
// the bug corresponding to issue 695 causes the g function
// to be called at obsolete times t despite an event

View File

@ -135,6 +135,10 @@ public class OverlappingEventsTest implements FirstOrderDifferentialEquations {
this.eventType = eventType;
}
/** {@inheritDoc} */
public void init(double t0, double[] y0, double t) {
}
/** {@inheritDoc} */
public double g(double t, double[] y) {
return (eventType == 0) ? y[idx] >= 1.0 ? 1.0 : -1.0

View File

@ -67,6 +67,10 @@ public class ReappearingEventTest {
/** State events for this unit test. */
protected static class Event implements EventHandler {
public void init(double t0, double[] y0, double t) {
}
public double g(double t, double[] y) {
return y[6] - 15.0;
}

View File

@ -71,6 +71,9 @@ public class ClassicalRungeKuttaIntegratorTest {
integrator.addEventHandler(new EventHandler() {
public void init(double t0, double[] y0, double t) {
}
public void resetState(double t, double[] y) {
}
@ -242,9 +245,9 @@ public class ClassicalRungeKuttaIntegratorTest {
private static class KeplerHandler implements StepHandler {
public KeplerHandler(TestProblem3 pb) {
this.pb = pb;
reset();
maxError = 0;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
maxError = 0;
}
public void handleStep(StepInterpolator interpolator, boolean isLast) {
@ -281,7 +284,7 @@ public class ClassicalRungeKuttaIntegratorTest {
1.0e-12);
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(new FirstOrderDifferentialEquations() {

View File

@ -124,7 +124,7 @@ public class DormandPrince54IntegratorTest {
this.minStep = minStep;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
public void handleStep(StepInterpolator interpolator, boolean isLast) {
@ -265,9 +265,8 @@ public class DormandPrince54IntegratorTest {
private static class KeplerHandler implements StepHandler {
public KeplerHandler(TestProblem3 pb) {
this.pb = pb;
reset();
}
public void reset() {
public void init(double t0, double[] y0, double t) {
nbSteps = 0;
maxError = 0;
}
@ -306,7 +305,7 @@ public class DormandPrince54IntegratorTest {
minStep = 0;
maxStep = 0;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
firstTime = true;
minStep = 0;
maxStep = 0;

View File

@ -112,7 +112,7 @@ public class DormandPrince54StepInterpolatorTest {
scalAbsoluteTolerance,
scalRelativeTolerance);
integ.addStepHandler(new StepHandler() {
public void handleStep(StepInterpolator interpolator, boolean isLast) {
public void handleStep(StepInterpolator interpolator, boolean isLast) {
StepInterpolator cloned = interpolator.copy();
double tA = cloned.getPreviousTime();
double tB = cloned.getCurrentTime();
@ -132,7 +132,7 @@ public class DormandPrince54StepInterpolatorTest {
}
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(pb,

View File

@ -73,6 +73,9 @@ public class DormandPrince853IntegratorTest {
integrator.setInitialStepSize(60.0);
integrator.addEventHandler(new EventHandler() {
public void init(double t0, double[] y0, double t) {
}
public void resetState(double t, double[] y) {
}
@ -289,9 +292,8 @@ public class DormandPrince853IntegratorTest {
private static class KeplerHandler implements StepHandler {
public KeplerHandler(TestProblem3 pb) {
this.pb = pb;
reset();
}
public void reset() {
public void init(double t0, double[] y0, double t) {
nbSteps = 0;
maxError = 0;
}
@ -326,9 +328,11 @@ public class DormandPrince853IntegratorTest {
private static class VariableHandler implements StepHandler {
public VariableHandler() {
reset();
firstTime = true;
minStep = 0;
maxStep = 0;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
firstTime = true;
minStep = 0;
maxStep = 0;

View File

@ -132,7 +132,7 @@ public class DormandPrince853StepInterpolatorTest {
}
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(pb,

View File

@ -163,7 +163,7 @@ public class EulerIntegratorTest {
1.0e-12);
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(new FirstOrderDifferentialEquations() {

View File

@ -177,9 +177,8 @@ public class GillIntegratorTest {
private static class KeplerStepHandler implements StepHandler {
public KeplerStepHandler(TestProblem3 pb) {
this.pb = pb;
reset();
}
public void reset() {
public void init(double t0, double[] y0, double t) {
maxError = 0;
}
public void handleStep(StepInterpolator interpolator, boolean isLast) {
@ -216,7 +215,7 @@ public class GillIntegratorTest {
1.0e-12);
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(new FirstOrderDifferentialEquations() {

View File

@ -271,7 +271,8 @@ public class GraggBulirschStoerIntegratorTest {
FirstOrderIntegrator integ = new GraggBulirschStoerIntegrator(1e-10, 100.0, 1e-7, 1e-7);
integ.addStepHandler(new StepHandler() {
public void reset() {}
public void init(double t0, double[] y0, double t) {
}
public void handleStep(StepInterpolator interpolator, boolean isLast) {
double t = interpolator.getCurrentTime();
@ -300,9 +301,8 @@ public class GraggBulirschStoerIntegratorTest {
private static class KeplerStepHandler implements StepHandler {
public KeplerStepHandler(TestProblem3 pb) {
this.pb = pb;
reset();
}
public void reset() {
public void init(double t0, double[] y0, double t) {
nbSteps = 0;
maxError = 0;
}
@ -337,9 +337,11 @@ public class GraggBulirschStoerIntegratorTest {
public static class VariableStepHandler implements StepHandler {
public VariableStepHandler() {
reset();
firstTime = true;
minStep = 0;
maxStep = 0;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
firstTime = true;
minStep = 0;
maxStep = 0;

View File

@ -134,7 +134,7 @@ public class GraggBulirschStoerStepInterpolatorTest {
}
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(pb,

View File

@ -202,6 +202,8 @@ public class HighamHall54IntegratorTest {
integ.addStepHandler(handler);
integ.addEventHandler(new EventHandler() {
public void init(double t0, double[] y0, double t) {
}
public Action eventOccurred(double t, double[] y, boolean increasing) {
return Action.CONTINUE;
}
@ -246,6 +248,8 @@ public class HighamHall54IntegratorTest {
integ.addStepHandler(handler);
integ.addEventHandler(new EventHandler() {
public void init(double t0, double[] y0, double t) {
}
public Action eventOccurred(double t, double[] y, boolean increasing) {
return Action.CONTINUE;
}

View File

@ -132,7 +132,7 @@ public class HighamHall54StepInterpolatorTest {
}
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(pb,

View File

@ -163,7 +163,7 @@ public class MidpointIntegratorTest {
1.0e-12);
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(new FirstOrderDifferentialEquations() {

View File

@ -43,6 +43,9 @@ public class StepProblem
this.rate = rate;
}
public void init(double t0, double[] y0, double t) {
}
public Action eventOccurred(double t, double[] y, boolean increasing) {
setRate(rateAfter);
return Action.RESET_DERIVATIVES;

View File

@ -170,7 +170,7 @@ public class ThreeEighthesIntegratorTest {
maxError = 0;
}
public void reset() {
public void init(double t0, double[] y0, double t) {
maxError = 0;
}
@ -210,7 +210,7 @@ public class ThreeEighthesIntegratorTest {
1.0e-12);
}
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});
integ.integrate(new FirstOrderDifferentialEquations() {

View File

@ -68,7 +68,7 @@ public class StepInterpolatorTestUtils {
}
public void reset() {
public void init(double t0, double[] y0, double t) {
}
});