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/12/08 20:34:06 UTC

[1/8] [math] Fixed exception handling for too many iterations in event search.

Repository: commons-math
Updated Branches:
  refs/heads/field-ode d5c183b21 -> b713e4ca0


Fixed exception handling for too many iterations in event search.

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

Branch: refs/heads/field-ode
Commit: de965cbe40791f3a2ef03fc05480d12d37923098
Parents: d5c183b
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 18:07:47 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 18:07:47 2015 +0100

----------------------------------------------------------------------
 .../math3/ode/events/FieldEventState.java       | 174 ++++++++-----------
 1 file changed, 70 insertions(+), 104 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/de965cbe/src/main/java/org/apache/commons/math3/ode/events/FieldEventState.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/events/FieldEventState.java b/src/main/java/org/apache/commons/math3/ode/events/FieldEventState.java
index 044b889..5c22357 100644
--- a/src/main/java/org/apache/commons/math3/ode/events/FieldEventState.java
+++ b/src/main/java/org/apache/commons/math3/ode/events/FieldEventState.java
@@ -191,100 +191,91 @@ public class FieldEventState<T extends RealFieldElement<T>> {
     public boolean evaluateStep(final FieldStepInterpolator<T> interpolator)
         throws MaxCountExceededException, NoBracketingException {
 
-        try {
-            forward = interpolator.isForward();
-            final FieldODEStateAndDerivative<T> s1 = interpolator.getCurrentState();
-            final T t1 = s1.getTime();
-            final T dt = t1.subtract(t0);
-            if (dt.abs().subtract(convergence).getReal() < 0) {
-                // we cannot do anything on such a small step, don't trigger any events
-                return false;
+        forward = interpolator.isForward();
+        final FieldODEStateAndDerivative<T> s1 = interpolator.getCurrentState();
+        final T t1 = s1.getTime();
+        final T dt = t1.subtract(t0);
+        if (dt.abs().subtract(convergence).getReal() < 0) {
+            // we cannot do anything on such a small step, don't trigger any events
+            return false;
+        }
+        final int n = FastMath.max(1, (int) FastMath.ceil(FastMath.abs(dt.getReal()) / maxCheckInterval));
+        final T   h = dt.divide(n);
+
+        final RealFieldUnivariateFunction<T> f = new RealFieldUnivariateFunction<T>() {
+            /** {@inheritDoc} */
+            public T value(final T t) {
+                return handler.g(interpolator.getInterpolatedState(t));
             }
-            final int n = FastMath.max(1, (int) FastMath.ceil(FastMath.abs(dt.getReal()) / maxCheckInterval));
-            final T   h = dt.divide(n);
-
-            final RealFieldUnivariateFunction<T> f = new RealFieldUnivariateFunction<T>() {
-                /** {@inheritDoc} */
-                public T value(final T t) throws LocalMaxCountExceededException {
-                    try {
-                        return handler.g(interpolator.getInterpolatedState(t));
-                    } catch (MaxCountExceededException mcee) {
-                        throw new LocalMaxCountExceededException(mcee);
-                    }
-                }
-            };
-
-            T ta = t0;
-            T ga = g0;
-            for (int i = 0; i < n; ++i) {
-
-                // evaluate handler value at the end of the substep
-                final T tb = (i == n - 1) ? t1 : t0.add(h.multiply(i + 1));
-                final T gb = handler.g(interpolator.getInterpolatedState(tb));
-
-                // check events occurrence
-                if (g0Positive ^ (gb.getReal() >= 0)) {
-                    // there is a sign change: an event is expected during this step
-
-                    // variation direction, with respect to the integration direction
-                    increasing = gb.subtract(ga).getReal() >= 0;
-
-                    // find the event time making sure we select a solution just at or past the exact root
-                    final T root = forward ?
-                                   solver.solve(maxIterationCount, f, ta, tb, AllowedSolution.RIGHT_SIDE) :
-                                   solver.solve(maxIterationCount, f, tb, ta, AllowedSolution.LEFT_SIDE);
-
-                    if (previousEventTime != null &&
-                        root.subtract(ta).abs().subtract(convergence).getReal() <= 0 &&
-                        root.subtract(previousEventTime).abs().subtract(convergence).getReal() <= 0) {
-                        // we have either found nothing or found (again ?) a past event,
-                        // retry the substep excluding this value, and taking care to have the
-                        // required sign in case the g function is noisy around its zero and
-                        // crosses the axis several times
-                        do {
-                            ta = forward ? ta.add(convergence) : ta.subtract(convergence);
-                            ga = f.value(ta);
-                        } while ((g0Positive ^ (ga.getReal() >= 0)) && (forward ^ (ta.subtract(tb).getReal() >= 0)));
-
-                        if (forward ^ (ta.subtract(tb).getReal() >= 0)) {
-                            // 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 (previousEventTime == null ||
-                               previousEventTime.subtract(root).abs().subtract(convergence).getReal() > 0) {
+        };
+
+        T ta = t0;
+        T ga = g0;
+        for (int i = 0; i < n; ++i) {
+
+            // evaluate handler value at the end of the substep
+            final T tb = (i == n - 1) ? t1 : t0.add(h.multiply(i + 1));
+            final T gb = handler.g(interpolator.getInterpolatedState(tb));
+
+            // check events occurrence
+            if (g0Positive ^ (gb.getReal() >= 0)) {
+                // there is a sign change: an event is expected during this step
+
+                // variation direction, with respect to the integration direction
+                increasing = gb.subtract(ga).getReal() >= 0;
+
+                // find the event time making sure we select a solution just at or past the exact root
+                final T root = forward ?
+                               solver.solve(maxIterationCount, f, ta, tb, AllowedSolution.RIGHT_SIDE) :
+                               solver.solve(maxIterationCount, f, tb, ta, AllowedSolution.LEFT_SIDE);
+
+                if (previousEventTime != null &&
+                    root.subtract(ta).abs().subtract(convergence).getReal() <= 0 &&
+                    root.subtract(previousEventTime).abs().subtract(convergence).getReal() <= 0) {
+                    // we have either found nothing or found (again ?) a past event,
+                    // retry the substep excluding this value, and taking care to have the
+                    // required sign in case the g function is noisy around its zero and
+                    // crosses the axis several times
+                    do {
+                        ta = forward ? ta.add(convergence) : ta.subtract(convergence);
+                        ga = f.value(ta);
+                    } while ((g0Positive ^ (ga.getReal() >= 0)) && (forward ^ (ta.subtract(tb).getReal() >= 0)));
+
+                    if (forward ^ (ta.subtract(tb).getReal() >= 0)) {
+                        // 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 {
-                        // no sign change: there is no event for now
-                        ta = tb;
-                        ga = gb;
                     }
-
+                } else if (previousEventTime == null ||
+                           previousEventTime.subtract(root).abs().subtract(convergence).getReal() > 0) {
+                    pendingEventTime = root;
+                    pendingEvent     = true;
+                    return true;
                 } else {
                     // no sign change: there is no event for now
                     ta = tb;
                     ga = gb;
                 }
 
+            } else {
+                // no sign change: there is no event for now
+                ta = tb;
+                ga = gb;
             }
 
-            // no event during the whole step
-            pendingEvent     = false;
-            pendingEventTime = null;
-            return false;
-
-        } catch (LocalMaxCountExceededException lmcee) {
-            throw lmcee.getException();
         }
 
+        // no event during the whole step
+        pendingEvent     = false;
+        pendingEventTime = null;
+        return false;
+
     }
 
     /** Get the occurrence time of the event triggered in the current step.
@@ -350,29 +341,4 @@ public class FieldEventState<T extends RealFieldElement<T>> {
 
     }
 
-    /** Local wrapper to propagate exceptions. */
-    private static class LocalMaxCountExceededException extends RuntimeException {
-
-        /** Serializable UID. */
-        private static final long serialVersionUID = 20151113L;
-
-        /** Wrapped exception. */
-        private final MaxCountExceededException wrapped;
-
-        /** Simple constructor.
-         * @param exception exception to wrap
-         */
-        LocalMaxCountExceededException(final MaxCountExceededException exception) {
-            wrapped = exception;
-        }
-
-        /** Get the wrapped exception.
-         * @return wrapped exception
-         */
-        public MaxCountExceededException getException() {
-            return wrapped;
-        }
-
-    }
-
 }


[7/8] [math] Added tests for the Dormand-Prince 5(4) integrator.

Posted by lu...@apache.org.
Added tests for the Dormand-Prince 5(4) integrator.

BEWARE! These test do not pass yet. The integrator is currently not
consistent with the regular double-based integrator. 

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

Branch: refs/heads/field-ode
Commit: d587d2c410dcdbf050973bdd3d7e644592f4c21b
Parents: 8f1c2d6
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 20:28:04 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 20:28:04 2015 +0100

----------------------------------------------------------------------
 .../DormandPrince54FieldIntegratorTest.java     | 93 ++++++++++++++++++++
 ...ormandPrince54FieldStepInterpolatorTest.java | 49 +++++++++++
 2 files changed, 142 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/d587d2c4/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegratorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegratorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegratorTest.java
new file mode 100644
index 0000000..a52e4a5
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegratorTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class DormandPrince54FieldIntegratorTest extends AbstractEmbeddedRungeKuttaFieldIntegratorTest {
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double scalAbsoluteTolerance, final double scalRelativeTolerance) {
+        return new DormandPrince54FieldIntegrator<T>(field, minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
+    }
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double[] vecAbsoluteTolerance, final double[] vecRelativeTolerance) {
+        return new DormandPrince54FieldIntegrator<T>(field, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
+    }
+
+    @Test
+    public void testNonFieldIntegratorConsistency() {
+        doTestNonFieldIntegratorConsistency(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testSanityChecks() {
+        doTestSanityChecks(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testBackward() {
+        doTestBackward(Decimal64Field.getInstance(), 2.0e-7, 2.0e-7, 1.0e-12, "Dormand-Prince 5(4)");
+    }
+
+    @Test
+    public void testKepler() {
+        doTestKepler(Decimal64Field.getInstance(), 7.0e-10);
+    }
+
+    @Override
+    public void testForwardBackwardExceptions() {
+        doTestForwardBackwardExceptions(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testMinStep() {
+        doTestMinStep(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testIncreasingTolerance() {
+        // the 0.7 factor is only valid for this test
+        // and has been obtained from trial and error
+        // there is no general relation between local and global errors
+        doTestIncreasingTolerance(Decimal64Field.getInstance(), 0.7, 1.0e-12);
+    }
+
+    @Override
+    public void testEvents() {
+        doTestEvents(Decimal64Field.getInstance(), 5.0e-6, "Dormand-Prince 5(4)");
+    }
+
+    @Override
+    public void testEventsErrors() {
+        doTestEventsErrors(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testEventsNoConvergence() {
+        doTestEventsNoConvergence(Decimal64Field.getInstance());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/d587d2c4/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldStepInterpolatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldStepInterpolatorTest.java
new file mode 100644
index 0000000..378fbc8
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldStepInterpolatorTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.FieldEquationsMapper;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class DormandPrince54FieldStepInterpolatorTest extends AbstractRungeKuttaFieldStepInterpolatorTest {
+
+    protected <T extends RealFieldElement<T>> RungeKuttaFieldStepInterpolator<T>
+    createInterpolator(Field<T> field, boolean forward, FieldEquationsMapper<T> mapper) {
+        return new DormandPrince54FieldStepInterpolator<T>(field, forward, mapper);
+    }
+
+    @Test
+    public void interpolationAtBounds() {
+        doInterpolationAtBounds(Decimal64Field.getInstance(), 1.0e-50);
+    }
+
+    @Test
+    public void interpolationInside() {
+        doInterpolationInside(Decimal64Field.getInstance(), 4.0e-13, 2.7e-15);
+    }
+
+    @Test
+    public void nonFieldInterpolatorConsistency() {
+        doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 4.2e-17, 2.3e-16, 6.7e-16, 8.4e-17);
+    }
+
+}


[5/8] [math] Prevent NullPointerException in tests.

Posted by lu...@apache.org.
Prevent NullPointerException in tests.

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

Branch: refs/heads/field-ode
Commit: a3d10998f03bbdaaf4e63e98591f76b8f64fb793
Parents: b9e3ac5
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 20:12:49 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 20:12:49 2015 +0100

----------------------------------------------------------------------
 ...ractRungeKuttaFieldStepInterpolatorTest.java | 32 +++++++++++++++++---
 1 file changed, 27 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/a3d10998/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
index 82e9887..64365b4 100644
--- a/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
@@ -22,7 +22,9 @@ import java.lang.reflect.InvocationTargetException;
 
 import org.apache.commons.math3.Field;
 import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.AbstractIntegrator;
 import org.apache.commons.math3.ode.EquationsMapper;
+import org.apache.commons.math3.ode.ExpandableStatefulODE;
 import org.apache.commons.math3.ode.FieldEquationsMapper;
 import org.apache.commons.math3.ode.FieldExpandableODE;
 import org.apache.commons.math3.ode.FieldFirstOrderDifferentialEquations;
@@ -70,7 +72,7 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
 
         RungeKuttaFieldStepInterpolator<T> interpolator = setUpInterpolator(field,
                                                                             new SinCos<>(field),
-                                                                            0.0, new double[] { 0.0, 1.0 }, 0.125);
+                                                                            0.0, new double[] { 0.0, 1.0 }, 0.0125);
 
         int n = 100;
         double maxErrorSin = 0;
@@ -95,9 +97,10 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
                                                                                      double epsilonSin, double epsilonCos,
                                                                                      double epsilonSinDot, double epsilonCosDot) {
 
+        FieldFirstOrderDifferentialEquations<T> eqn = new SinCos<>(field);
         RungeKuttaFieldStepInterpolator<T> fieldInterpolator =
-                        setUpInterpolator(field, new SinCos<>(field), 0.0, new double[] { 0.0, 1.0 }, 0.125);
-        RungeKuttaStepInterpolator regularInterpolator = convertInterpolator(fieldInterpolator);
+                        setUpInterpolator(field, eqn, 0.0, new double[] { 0.0, 1.0 }, 0.125);
+        RungeKuttaStepInterpolator regularInterpolator = convertInterpolator(fieldInterpolator, eqn);
 
         int n = 100;
         double maxErrorSin    = 0;
@@ -185,7 +188,8 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
     }
 
     private <T extends RealFieldElement<T>>
-    RungeKuttaStepInterpolator convertInterpolator(final RungeKuttaFieldStepInterpolator<T> fieldInterpolator) {
+    RungeKuttaStepInterpolator convertInterpolator(final RungeKuttaFieldStepInterpolator<T> fieldInterpolator,
+                                                   final FieldFirstOrderDifferentialEquations<T> eqn) {
 
         RungeKuttaStepInterpolator regularInterpolator = null;
         try {
@@ -225,7 +229,25 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
                 secondaryMappers[i] = new EquationsMapper(start[i + 1], start[i + 2]);
             }
 
-            regularInterpolator.reinitialize(null, y, yDotArray,
+            AbstractIntegrator dummyIntegrator = new AbstractIntegrator("dummy") {
+                @Override
+                public void integrate(ExpandableStatefulODE equations, double t) {
+                    Assert.fail("this method should not be called");
+                }
+                @Override
+                public void computeDerivatives(final double t, final double[] y, final double[] yDot) {
+                    T fieldT = fieldInterpolator.getField().getZero().add(t);
+                    T[] fieldY = MathArrays.buildArray(fieldInterpolator.getField(), y.length);
+                    for (int i = 0; i < y.length; ++i) {
+                        fieldY[i] = fieldInterpolator.getField().getZero().add(y[i]);
+                    }
+                    T[] fieldYDot = eqn.computeDerivatives(fieldT, fieldY);
+                    for (int i = 0; i < yDot.length; ++i) {
+                        yDot[i] = fieldYDot[i].getReal();
+                    }
+                }
+            };
+            regularInterpolator.reinitialize(dummyIntegrator, y, yDotArray,
                                              fieldInterpolator.isForward(),
                                              primaryMapper, secondaryMappers);
 


[4/8] [math] Set up a shared interface for Butcher arrays used by integrators.

Posted by lu...@apache.org.
Set up a shared interface for Butcher arrays used by integrators.

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

Branch: refs/heads/field-ode
Commit: b9e3ac55df3a51b1a4de65300ff3a9da38f961fe
Parents: a39a852
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 19:14:20 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 19:14:20 2015 +0100

----------------------------------------------------------------------
 .../ClassicalRungeKuttaFieldIntegrator.java     |  6 +--
 .../DormandPrince54FieldIntegrator.java         |  6 +--
 .../DormandPrince853FieldIntegrator.java        |  6 +--
 .../DormandPrince853FieldStepInterpolator.java  |  2 +-
 .../EmbeddedRungeKuttaFieldIntegrator.java      | 18 +-------
 .../ode/nonstiff/EulerFieldIntegrator.java      |  6 +--
 .../ode/nonstiff/FieldButcherArrayProvider.java | 46 ++++++++++++++++++++
 .../math3/ode/nonstiff/GillFieldIntegrator.java |  6 +--
 .../nonstiff/HighamHall54FieldIntegrator.java   |  6 +--
 .../ode/nonstiff/LutherFieldIntegrator.java     |  6 +--
 .../ode/nonstiff/MidpointFieldIntegrator.java   |  6 +--
 .../ode/nonstiff/RungeKuttaFieldIntegrator.java | 18 +-------
 .../nonstiff/ThreeEighthesFieldIntegrator.java  |  6 +--
 ...ractRungeKuttaFieldStepInterpolatorTest.java | 28 ++++++------
 14 files changed, 91 insertions(+), 75 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaFieldIntegrator.java
index e5116e8..057a39d 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungeKuttaFieldIntegrator.java
@@ -62,7 +62,7 @@ public class ClassicalRungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 3);
         c[0] = getField().getOne().multiply(0.5);
         c[1] = c[0];
@@ -72,7 +72,7 @@ public class ClassicalRungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T[][] a = MathArrays.buildArray(getField(), 3, -1);
         for (int i = 0; i < a.length; ++i) {
             a[i] = MathArrays.buildArray(getField(), i + 1);
@@ -88,7 +88,7 @@ public class ClassicalRungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 4);
         b[0] = fraction(1, 6);
         b[1] = fraction(1, 3);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegrator.java
index 2b01bdb..356c165 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince54FieldIntegrator.java
@@ -130,7 +130,7 @@ public class DormandPrince54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 6);
         c[0] = fraction(1,  5);
         c[1] = fraction(3, 10);
@@ -143,7 +143,7 @@ public class DormandPrince54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T[][] a = MathArrays.buildArray(getField(), 6, -1);
         for (int i = 0; i < a.length; ++i) {
             a[i] = MathArrays.buildArray(getField(), i + 1);
@@ -174,7 +174,7 @@ public class DormandPrince54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 7);
         b[0] = fraction(   35,   384);
         b[1] = getField().getZero();

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegrator.java
index 86b3844..2c872e8 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegrator.java
@@ -191,7 +191,7 @@ public class DormandPrince853FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
 
         final T sqrt6 = getField().getOne().multiply(6).sqrt();
 
@@ -218,7 +218,7 @@ public class DormandPrince853FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
 
         final T sqrt6 = getField().getOne().multiply(6).sqrt();
 
@@ -371,7 +371,7 @@ public class DormandPrince853FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 16);
         b[ 0] = fraction(104257, 1929240);
         b[ 1] = getField().getZero();

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolator.java
index 182d8a6..211f18c 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolator.java
@@ -52,7 +52,7 @@ class DormandPrince853FieldStepInterpolator<T extends RealFieldElement<T>>
         super(field, forward, mapper);
 
         // interpolation weights
-        d = MathArrays.buildArray(getField(), 4, 16);
+        d = MathArrays.buildArray(getField(), 7, 16);
 
         // this row is the same as the b array
         d[0][ 0] = fraction(104257, 1929240);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
index 39a89e1..9a81493 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
@@ -68,7 +68,8 @@ import org.apache.commons.math3.util.MathUtils;
  */
 
 public abstract class EmbeddedRungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
-    extends AdaptiveStepsizeFieldIntegrator<T> {
+    extends AdaptiveStepsizeFieldIntegrator<T>
+    implements FieldButcherArrayProvider<T> {
 
     /** Index of the pre-computed derivative for <i>fsal</i> methods. */
     private final int fsal;
@@ -180,21 +181,6 @@ public abstract class EmbeddedRungeKuttaFieldIntegrator<T extends RealFieldEleme
         return getField().getOne().multiply(p).divide(q);
     }
 
-    /** Get the time steps from Butcher array (without the first zero).
-     * @return time steps from Butcher array (without the first zero
-     */
-    protected abstract T[] getC();
-
-    /** Get the internal weights from Butcher array (without the first empty row).
-     * @return internal weights from Butcher array (without the first empty row)
-     */
-    protected abstract T[][] getA();
-
-    /** Get the external weights for the high order method from Butcher array.
-     * @return external weights for the high order method from Butcher array
-     */
-    protected abstract T[] getB();
-
     /** Create an interpolator.
      * @param forward integration direction indicator
      * @param mapper equations mapper for the all equations

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/EulerFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/EulerFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/EulerFieldIntegrator.java
index 798c0e9..f6ee8ff 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/EulerFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/EulerFieldIntegrator.java
@@ -64,19 +64,19 @@ public class EulerFieldIntegrator<T extends RealFieldElement<T>> extends RungeKu
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         return MathArrays.buildArray(getField(), 0);
     }
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         return MathArrays.buildArray(getField(), 0, 0);
     }
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 1);
         b[0] = getField().getOne();
         return b;

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/FieldButcherArrayProvider.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/FieldButcherArrayProvider.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/FieldButcherArrayProvider.java
new file mode 100644
index 0000000..b37d4cb
--- /dev/null
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/FieldButcherArrayProvider.java
@@ -0,0 +1,46 @@
+/*
+ * 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.nonstiff;
+
+import org.apache.commons.math3.RealFieldElement;
+
+/** This interface represents an integrator  based on Butcher arrays.
+ * @see RungeKuttaFieldIntegrator
+ * @see EmbeddedRungeKuttaFieldIntegrator
+ * @param <T> the type of the field elements
+ * @since 3.6
+ */
+
+public interface FieldButcherArrayProvider<T extends RealFieldElement<T>> {
+
+    /** Get the time steps from Butcher array (without the first zero).
+     * @return time steps from Butcher array (without the first zero
+     */
+    T[] getC();
+
+    /** Get the internal weights from Butcher array (without the first empty row).
+     * @return internal weights from Butcher array (without the first empty row)
+     */
+    T[][] getA();
+
+    /** Get the external weights for the high order method from Butcher array.
+     * @return external weights for the high order method from Butcher array
+     */
+    T[] getB();
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/GillFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/GillFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/GillFieldIntegrator.java
index e627782..4f4868d 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/GillFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/GillFieldIntegrator.java
@@ -62,7 +62,7 @@ public class GillFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 3);
         c[0] = fraction(1, 2);
         c[1] = c[0];
@@ -72,7 +72,7 @@ public class GillFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
 
         final T two     = getField().getZero().add(2);
         final T sqrtTwo = two.sqrt();
@@ -92,7 +92,7 @@ public class GillFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
 
         final T two     = getField().getZero().add(2);
         final T sqrtTwo = two.sqrt();

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegrator.java
index 8473892..a186b1d 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegrator.java
@@ -105,7 +105,7 @@ public class HighamHall54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 6);
         c[0] = fraction(2, 9);
         c[1] = fraction(1, 3);
@@ -118,7 +118,7 @@ public class HighamHall54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T[][] a = MathArrays.buildArray(getField(), 6, -1);
         for (int i = 0; i < a.length; ++i) {
             a[i] = MathArrays.buildArray(getField(), i + 1);
@@ -149,7 +149,7 @@ public class HighamHall54FieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 7);
         b[0] = fraction(  1, 12);
         b[1] = getField().getZero();

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/LutherFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/LutherFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/LutherFieldIntegrator.java
index d906703..9adb86b 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/LutherFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/LutherFieldIntegrator.java
@@ -71,7 +71,7 @@ public class LutherFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T q = getField().getZero().add(21).sqrt();
         final T[] c = MathArrays.buildArray(getField(), 6);
         c[0] = getField().getOne();
@@ -85,7 +85,7 @@ public class LutherFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T q = getField().getZero().add(21).sqrt();
         final T[][] a = MathArrays.buildArray(getField(), 6, -1);
         for (int i = 0; i < a.length; ++i) {
@@ -117,7 +117,7 @@ public class LutherFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
 
         final T[] b = MathArrays.buildArray(getField(), 7);
         b[0] = fraction( 1,  20);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldIntegrator.java
index d3a1f2f..9ea1a06 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldIntegrator.java
@@ -59,7 +59,7 @@ public class MidpointFieldIntegrator<T extends RealFieldElement<T>> extends Rung
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 1);
         c[0] = getField().getOne().multiply(0.5);
         return c;
@@ -67,7 +67,7 @@ public class MidpointFieldIntegrator<T extends RealFieldElement<T>> extends Rung
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T[][] a = MathArrays.buildArray(getField(), 1, 1);
         a[0][0] = fraction(1, 2);
         return a;
@@ -75,7 +75,7 @@ public class MidpointFieldIntegrator<T extends RealFieldElement<T>> extends Rung
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 2);
         b[0] = getField().getZero();
         b[1] = getField().getOne();

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaFieldIntegrator.java
index befa525..ed0ed77 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/RungeKuttaFieldIntegrator.java
@@ -58,7 +58,8 @@ import org.apache.commons.math3.util.MathArrays;
  */
 
 public abstract class RungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
-    extends AbstractFieldIntegrator<T> {
+    extends AbstractFieldIntegrator<T>
+    implements FieldButcherArrayProvider<T> {
 
     /** Time steps from Butcher array (without the first zero). */
     private final T[] c;
@@ -96,21 +97,6 @@ public abstract class RungeKuttaFieldIntegrator<T extends RealFieldElement<T>>
         return getField().getZero().add(p).divide(q);
     }
 
-    /** Get the time steps from Butcher array (without the first zero).
-     * @return time steps from Butcher array (without the first zero
-     */
-    protected abstract T[] getC();
-
-    /** Get the internal weights from Butcher array (without the first empty row).
-     * @return internal weights from Butcher array (without the first empty row)
-     */
-    protected abstract T[][] getA();
-
-    /** Get the external weights for the high order method from Butcher array.
-     * @return external weights for the high order method from Butcher array
-     */
-    protected abstract T[] getB();
-
     /** Create an interpolator.
      * @param forward integration direction indicator
      * @param mapper equations mapper for the all equations

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/main/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldIntegrator.java
index d298ff8..482c7d5 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldIntegrator.java
@@ -61,7 +61,7 @@ public class ThreeEighthesFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getC() {
+    public T[] getC() {
         final T[] c = MathArrays.buildArray(getField(), 3);
         c[0] = fraction(1, 3);
         c[1] = c[0].add(c[0]);
@@ -71,7 +71,7 @@ public class ThreeEighthesFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[][] getA() {
+    public T[][] getA() {
         final T[][] a = MathArrays.buildArray(getField(), 3, -1);
         for (int i = 0; i < a.length; ++i) {
             a[i] = MathArrays.buildArray(getField(), i + 1);
@@ -87,7 +87,7 @@ public class ThreeEighthesFieldIntegrator<T extends RealFieldElement<T>>
 
     /** {@inheritDoc} */
     @Override
-    protected T[] getB() {
+    public T[] getB() {
         final T[] b = MathArrays.buildArray(getField(), 4);
         b[0] = fraction(1, 8);
         b[1] = fraction(3, 8);

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b9e3ac55/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
index 9f419b9..82e9887 100644
--- a/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractRungeKuttaFieldStepInterpolatorTest.java
@@ -140,10 +140,10 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
         RungeKuttaFieldStepInterpolator<T> interpolator = createInterpolator(field, t1 > t0,
                                                                              new FieldExpandableODE<T>(eqn).getMapper());
         // get the Butcher arrays from the field integrator
-        RungeKuttaFieldIntegrator<T> fieldIntegrator = createFieldIntegrator(field, interpolator);
-        T[][] a = fieldIntegrator.getA();
-        T[]   b = fieldIntegrator.getB();
-        T[]   c = fieldIntegrator.getC();
+        FieldButcherArrayProvider<T> provider = createButcherArrayProvider(field, interpolator);
+        T[][] a = provider.getA();
+        T[]   b = provider.getB();
+        T[]   c = provider.getC();
 
         // store initial state
         T     t          = field.getZero().add(t0);
@@ -259,25 +259,23 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest {
 
     }
 
-    private <T extends RealFieldElement<T>> RungeKuttaFieldIntegrator<T>
-    createFieldIntegrator(final Field<T> field, final RungeKuttaFieldStepInterpolator<T> interpolator) {
-        RungeKuttaFieldIntegrator<T> integrator = null;
+    private <T extends RealFieldElement<T>> FieldButcherArrayProvider<T>
+    createButcherArrayProvider(final Field<T> field, final RungeKuttaFieldStepInterpolator<T> provider) {
+        FieldButcherArrayProvider<T> integrator = null;
         try {
-        String interpolatorName = interpolator.getClass().getName();
+        String interpolatorName = provider.getClass().getName();
         String integratorName = interpolatorName.replaceAll("StepInterpolator", "Integrator");
             @SuppressWarnings("unchecked")
-            Class<RungeKuttaFieldIntegrator<T>> clz = (Class<RungeKuttaFieldIntegrator<T>>) Class.forName(integratorName);
+            Class<FieldButcherArrayProvider<T>> clz = (Class<FieldButcherArrayProvider<T>>) Class.forName(integratorName);
             try {
                 integrator = clz.getConstructor(Field.class, RealFieldElement.class).
-                             newInstance(field, field.getOne());
+                                                newInstance(field, field.getOne());
             } catch (NoSuchMethodException nsme) {
                 try {
                     integrator = clz.getConstructor(Field.class,
-                                                    RealFieldElement.class,
-                                                    RealFieldElement.class,
-                                                    RealFieldElement.class).
-                                 newInstance(field, field.getZero().add(0.001),
-                                             field.getOne(), field.getOne(), field.getOne());
+                                                    Double.TYPE, Double.TYPE,
+                                                    Double.TYPE, Double.TYPE).
+                                 newInstance(field, 0.001, 1.0, 1.0, 1.0);
                 } catch (NoSuchMethodException e) {
                     Assert.fail(e.getLocalizedMessage());
                 }


[3/8] [math] Set up test framework for field-based embedded Runge-Kutta integrators.

Posted by lu...@apache.org.
Set up test framework for field-based embedded Runge-Kutta integrators.

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

Branch: refs/heads/field-ode
Commit: a39a8527ddc71711357cc9f1ff84771fe24d0109
Parents: d671ede
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 18:09:41 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 18:09:41 2015 +0100

----------------------------------------------------------------------
 ...ctEmbeddedRungeKuttaFieldIntegratorTest.java | 445 +++++++++++++++++++
 1 file changed, 445 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/a39a8527/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractEmbeddedRungeKuttaFieldIntegratorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractEmbeddedRungeKuttaFieldIntegratorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractEmbeddedRungeKuttaFieldIntegratorTest.java
new file mode 100644
index 0000000..06a05c9
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/AbstractEmbeddedRungeKuttaFieldIntegratorTest.java
@@ -0,0 +1,445 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.MaxCountExceededException;
+import org.apache.commons.math3.exception.NoBracketingException;
+import org.apache.commons.math3.exception.NumberIsTooSmallException;
+import org.apache.commons.math3.ode.FieldExpandableODE;
+import org.apache.commons.math3.ode.FieldFirstOrderDifferentialEquations;
+import org.apache.commons.math3.ode.FieldFirstOrderIntegrator;
+import org.apache.commons.math3.ode.FieldODEState;
+import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
+import org.apache.commons.math3.ode.TestFieldProblem1;
+import org.apache.commons.math3.ode.TestFieldProblem3;
+import org.apache.commons.math3.ode.TestFieldProblem4;
+import org.apache.commons.math3.ode.TestFieldProblem5;
+import org.apache.commons.math3.ode.TestFieldProblemHandler;
+import org.apache.commons.math3.ode.events.Action;
+import org.apache.commons.math3.ode.events.FieldEventHandler;
+import org.apache.commons.math3.ode.sampling.FieldStepHandler;
+import org.apache.commons.math3.ode.sampling.FieldStepInterpolator;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathArrays;
+import org.junit.Assert;
+import org.junit.Test;
+
+public abstract class AbstractEmbeddedRungeKuttaFieldIntegratorTest {
+
+    protected abstract <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double scalAbsoluteTolerance, final double scalRelativeTolerance) ;
+
+    protected abstract <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double[] vecAbsoluteTolerance, final double[] vecRelativeTolerance);
+
+    @Test
+    public abstract void testNonFieldIntegratorConsistency();
+
+    protected <T extends RealFieldElement<T>> void doTestNonFieldIntegratorConsistency(final Field<T> field) {
+        try {
+
+            // get the Butcher arrays from the field integrator
+            EmbeddedRungeKuttaFieldIntegrator<T> fieldIntegrator = createIntegrator(field, 0.001, 1.0, 1.0, 1.0);
+            T[][] fieldA = fieldIntegrator.getA();
+            T[]   fieldB = fieldIntegrator.getB();
+            T[]   fieldC = fieldIntegrator.getC();
+
+            String fieldName   = fieldIntegrator.getClass().getName();
+            String regularName = fieldName.replaceAll("Field", "");
+
+            // get the Butcher arrays from the regular integrator
+            @SuppressWarnings("unchecked")
+            Class<RungeKuttaIntegrator> c = (Class<RungeKuttaIntegrator>) Class.forName(regularName);
+            java.lang.reflect.Field jlrFieldA = c.getDeclaredField("STATIC_A");
+            jlrFieldA.setAccessible(true);
+            double[][] regularA = (double[][]) jlrFieldA.get(null);
+            java.lang.reflect.Field jlrFieldB = c.getDeclaredField("STATIC_B");
+            jlrFieldB.setAccessible(true);
+            double[]   regularB = (double[])   jlrFieldB.get(null);
+            java.lang.reflect.Field jlrFieldC = c.getDeclaredField("STATIC_C");
+            jlrFieldC.setAccessible(true);
+            double[]   regularC = (double[])   jlrFieldC.get(null);
+
+            Assert.assertEquals(regularA.length, fieldA.length);
+            for (int i = 0; i < regularA.length; ++i) {
+                checkArray(regularA[i], fieldA[i]);
+            }
+            checkArray(regularB, fieldB);
+            checkArray(regularC, fieldC);
+
+        } catch (ClassNotFoundException cnfe) {
+            Assert.fail(cnfe.getLocalizedMessage());
+        } catch (IllegalAccessException iae) {
+            Assert.fail(iae.getLocalizedMessage());
+        } catch (IllegalArgumentException iae) {
+            Assert.fail(iae.getLocalizedMessage());
+        } catch (SecurityException se) {
+            Assert.fail(se.getLocalizedMessage());
+        } catch (NoSuchFieldException nsfe) {
+            Assert.fail(nsfe.getLocalizedMessage());
+        }
+    }
+
+    private <T extends RealFieldElement<T>> void checkArray(double[] regularArray, T[] fieldArray) {
+        Assert.assertEquals(regularArray.length, fieldArray.length);
+        for (int i = 0; i < regularArray.length; ++i) {
+            if (regularArray[i] == 0) {
+                Assert.assertTrue(0.0 == fieldArray[i].getReal());
+            } else {
+                Assert.assertEquals(regularArray[i], fieldArray[i].getReal(), FastMath.ulp(regularArray[i]));
+            }
+        }
+    }
+
+    @Test
+    public abstract void testForwardBackwardExceptions();
+
+    protected <T extends RealFieldElement<T>> void doTestForwardBackwardExceptions(final Field<T> field) {
+        FieldFirstOrderDifferentialEquations<T> equations = new FieldFirstOrderDifferentialEquations<T>() {
+
+            public int getDimension() {
+                return 1;
+            }
+
+            public void init(T t0, T[] y0, T t) {
+            }
+
+            public T[] computeDerivatives(T t, T[] y) {
+                if (t.getReal() < -0.5) {
+                    throw new LocalException();
+                } else {
+                    throw new RuntimeException("oops");
+                }
+            }
+        };
+
+        EmbeddedRungeKuttaFieldIntegrator<T> integrator = createIntegrator(field, 0.0, 1.0, 1.0e-10, 1.0e-10);
+
+        try  {
+            integrator.integrate(new FieldExpandableODE<>(equations),
+                                 new FieldODEState<T>(field.getOne().negate(),
+                                                      MathArrays.buildArray(field, 1)),
+                                 field.getZero());
+            Assert.fail("an exception should have been thrown");
+          } catch(LocalException de) {
+            // expected behavior
+          }
+
+          try  {
+              integrator.integrate(new FieldExpandableODE<>(equations),
+                                   new FieldODEState<T>(field.getZero(),
+                                                        MathArrays.buildArray(field, 1)),
+                                   field.getOne());
+               Assert.fail("an exception should have been thrown");
+          } catch(RuntimeException de) {
+            // expected behavior
+          }
+    }
+
+    protected static class LocalException extends RuntimeException {
+        private static final long serialVersionUID = 20151208L;
+    }
+
+    @Test(expected=NumberIsTooSmallException.class)
+    public abstract void testMinStep();
+
+    protected <T extends RealFieldElement<T>> void doTestMinStep(final Field<T> field)
+        throws NumberIsTooSmallException {
+
+        TestFieldProblem1<T> pb = new TestFieldProblem1<T>(field);
+        double minStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).multiply(0.1).getReal();
+        double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+        double[] vecAbsoluteTolerance = { 1.0e-15, 1.0e-16 };
+        double[] vecRelativeTolerance = { 1.0e-15, 1.0e-16 };
+
+        FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                              vecAbsoluteTolerance, vecRelativeTolerance);
+        TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+        integ.addStepHandler(handler);
+        integ.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getFinalTime());
+        Assert.fail("an exception should have been thrown");
+
+    }
+
+    @Test
+    public abstract void testIncreasingTolerance();
+
+    protected <T extends RealFieldElement<T>> void doTestIncreasingTolerance(final Field<T> field,
+                                                                             double factor,
+                                                                             double epsilon) {
+
+        int previousCalls = Integer.MAX_VALUE;
+        for (int i = -12; i < -2; ++i) {
+            TestFieldProblem1<T> pb = new TestFieldProblem1<T>(field);
+            double minStep = 0;
+            double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+            double scalAbsoluteTolerance = FastMath.pow(10.0, i);
+            double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
+
+            FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                                  scalAbsoluteTolerance, scalRelativeTolerance);
+            TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+            integ.addStepHandler(handler);
+            integ.integrate(new FieldExpandableODE<T>(pb), pb.getInitialState(), pb.getFinalTime());
+
+            Assert.assertTrue(handler.getMaximalValueError().getReal() < (factor * scalAbsoluteTolerance));
+            Assert.assertEquals(0, handler.getMaximalTimeError().getReal(), epsilon);
+
+            int calls = pb.getCalls();
+            Assert.assertEquals(integ.getEvaluations(), calls);
+            Assert.assertTrue(calls <= previousCalls);
+            previousCalls = calls;
+
+        }
+
+    }
+
+    @Test
+    public abstract void testEvents();
+
+    protected <T extends RealFieldElement<T>> void doTestEvents(final Field<T> field,
+                                                                final double epsilonMaxValue,
+                                                                final String name) {
+
+      TestFieldProblem4<T> pb = new TestFieldProblem4<T>(field);
+      double minStep = 0;
+      double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+      double scalAbsoluteTolerance = 1.0e-8;
+      double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
+
+      FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                            scalAbsoluteTolerance, scalRelativeTolerance);
+      TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+      integ.addStepHandler(handler);
+      FieldEventHandler<T>[] functions = pb.getEventsHandlers();
+      double convergence = 1.0e-8 * maxStep;
+      for (int l = 0; l < functions.length; ++l) {
+          integ.addEventHandler(functions[l], Double.POSITIVE_INFINITY, convergence, 1000);
+      }
+      Assert.assertEquals(functions.length, integ.getEventHandlers().size());
+      integ.integrate(new FieldExpandableODE<T>(pb), pb.getInitialState(), pb.getFinalTime());
+
+      Assert.assertEquals(0, handler.getMaximalValueError().getReal(), epsilonMaxValue);
+      Assert.assertEquals(0, handler.getMaximalTimeError().getReal(), convergence);
+      Assert.assertEquals(12.0, handler.getLastTime().getReal(), convergence);
+      Assert.assertEquals(name, integ.getName());
+      integ.clearEventHandlers();
+      Assert.assertEquals(0, integ.getEventHandlers().size());
+
+    }
+
+    @Test(expected=LocalException.class)
+    public abstract void testEventsErrors();
+
+    protected <T extends RealFieldElement<T>> void doTestEventsErrors(final Field<T> field)
+        throws LocalException {
+        final TestFieldProblem1<T> pb = new TestFieldProblem1<T>(field);
+        double minStep = 0;
+        double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+        double scalAbsoluteTolerance = 1.0e-8;
+        double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
+
+        FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                              scalAbsoluteTolerance, scalRelativeTolerance);
+        TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+        integ.addStepHandler(handler);
+
+        integ.addEventHandler(new FieldEventHandler<T>() {
+          public void init(FieldODEStateAndDerivative<T> state0, T t) {
+          }
+          public Action eventOccurred(FieldODEStateAndDerivative<T> state, boolean increasing) {
+            return Action.CONTINUE;
+          }
+          public T g(FieldODEStateAndDerivative<T> state) {
+            T middle = pb.getInitialState().getTime().add(pb.getFinalTime()).multiply(0.5);
+            T offset = state.getTime().subtract(middle);
+            if (offset.getReal() > 0) {
+              throw new LocalException();
+            }
+            return offset;
+          }
+          public FieldODEState<T> resetState(FieldODEStateAndDerivative<T> state) {
+              return state;
+          }
+        }, Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 1000);
+
+        integ.integrate(new FieldExpandableODE<T>(pb), pb.getInitialState(), pb.getFinalTime());
+
+    }
+
+    @Test
+    public abstract void testEventsNoConvergence();
+
+    protected <T extends RealFieldElement<T>> void doTestEventsNoConvergence(final Field<T> field){
+
+        final TestFieldProblem1<T> pb = new TestFieldProblem1<T>(field);
+        double minStep = 0;
+        double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+        double scalAbsoluteTolerance = 1.0e-8;
+        double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
+
+        FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                              scalAbsoluteTolerance, scalRelativeTolerance);
+        TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+        integ.addStepHandler(handler);
+
+        integ.addEventHandler(new FieldEventHandler<T>() {
+            public void init(FieldODEStateAndDerivative<T> state0, T t) {
+            }
+            public Action eventOccurred(FieldODEStateAndDerivative<T> state, boolean increasing) {
+                return Action.CONTINUE;
+            }
+            public T g(FieldODEStateAndDerivative<T> state) {
+                T middle = pb.getInitialState().getTime().add(pb.getFinalTime()).multiply(0.5);
+                T offset = state.getTime().subtract(middle);
+                return (offset.getReal() > 0) ? offset.add(0.5) : offset.subtract(0.5);
+            }
+            public FieldODEState<T> resetState(FieldODEStateAndDerivative<T> state) {
+                return state;
+            }
+        }, Double.POSITIVE_INFINITY, 1.0e-8 * maxStep, 3);
+
+        try {
+            integ.integrate(new FieldExpandableODE<T>(pb), pb.getInitialState(), pb.getFinalTime());
+            Assert.fail("an exception should have been thrown");
+        } catch (MaxCountExceededException mcee) {
+            // Expected.
+        }
+
+    }
+
+    @Test
+    public abstract void testSanityChecks();
+
+    protected <T extends RealFieldElement<T>> void doTestSanityChecks(Field<T> field) {
+        TestFieldProblem3<T> pb = new TestFieldProblem3<T>(field);
+        try  {
+            EmbeddedRungeKuttaFieldIntegrator<T> integrator = createIntegrator(field, 0,
+                                                                               pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal(),
+                                                                               new double[4], new double[4]);
+            integrator.integrate(new FieldExpandableODE<>(pb),
+                                 new FieldODEState<T>(pb.getInitialState().getTime(),
+                                                      MathArrays.buildArray(field, 6)),
+                                 pb.getFinalTime());
+            Assert.fail("an exception should have been thrown");
+        } catch(DimensionMismatchException ie) {
+        }
+        try  {
+            EmbeddedRungeKuttaFieldIntegrator<T> integrator =
+                            createIntegrator(field, 0,
+                                             pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal(),
+                                             new double[2], new double[4]);
+            integrator.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getFinalTime());
+            Assert.fail("an exception should have been thrown");
+        } catch(DimensionMismatchException ie) {
+        }
+        try  {
+            EmbeddedRungeKuttaFieldIntegrator<T> integrator =
+                            createIntegrator(field, 0,
+                                             pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal(),
+                                             new double[4], new double[4]);
+            integrator.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getInitialState().getTime());
+            Assert.fail("an exception should have been thrown");
+        } catch(NumberIsTooSmallException ie) {
+        }
+    }
+
+    @Test
+    public abstract void testBackward();
+
+    protected <T extends RealFieldElement<T>> void doTestBackward(Field<T> field,
+                                                                  final double espilonLast,
+                                                                  final double epsilonMaxValue,
+                                                                  final double epsilonMaxTime,
+                                                                  final String name)
+        throws DimensionMismatchException, NumberIsTooSmallException,
+               MaxCountExceededException, NoBracketingException {
+
+        TestFieldProblem5<T> pb = new TestFieldProblem5<T>(field);
+        double minStep = 0;
+        double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).abs().getReal();
+        double scalAbsoluteTolerance = 1.0e-8;
+        double scalRelativeTolerance = 0.01 * scalAbsoluteTolerance;
+
+        EmbeddedRungeKuttaFieldIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                                      scalAbsoluteTolerance,
+                                                                      scalRelativeTolerance);
+        TestFieldProblemHandler<T> handler = new TestFieldProblemHandler<T>(pb, integ);
+        integ.addStepHandler(handler);
+        integ.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getFinalTime());
+
+        Assert.assertEquals(0, handler.getLastError().getReal(),         espilonLast);
+        Assert.assertEquals(0, handler.getMaximalValueError().getReal(), epsilonMaxValue);
+        Assert.assertEquals(0, handler.getMaximalTimeError().getReal(),  epsilonMaxTime);
+        Assert.assertEquals(name, integ.getName());
+
+    }
+
+    @Test
+    public abstract void testKepler();
+
+    protected <T extends RealFieldElement<T>> void doTestKepler(Field<T> field, double epsilon) {
+
+        final TestFieldProblem3<T> pb  = new TestFieldProblem3<T>(field, field.getZero().add(0.9));
+        double minStep = 0;
+        double maxStep = pb.getFinalTime().subtract(pb.getInitialState().getTime()).getReal();
+        double[] vecAbsoluteTolerance = { 1.0e-8, 1.0e-8, 1.0e-10, 1.0e-10 };
+        double[] vecRelativeTolerance = { 1.0e-10, 1.0e-10, 1.0e-8, 1.0e-8 };
+
+        FieldFirstOrderIntegrator<T> integ = createIntegrator(field, minStep, maxStep,
+                                                              vecAbsoluteTolerance, vecRelativeTolerance);
+        integ.addStepHandler(new KeplerHandler<T>(pb, epsilon));
+        integ.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getFinalTime());
+    }
+
+    private static class KeplerHandler<T extends RealFieldElement<T>> implements FieldStepHandler<T> {
+        private T maxError;
+        private final TestFieldProblem3<T> pb;
+        private final double epsilon;
+        public KeplerHandler(TestFieldProblem3<T> pb, double epsilon) {
+            this.pb      = pb;
+            this.epsilon = epsilon;
+            maxError = pb.getField().getZero();
+        }
+        public void init(FieldODEStateAndDerivative<T> state0, T t) {
+            maxError = pb.getField().getZero();
+        }
+        public void handleStep(FieldStepInterpolator<T> interpolator, boolean isLast)
+                        throws MaxCountExceededException {
+
+            FieldODEStateAndDerivative<T> current = interpolator.getCurrentState();
+            T[] theoreticalY  = pb.computeTheoreticalState(current.getTime());
+            T dx = current.getState()[0].subtract(theoreticalY[0]);
+            T dy = current.getState()[1].subtract(theoreticalY[1]);
+            T error = dx.multiply(dx).add(dy.multiply(dy));
+            if (error.subtract(maxError).getReal() > 0) {
+                maxError = error;
+            }
+            if (isLast) {
+                Assert.assertEquals(0.0, maxError.getReal(), epsilon);
+            }
+        }
+    }
+
+}


[8/8] [math] Added tests for the Dormand-Prince 8(5,3) integrator.

Posted by lu...@apache.org.
Added tests for the Dormand-Prince 8(5,3) integrator.

BEWARE! These test do not pass yet. The integrator is currently not
consistent with the regular double-based integrator. 

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

Branch: refs/heads/field-ode
Commit: b713e4ca049989913850bb712cf0cdc344fcab35
Parents: d587d2c
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 20:28:26 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 20:28:26 2015 +0100

----------------------------------------------------------------------
 .../DormandPrince853FieldIntegratorTest.java    | 93 ++++++++++++++++++++
 ...rmandPrince853FieldStepInterpolatorTest.java | 49 +++++++++++
 2 files changed, 142 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/b713e4ca/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegratorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegratorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegratorTest.java
new file mode 100644
index 0000000..61a9fd8
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldIntegratorTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class DormandPrince853FieldIntegratorTest extends AbstractEmbeddedRungeKuttaFieldIntegratorTest {
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double scalAbsoluteTolerance, final double scalRelativeTolerance) {
+        return new DormandPrince853FieldIntegrator<T>(field, minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
+    }
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double[] vecAbsoluteTolerance, final double[] vecRelativeTolerance) {
+        return new DormandPrince853FieldIntegrator<T>(field, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
+    }
+
+    @Test
+    public void testNonFieldIntegratorConsistency() {
+        doTestNonFieldIntegratorConsistency(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testSanityChecks() {
+        doTestSanityChecks(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testBackward() {
+        doTestBackward(Decimal64Field.getInstance(), 1.1e-7, 1.1e-7, 1.0e-12, "Dormand-Prince 8 (5, 3)");
+    }
+
+    @Test
+    public void testKepler() {
+        doTestKepler(Decimal64Field.getInstance(), 2.4e-10);
+    }
+
+    @Override
+    public void testForwardBackwardExceptions() {
+        doTestForwardBackwardExceptions(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testMinStep() {
+        doTestMinStep(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testIncreasingTolerance() {
+        // the 1.3 factor is only valid for this test
+        // and has been obtained from trial and error
+        // there is no general relation between local and global errors
+        doTestIncreasingTolerance(Decimal64Field.getInstance(), 1.3, 1.0e-12);
+    }
+
+    @Override
+    public void testEvents() {
+        doTestEvents(Decimal64Field.getInstance(), 2.1e-7, "Dormand-Prince 8 (5, 3)");
+    }
+
+    @Override
+    public void testEventsErrors() {
+        doTestEventsErrors(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testEventsNoConvergence() {
+        doTestEventsNoConvergence(Decimal64Field.getInstance());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/b713e4ca/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolatorTest.java
new file mode 100644
index 0000000..8153ed3
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/DormandPrince853FieldStepInterpolatorTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.FieldEquationsMapper;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class DormandPrince853FieldStepInterpolatorTest extends AbstractRungeKuttaFieldStepInterpolatorTest {
+
+    protected <T extends RealFieldElement<T>> RungeKuttaFieldStepInterpolator<T>
+    createInterpolator(Field<T> field, boolean forward, FieldEquationsMapper<T> mapper) {
+        return new DormandPrince853FieldStepInterpolator<T>(field, forward, mapper);
+    }
+
+    @Test
+    public void interpolationAtBounds() {
+        doInterpolationAtBounds(Decimal64Field.getInstance(), 1.0e-50);
+    }
+
+    @Test
+    public void interpolationInside() {
+        doInterpolationInside(Decimal64Field.getInstance(), 1.0e-50, 1.0e-50);
+    }
+
+    @Test
+    public void nonFieldInterpolatorConsistency() {
+        doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.0e-50, 1.0e-50, 1.0e-50, 1.0e-50);
+    }
+
+}


[2/8] [math] Fixed state copying after event detection.

Posted by lu...@apache.org.
Fixed state copying after event detection.

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

Branch: refs/heads/field-ode
Commit: d671edefb64cfccfb51fc957b5a94cc26fe57059
Parents: de965cb
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 18:08:31 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 18:08:31 2015 +0100

----------------------------------------------------------------------
 .../math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/d671edef/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java b/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
index 5f648f8..39a89e1 100644
--- a/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/nonstiff/EmbeddedRungeKuttaFieldIntegrator.java
@@ -260,7 +260,8 @@ public abstract class EmbeddedRungeKuttaFieldIntegrator<T extends RealFieldEleme
             while (error.subtract(1.0).getReal() >= 0) {
 
                 // first stage
-                yDotK[0] = stepStart.getDerivative();
+                y        = equations.getMapper().mapState(stepStart);
+                yDotK[0] = equations.getMapper().mapDerivative(stepStart);
 
                 if (firstTime) {
                     final T[] scale = MathArrays.buildArray(getField(), mainSetDimension);
@@ -331,7 +332,6 @@ public abstract class EmbeddedRungeKuttaFieldIntegrator<T extends RealFieldEleme
             interpolator.storeState(stateTmp);
             System.arraycopy(yTmp, 0, y, 0, y0.length);
             stepStart = acceptStep(interpolator, finalTime);
-            System.arraycopy(y, 0, yTmp, 0, y.length);
 
             if (!isLastStep) {
 


[6/8] [math] Added tests for the Higham-Hall 5(4) integrator.

Posted by lu...@apache.org.
Added tests for the Higham-Hall 5(4) integrator.

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

Branch: refs/heads/field-ode
Commit: 8f1c2d6a5c236e908c4d7ac490847c84113a6427
Parents: a3d1099
Author: Luc Maisonobe <lu...@apache.org>
Authored: Tue Dec 8 20:26:54 2015 +0100
Committer: Luc Maisonobe <lu...@apache.org>
Committed: Tue Dec 8 20:26:54 2015 +0100

----------------------------------------------------------------------
 .../HighamHall54FieldIntegratorTest.java        | 93 ++++++++++++++++++++
 .../HighamHall54FieldStepInterpolatorTest.java  | 49 +++++++++++
 2 files changed, 142 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/8f1c2d6a/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegratorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegratorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegratorTest.java
new file mode 100644
index 0000000..9ac49f4
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldIntegratorTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class HighamHall54FieldIntegratorTest extends AbstractEmbeddedRungeKuttaFieldIntegratorTest {
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double scalAbsoluteTolerance, final double scalRelativeTolerance) {
+        return new HighamHall54FieldIntegrator<T>(field, minStep, maxStep, scalAbsoluteTolerance, scalRelativeTolerance);
+    }
+
+    protected <T extends RealFieldElement<T>> EmbeddedRungeKuttaFieldIntegrator<T>
+    createIntegrator(Field<T> field, final double minStep, final double maxStep,
+                     final double[] vecAbsoluteTolerance, final double[] vecRelativeTolerance) {
+        return new HighamHall54FieldIntegrator<T>(field, minStep, maxStep, vecAbsoluteTolerance, vecRelativeTolerance);
+    }
+
+    @Test
+    public void testNonFieldIntegratorConsistency() {
+        doTestNonFieldIntegratorConsistency(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testSanityChecks() {
+        doTestSanityChecks(Decimal64Field.getInstance());
+    }
+
+    @Test
+    public void testBackward() {
+        doTestBackward(Decimal64Field.getInstance(), 5.0e-7, 5.0e-7, 1.0e-12, "Higham-Hall 5(4)");
+    }
+
+    @Test
+    public void testKepler() {
+        doTestKepler(Decimal64Field.getInstance(), 1.5e-4);
+    }
+
+    @Override
+    public void testForwardBackwardExceptions() {
+        doTestForwardBackwardExceptions(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testMinStep() {
+        doTestMinStep(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testIncreasingTolerance() {
+        // the 1.3 factor is only valid for this test
+        // and has been obtained from trial and error
+        // there is no general relation between local and global errors
+        doTestIncreasingTolerance(Decimal64Field.getInstance(), 1.3, 1.0e-12);
+    }
+
+    @Override
+    public void testEvents() {
+        doTestEvents(Decimal64Field.getInstance(), 1.0e-7, "Higham-Hall 5(4)");
+    }
+
+    @Override
+    public void testEventsErrors() {
+        doTestEventsErrors(Decimal64Field.getInstance());
+    }
+
+    @Override
+    public void testEventsNoConvergence() {
+        doTestEventsNoConvergence(Decimal64Field.getInstance());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/8f1c2d6a/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldStepInterpolatorTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldStepInterpolatorTest.java
new file mode 100644
index 0000000..e66cf48
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/HighamHall54FieldStepInterpolatorTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.nonstiff;
+
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.FieldEquationsMapper;
+import org.apache.commons.math3.util.Decimal64Field;
+import org.junit.Test;
+
+public class HighamHall54FieldStepInterpolatorTest extends AbstractRungeKuttaFieldStepInterpolatorTest {
+
+    protected <T extends RealFieldElement<T>> RungeKuttaFieldStepInterpolator<T>
+    createInterpolator(Field<T> field, boolean forward, FieldEquationsMapper<T> mapper) {
+        return new HighamHall54FieldStepInterpolator<T>(field, forward, mapper);
+    }
+
+    @Test
+    public void interpolationAtBounds() {
+        doInterpolationAtBounds(Decimal64Field.getInstance(), 4.9e-16);
+    }
+
+    @Test
+    public void interpolationInside() {
+        doInterpolationInside(Decimal64Field.getInstance(), 4.0e-13, 2.7e-15);
+    }
+
+    @Test
+    public void nonFieldInterpolatorConsistency() {
+        doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.4e-17, 1.0e-50, 1.0e-50, 1.0e-50);
+    }
+
+}