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 2015/05/19 13:26:46 UTC

[math] Fixed wrong event detection in case of close events pairs.

Repository: commons-math
Updated Branches:
  refs/heads/MATH_3_X 01673c2ce -> 777273e23


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/777273e2
Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/777273e2
Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/777273e2

Branch: refs/heads/MATH_3_X
Commit: 777273e23f825d659695a4d69fca29eeba31cf37
Parents: 01673c2
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue May 19 13:26:33 2015 +0200
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue May 19 13:26:33 2015 +0200

----------------------------------------------------------------------
 src/changes/changes.xml                         |  5 +-
 .../commons/math3/ode/events/EventState.java    | 13 +++-
 .../math3/ode/events/EventStateTest.java        | 74 ++++++++++++++++----
 3 files changed, 77 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/777273e2/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3f1920b..d38f022 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -51,7 +51,10 @@ If the output is not quite correct, check for invisible trailing spaces!
   </properties>
   <body>
     <release version="3.6" date="XXXX-XX-XX" description="">
-      <action dev="tn" type="fix"> <!-- backported to 3.6 -->
+      <action dev="luc" type="fix" issue="MATH-1226">
+        Fixed wrong event detection in case of close events pairs.
+      </action>
+      <action dev="tn" type="fix">
         Fix potential branching errors in "FastMath#pow(double, double)" when
         passing special values, i.e. infinity, due to erroneous JIT optimization.
       </action>    

http://git-wip-us.apache.org/repos/asf/commons-math/blob/777273e2/src/main/java/org/apache/commons/math3/ode/events/EventState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/events/EventState.java b/src/main/java/org/apache/commons/math3/ode/events/EventState.java
index 76dae72..6d34266 100644
--- a/src/main/java/org/apache/commons/math3/ode/events/EventState.java
+++ b/src/main/java/org/apache/commons/math3/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/777273e2/src/test/java/org/apache/commons/math3/ode/events/EventStateTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/events/EventStateTest.java b/src/test/java/org/apache/commons/math3/ode/events/EventStateTest.java
index 6468fdc..4a8091f 100644
--- a/src/test/java/org/apache/commons/math3/ode/events/EventStateTest.java
+++ b/src/test/java/org/apache/commons/math3/ode/events/EventStateTest.java
@@ -27,6 +27,7 @@ import org.apache.commons.math3.ode.ExpandableStatefulODE;
 import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
 import org.apache.commons.math3.ode.SecondaryEquations;
 import org.apache.commons.math3.ode.nonstiff.DormandPrince853Integrator;
+import org.apache.commons.math3.ode.nonstiff.LutherIntegrator;
 import org.apache.commons.math3.ode.sampling.AbstractStepInterpolator;
 import org.apache.commons.math3.ode.sampling.DummyStepInterpolator;
 import org.junit.Assert;
@@ -41,21 +42,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() {
@@ -224,4 +213,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;
+        }
+
+    }
+
 }