Repository: commons-math
Updated Branches:
  refs/heads/master cf571ba2a -> c44bfe000


Fixed wrong event detection in case of close events pairs.

JIRA: MATH-1226


Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/c44bfe00
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/c44bfe00
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/c44bfe00

Branch: refs/heads/master
Commit: c44bfe000cd84d0b48401f8c7107bc37c09ec622
Parents: cf571ba
Author: Luc Maisonobe <l...@apache.org>
Authored: Tue May 19 13:18:32 2015 +0200
Committer: Luc Maisonobe <l...@apache.org>
Committed: Tue May 19 13:18:32 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |  3 +
 .../commons/math4/ode/events/EventState.java    | 13 +++-
 .../math4/ode/events/EventStateTest.java        | 74 ++++++++++++++++----
 3 files changed, 76 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/c44bfe00/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 66f0175..228a7f3 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,6 +54,9 @@ If the output is not quite correct, check for invisible 
trailing spaces!
     </release>
 
     <release version="4.0" date="XXXX-XX-XX" description="">
+      <action dev="luc" type="fix" issue="MATH-1226"> <!-- backported to 3.6 
-->
+        Fixed wrong event detection in case of close events pairs.
+      </action>
       <action dev="luc" type="add" >
         Reimplemented pow(double, double) in FastMath, for better accuracy in
         integral power cases and trying to fix erroneous JIT optimization 
again.

http://git-wip-us.apache.org/repos/asf/commons-math/blob/c44bfe00/src/main/java/org/apache/commons/math4/ode/events/EventState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math4/ode/events/EventState.java 
b/src/main/java/org/apache/commons/math4/ode/events/EventState.java
index fe3039a..1908440 100644
--- a/src/main/java/org/apache/commons/math4/ode/events/EventState.java
+++ b/src/main/java/org/apache/commons/math4/ode/events/EventState.java
@@ -296,7 +296,18 @@ public class EventState {
                             ta = forward ? ta + convergence : ta - convergence;
                             ga = f.value(ta);
                         } while ((g0Positive ^ (ga >= 0)) && (forward ^ (ta >= 
tb)));
-                        --i;
+
+                        if (forward ^ (ta >= tb)) {
+                            // we were able to skip this spurious root
+                            --i;
+                        } else {
+                            // we can't avoid this root before the end of the 
step,
+                            // we have to handle it despite it is close to the 
former one
+                            // maybe we have two very close roots
+                            pendingEventTime = root;
+                            pendingEvent = true;
+                            return true;
+                        }
                     } else if (Double.isNaN(previousEventTime) ||
                                (FastMath.abs(previousEventTime - root) > 
convergence)) {
                         pendingEventTime = root;

http://git-wip-us.apache.org/repos/asf/commons-math/blob/c44bfe00/src/test/java/org/apache/commons/math4/ode/events/EventStateTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/math4/ode/events/EventStateTest.java 
b/src/test/java/org/apache/commons/math4/ode/events/EventStateTest.java
index b2041dc..bbb2bc5 100644
--- a/src/test/java/org/apache/commons/math4/ode/events/EventStateTest.java
+++ b/src/test/java/org/apache/commons/math4/ode/events/EventStateTest.java
@@ -29,6 +29,7 @@ import org.apache.commons.math4.ode.SecondaryEquations;
 import org.apache.commons.math4.ode.events.EventHandler;
 import org.apache.commons.math4.ode.events.EventState;
 import org.apache.commons.math4.ode.nonstiff.DormandPrince853Integrator;
+import org.apache.commons.math4.ode.nonstiff.LutherIntegrator;
 import org.apache.commons.math4.ode.sampling.AbstractStepInterpolator;
 import org.apache.commons.math4.ode.sampling.DummyStepInterpolator;
 import org.junit.Assert;
@@ -43,21 +44,9 @@ public class EventStateTest {
         final double r1  = 90.0;
         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) {
-                return (t - r1) * (r2 - t);
-            }
-            public Action eventOccurred(double t, double[] y, boolean 
increasing) {
-                return Action.CONTINUE;
-            }
-        };
 
         final double tolerance = 0.1;
-        EventState es = new EventState(closeEventsGenerator, 1.5 * gap,
+        EventState es = new EventState(new CloseEventsGenerator(r1, r2), 1.5 * 
gap,
                                        tolerance, 100,
                                        new BrentSolver(tolerance));
         es.setExpandable(new ExpandableStatefulODE(new 
FirstOrderDifferentialEquations() {
@@ -226,4 +215,63 @@ public class EventStateTest {
 
     }
 
+    @Test
+    public void testEventsCloserThanThreshold()
+        throws DimensionMismatchException, NumberIsTooSmallException,
+               MaxCountExceededException, NoBracketingException {
+
+        FirstOrderDifferentialEquations equation = new 
FirstOrderDifferentialEquations() {
+            
+            public int getDimension() {
+                return 1;
+            }
+            
+            public void computeDerivatives(double t, double[] y, double[] 
yDot) {
+                yDot[0] = 1.0;
+            }
+        };
+
+        LutherIntegrator integrator = new LutherIntegrator(20.0);
+        CloseEventsGenerator eventsGenerator =
+                        new CloseEventsGenerator(9.0 - 1.0 / 128, 9.0 + 1.0 / 
128);
+        integrator.addEventHandler(eventsGenerator, 1.0, 0.02, 1000);
+        double[] y = new double[1];
+        double tEnd = integrator.integrate(equation, 0.0, y, 100.0, y);
+        Assert.assertEquals( 2, eventsGenerator.getCount());
+        Assert.assertEquals( 9.0 + 1.0 / 128, tEnd, 1.0 / 32.0);
+
+    }
+
+    private class CloseEventsGenerator implements EventHandler {
+
+        final double r1;
+        final double r2;
+        int count;
+
+        public CloseEventsGenerator(final double r1, final double r2) {
+            this.r1    = r1;
+            this.r2    = r2;
+            this.count = 0;
+        }
+
+        public void init(double t0, double[] y0, double t) {
+        }
+
+        public void resetState(double t, double[] y) {
+        }
+
+        public double g(double t, double[] y) {
+            return (t - r1) * (r2 - t);
+        }
+
+        public Action eventOccurred(double t, double[] y, boolean increasing) {
+            return ++count < 2 ? Action.CONTINUE : Action.STOP;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+    }
+
 }

Reply via email to