From 5a2bf9c6570a96383386039cd4ab7aa0c8a0b7eb Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Mon, 14 Feb 2011 14:19:55 +0000 Subject: [PATCH] second attempt at fixing MATH-484 This fixes bad behavior when several events occur during a long step This also fixes bad behavior when events are triggered during backward integration Jira: MATH-484 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1070499 13f79535-47bb-0310-9956-ffa450edef68 --- .../commons/math/ode/AbstractIntegrator.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 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 c34b29440..63ff091b1 100644 --- a/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java +++ b/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.Iterator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; @@ -245,16 +246,17 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator { statesInitialized = true; } + // search for next events that may occur during the step + final int orderingSign = interpolator.isForward() ? +1 : -1; SortedSet occuringEvents = new TreeSet(new Comparator() { /** {@inheritDoc} */ public int compare(EventState es0, EventState es1) { - return Double.compare(es0.getEventTime(), es1.getEventTime()); + return orderingSign * Double.compare(es0.getEventTime(), es1.getEventTime()); } }); - // find all events that occur during the step for (final EventState state : eventsStates) { if (state.evaluateStep(interpolator)) { // the event occurs during the current step @@ -262,19 +264,23 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator { } } - // handle the events chronologically - for (final EventState state : occuringEvents) { + while (!occuringEvents.isEmpty()) { + + // handle the chronologically first event + final Iterator iterator = occuringEvents.iterator(); + final EventState currentEvent = iterator.next(); + iterator.remove(); // restrict the interpolator to the first part of the step, up to the event - final double eventT = state.getEventTime(); + final double eventT = currentEvent.getEventTime(); interpolator.setSoftPreviousTime(previousT); interpolator.setSoftCurrentTime(eventT); // trigger the event interpolator.setInterpolatedTime(eventT); final double[] eventY = interpolator.getInterpolatedState(); - state.stepAccepted(eventT, eventY); - isLastStep = state.stop(); + currentEvent.stepAccepted(eventT, eventY); + isLastStep = currentEvent.stop(); // handle the first part of the step, up to the event for (final StepHandler handler : stepHandlers) { @@ -287,7 +293,7 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator { return eventT; } - if (state.reset(eventT, eventY)) { + if (currentEvent.reset(eventT, eventY)) { // some event handler has triggered changes that // invalidate the derivatives, we need to recompute them System.arraycopy(eventY, 0, y, 0, y.length); @@ -301,6 +307,12 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator { interpolator.setSoftPreviousTime(eventT); interpolator.setSoftCurrentTime(currentT); + // check if the same event occurs again in the remaining part of the step + if (currentEvent.evaluateStep(interpolator)) { + // the event occurs during the current step + occuringEvents.add(currentEvent); + } + } interpolator.setInterpolatedTime(currentT);