commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From evanw...@apache.org
Subject [math] Fix ODE integration with close events
Date Thu, 17 Mar 2016 12:17:55 GMT
Repository: commons-math
Updated Branches:
  refs/heads/MATH_3_X d69fb7113 -> 5238b0087


Fix ODE integration with close events

Previously integration would crash when two event detectors triggered events
within the root finder's tolerance of each other. Now all events are handled
in order and integration proceeds.


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

Branch: refs/heads/MATH_3_X
Commit: 5238b008798997de8581c11bb17e9ae23008bb03
Parents: d69fb71
Author: Evan Ward <evan.ward@nrl.navy.mil>
Authored: Wed Mar 16 11:36:05 2016 -0400
Committer: Evan Ward <evan.ward@nrl.navy.mil>
Committed: Wed Mar 16 11:49:37 2016 -0400

----------------------------------------------------------------------
 .../commons/math3/ode/AbstractIntegrator.java   |   4 +-
 .../math3/ode/events/CloseEventsTest.java       | 127 +++++++++++++++++++
 2 files changed, 128 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/5238b008/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java b/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
index f5d7260..4b2b741 100644
--- a/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/AbstractIntegrator.java
@@ -395,9 +395,7 @@ public abstract class AbstractIntegrator implements FirstOrderIntegrator
{
 
                 boolean needReset = false;
                 resetOccurred = false;
-                for (final EventState state : eventsStates) {
-                    needReset =  needReset || state.reset(eventT, eventYComplete);
-                }
+                needReset = currentEvent.reset(eventT, eventYComplete);
                 if (needReset) {
                     // some event handler has triggered changes that
                     // invalidate the derivatives, we need to recompute them

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5238b008/src/test/java/org/apache/commons/math3/ode/events/CloseEventsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/events/CloseEventsTest.java b/src/test/java/org/apache/commons/math3/ode/events/CloseEventsTest.java
new file mode 100644
index 0000000..90ce9a6
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/events/CloseEventsTest.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.ode.events;
+
+import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
+import org.apache.commons.math3.ode.FirstOrderIntegrator;
+import org.apache.commons.math3.ode.nonstiff.DormandPrince853Integrator;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Check events are detected correctly when the event times are close.
+ *
+ * @author Evan Ward
+ */
+public class CloseEventsTest {
+
+    @Test
+    public void testCloseEvents() {
+        // setup
+        double e = 1e-15;
+        FirstOrderIntegrator integrator =
+                new DormandPrince853Integrator(e, 100.0, 1e-7, 1e-7);
+
+        TimeDetector detector1 = new TimeDetector(5);
+        integrator.addEventHandler(detector1, 10, 1, 100);
+        TimeDetector detector2 = new TimeDetector(5.5);
+        integrator.addEventHandler(detector2, 10, 1, 100);
+
+        // action
+        integrator.integrate(new Equation(), 0, new double[2], 20, new double[2]);
+
+        // verify
+        Assert.assertEquals(5, detector1.getActualT(), 0.0);
+        Assert.assertEquals(5.5, detector2.getActualT(), 0.0);
+    }
+
+    @Test
+    public void testSimultaneousEvents() {
+        // setup
+        double e = 1e-15;
+        FirstOrderIntegrator integrator =
+                new DormandPrince853Integrator(e, 100.0, 1e-7, 1e-7);
+
+        TimeDetector detector1 = new TimeDetector(5);
+        integrator.addEventHandler(detector1, 10, 1, 100);
+        TimeDetector detector2 = new TimeDetector(5);
+        integrator.addEventHandler(detector2, 10, 1, 100);
+
+        // action
+        integrator.integrate(new Equation(), 0, new double[2], 20, new double[2]);
+
+        // verify
+        Assert.assertEquals(5, detector1.getActualT(), 0.0);
+        Assert.assertEquals(5, detector2.getActualT(), 0.0);
+    }
+
+
+    /** Trigger an event at a particular time. */
+    private static class TimeDetector implements EventHandler {
+
+        /** time of the event to trigger. */
+        private final double eventT;
+
+        /** time the event was actually triggered. */
+        private double actualT;
+
+        /**
+         * Create a new detector.
+         *
+         * @param eventT the time to trigger an event.
+         */
+        public TimeDetector(double eventT) {
+            this.eventT = eventT;
+        }
+
+        /** Get the actual time the event occurred. */
+        public double getActualT() {
+            return actualT;
+        }
+
+        public void init(double t0, double[] y0, double t) {
+        }
+
+        public double g(double t, double[] y) {
+            return t - eventT;
+        }
+
+        public Action eventOccurred(double t, double[] y, boolean increasing) {
+            this.actualT = t;
+            return Action.CONTINUE;
+        }
+
+        public void resetState(double t, double[] y) {
+        }
+
+    }
+
+    /** Some basic equations to integrate. */
+    public static class Equation implements FirstOrderDifferentialEquations {
+
+        public int getDimension() {
+            return 2;
+        }
+
+        public void computeDerivatives(double t, double[] y, double[] yDot) {
+            yDot[0] = 1.0;
+            yDot[1] = 2.0;
+        }
+
+    }
+
+}


Mime
View raw message