Author: luc
Date: Wed Oct 26 09:08:22 2011
New Revision: 1189086

URL: http://svn.apache.org/viewvc?rev=1189086&view=rev
Log:
Fixed an event resetting issue in ODE.

When several discrete events occur during the same ODE integration step,
they are handled chronologically or reverse chronologically depending on
the integration direction. If one of the event truncates the step (for
example because its eventOccurred method returns RESET or
RESET_DERIVATIVES for example), the stepAccepted method of the pending
events later in the step were not called. This implied that in the next
step, these events were still referring to data from previous step, they
had lost synchronization with the integrator.

JIRA: MATH-695

Modified:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/ode/events/EventStateTest.java

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java?rev=1189086&r1=1189085&r2=1189086&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/ode/AbstractIntegrator.java
 Wed Oct 26 09:08:22 2011
@@ -40,7 +40,6 @@ import org.apache.commons.math.ode.sampl
 import org.apache.commons.math.ode.sampling.StepHandler;
 import org.apache.commons.math.util.FastMath;
 import org.apache.commons.math.util.Incrementor;
-import org.apache.commons.math.util.MathUtils;
 import org.apache.commons.math.util.Precision;
 
 /**
@@ -278,7 +277,6 @@ public abstract class AbstractIntegrator
 
             double previousT = interpolator.getGlobalPreviousTime();
             final double currentT = interpolator.getGlobalCurrentTime();
-            resetOccurred = false;
 
             // initialize the events states if needed
             if (! statesInitialized) {
@@ -332,6 +330,9 @@ public abstract class AbstractIntegrator
                 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;
                 }
 
@@ -341,6 +342,9 @@ public abstract class AbstractIntegrator
                     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;
                 }
 

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=1189086&r1=1189085&r2=1189086&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Wed Oct 26 09:08:22 2011
@@ -52,6 +52,9 @@ The <action> type attribute can be add,u
     If the output is not quite correct, check for invisible trailing spaces!
      -->
     <release version="3.0" date="TBD" description="TBD">
+      <action dev="luc" type="fix" issue="MATH-695">
+        Fixed an event resetting issue in ODE.
+      </action>
       <action dev="erans" type="update" issue="MATH-696">
         Default implementation for "addToEntry" and "multiplyEntry" in
         "AbstractRealMatrix".

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/ode/events/EventStateTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/ode/events/EventStateTest.java?rev=1189086&r1=1189085&r2=1189086&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/ode/events/EventStateTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/ode/events/EventStateTest.java
 Wed Oct 26 09:08:22 2011
@@ -19,6 +19,8 @@ package org.apache.commons.math.ode.even
 
 
 import org.apache.commons.math.analysis.solvers.BrentSolver;
+import org.apache.commons.math.ode.FirstOrderDifferentialEquations;
+import org.apache.commons.math.ode.nonstiff.DormandPrince853Integrator;
 import org.apache.commons.math.ode.sampling.AbstractStepInterpolator;
 import org.apache.commons.math.ode.sampling.DummyStepInterpolator;
 import org.junit.Assert;
@@ -73,4 +75,64 @@ public class EventStateTest {
 
     }
 
+    // Jira: MATH-695
+    @Test
+    public void testIssue695() {
+
+        FirstOrderDifferentialEquations equation = new 
FirstOrderDifferentialEquations() {
+            
+            public int getDimension() {
+                return 1;
+            }
+            
+            public void computeDerivatives(double t, double[] y, double[] 
yDot) {
+                yDot[0] = 1.0;
+            }
+        };
+
+        DormandPrince853Integrator integrator = new 
DormandPrince853Integrator(0.001, 1000, 1.0e-14, 1.0e-14);
+        integrator.addEventHandler(new ResettingEvent(10.99), 0.1, 1.0e-9, 
1000);
+        integrator.addEventHandler(new ResettingEvent(11.01), 0.1, 1.0e-9, 
1000);
+        integrator.setInitialStepSize(3.0);
+
+        double target = 30.0;
+        double[] y = new double[1];
+        double tEnd = integrator.integrate(equation, 0.0, y, target, y);
+        Assert.assertEquals(target, tEnd, 1.0e-10);
+        Assert.assertEquals(32.0, y[0], 1.0e-10);
+
+    }
+
+    private static class ResettingEvent implements EventHandler {
+
+        private static double lastTriggerTime = Double.NEGATIVE_INFINITY;
+        private final double tEvent;
+
+        public ResettingEvent(final double tEvent) {
+            this.tEvent = tEvent;
+        }
+
+        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
+            // occurring later has already been triggered.
+            // When this occurs, the following assertion is violated
+            Assert.assertTrue("going backard in time! (" + t + " < " + 
lastTriggerTime + ")",
+                              t >= lastTriggerTime);
+            return t - tEvent;
+        }
+
+        public Action eventOccurred(double t, double[] y, boolean increasing) {
+            // remember in a class variable when the event was triggered
+            lastTriggerTime = t;
+            return Action.RESET_STATE;
+        }
+
+        public void resetState(double t, double[] y) {
+            y[0] += 1.0;
+        }
+
+    };
+
+
 }


Reply via email to