You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2013/03/19 15:09:08 UTC

svn commit: r1458294 - in /commons/proper/math/trunk/src: changes/changes.xml main/java/org/apache/commons/math3/ode/AbstractIntegrator.java test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java

Author: luc
Date: Tue Mar 19 14:09:08 2013
New Revision: 1458294

URL: http://svn.apache.org/r1458294
Log:
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

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1458294&r1=1458293&r2=1458294&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Tue Mar 19 14:09:08 2013
@@ -55,6 +55,9 @@ This is a minor release: It combines bug
   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>

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java?rev=1458294&r1=1458293&r2=1458294&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java Tue Mar 19 14:09:08 2013
@@ -338,11 +338,15 @@ public abstract class AbstractIntegrator
                 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
                 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
 
             }
 
+            // last part of the step, after the last event
             interpolator.setInterpolatedTime(currentT);
             final double[] currentY = interpolator.getInterpolatedState();
             for (final EventState state : eventsStates) {

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java?rev=1458294&r1=1458293&r2=1458294&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853IntegratorTest.java Tue Mar 19 14:09:08 2013
@@ -333,6 +333,73 @@ public class DormandPrince853IntegratorT
     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;