Fixed missing update in ODE event handlers.
When a RESET_STATE was triggered, event states for events not triggered in the same step were not updated properly. JIRA: MATH-950 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1458294 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d18a6b8510
commit
424cbd201c
|
@ -55,6 +55,9 @@ This is a minor release: It combines bug fixes and new features.
|
|||
Changes to existing features were made in a backwards-compatible
|
||||
way such as to allow drop-in replacement of the v3.1[.1] JAR file.
|
||||
">
|
||||
<action dev="luc" type="fix" issue="MATH-950" >
|
||||
Fixed missing update in ODE event handlers, when a RESET_STATE is triggered.
|
||||
</action>
|
||||
<action dev="psteitz" type="update" issue="MATH-671">
|
||||
Made EmpiricalDisribution smoothing kernel pluggable.
|
||||
</action>
|
||||
|
|
|
@ -338,11 +338,15 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator {
|
|||
interpolator.setSoftPreviousTime(previousT);
|
||||
interpolator.setSoftCurrentTime(eventT);
|
||||
|
||||
// trigger the event
|
||||
// get state at event time
|
||||
interpolator.setInterpolatedTime(eventT);
|
||||
final double[] eventY = interpolator.getInterpolatedState().clone();
|
||||
currentEvent.stepAccepted(eventT, eventY);
|
||||
isLastStep = currentEvent.stop();
|
||||
|
||||
// advance all event states to current time
|
||||
for (final EventState state : eventsStates) {
|
||||
state.stepAccepted(eventT, eventY);
|
||||
isLastStep = isLastStep || state.stop();
|
||||
}
|
||||
|
||||
// handle the first part of the step, up to the event
|
||||
for (final StepHandler handler : stepHandlers) {
|
||||
|
@ -352,21 +356,19 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator {
|
|||
if (isLastStep) {
|
||||
// the event asked to stop integration
|
||||
System.arraycopy(eventY, 0, y, 0, y.length);
|
||||
for (final EventState remaining : occuringEvents) {
|
||||
remaining.stepAccepted(eventT, eventY);
|
||||
}
|
||||
return eventT;
|
||||
}
|
||||
|
||||
if (currentEvent.reset(eventT, eventY)) {
|
||||
boolean needReset = false;
|
||||
for (final EventState state : eventsStates) {
|
||||
needReset = needReset || state.reset(eventT, eventY);
|
||||
}
|
||||
if (needReset) {
|
||||
// some event handler has triggered changes that
|
||||
// invalidate the derivatives, we need to recompute them
|
||||
System.arraycopy(eventY, 0, y, 0, y.length);
|
||||
computeDerivatives(eventT, y, yDot);
|
||||
resetOccurred = true;
|
||||
for (final EventState remaining : occuringEvents) {
|
||||
remaining.stepAccepted(eventT, eventY);
|
||||
}
|
||||
return eventT;
|
||||
}
|
||||
|
||||
|
@ -383,6 +385,7 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator {
|
|||
|
||||
}
|
||||
|
||||
// last part of the step, after the last event
|
||||
interpolator.setInterpolatedTime(currentT);
|
||||
final double[] currentY = interpolator.getInterpolatedState();
|
||||
for (final EventState state : eventsStates) {
|
||||
|
|
|
@ -333,6 +333,73 @@ public class DormandPrince853IntegratorTest {
|
|||
Assert.assertEquals(8.0, y[0], 1.0e-12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventsScheduling() {
|
||||
|
||||
FirstOrderDifferentialEquations sincos = new FirstOrderDifferentialEquations() {
|
||||
|
||||
public int getDimension() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
public void computeDerivatives(double t, double[] y, double[] yDot) {
|
||||
yDot[0] = y[1];
|
||||
yDot[1] = -y[0];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SchedulingChecker sinChecker = new SchedulingChecker(0); // events at 0, PI, 2PI ...
|
||||
SchedulingChecker cosChecker = new SchedulingChecker(1); // events at PI/2, 3PI/2, 5PI/2 ...
|
||||
|
||||
FirstOrderIntegrator integ =
|
||||
new DormandPrince853Integrator(0.001, 1.0, 1.0e-12, 0.0);
|
||||
integ.addEventHandler(sinChecker, 0.01, 1.0e-7, 100);
|
||||
integ.addStepHandler(sinChecker);
|
||||
integ.addEventHandler(cosChecker, 0.01, 1.0e-7, 100);
|
||||
integ.addStepHandler(cosChecker);
|
||||
double t0 = 0.5;
|
||||
double[] y0 = new double[] { FastMath.sin(t0), FastMath.cos(t0) };
|
||||
double t = 10.0;
|
||||
double[] y = new double[2];
|
||||
integ.integrate(sincos, t0, y0, t, y);
|
||||
|
||||
}
|
||||
|
||||
private static class SchedulingChecker implements StepHandler, EventHandler {
|
||||
|
||||
int index;
|
||||
double tMin;
|
||||
|
||||
public SchedulingChecker(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void init(double t0, double[] y0, double t) {
|
||||
tMin = t0;
|
||||
}
|
||||
|
||||
public void handleStep(StepInterpolator interpolator, boolean isLast) {
|
||||
tMin = interpolator.getCurrentTime();
|
||||
}
|
||||
|
||||
public double g(double t, double[] y) {
|
||||
// once a step has been handled by handleStep,
|
||||
// events checking should only refer to dates after the step
|
||||
Assert.assertTrue(t >= tMin);
|
||||
return y[index];
|
||||
}
|
||||
|
||||
public Action eventOccurred(double t, double[] y, boolean increasing) {
|
||||
return Action.RESET_STATE;
|
||||
}
|
||||
|
||||
public void resetState(double t, double[] y) {
|
||||
// in fact, we don't need to reset anything for the test
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class KeplerHandler implements StepHandler {
|
||||
public KeplerHandler(TestProblem3 pb) {
|
||||
this.pb = pb;
|
||||
|
|
Loading…
Reference in New Issue