Added new consistency tests. We want the field-based integrators to be consistent with the regular double-based 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/d9431ea3 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/d9431ea3 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/d9431ea3 Branch: refs/heads/MATH_3_X Commit: d9431ea3d967a7536a18046a94855ce86400a8a8 Parents: 9829c0f Author: Luc Maisonobe <l...@apache.org> Authored: Tue Dec 8 12:01:33 2015 +0100 Committer: Luc Maisonobe <l...@apache.org> Committed: Tue Dec 8 12:01:33 2015 +0100 ---------------------------------------------------------------------- ...ractRungeKuttaFieldStepInterpolatorTest.java | 124 ++++++++++++++++++- ...sicalRungKuttaFieldStepInterpolatorTest.java | 5 + .../EulerFieldStepInterpolatorTest.java | 5 + .../nonstiff/GillFieldStepInterpolatorTest.java | 5 + .../LutherFieldStepInterpolatorTest.java | 5 + .../MidpointFieldStepInterpolatorTest.java | 5 + .../ThreeEighthesFieldStepInterpolatorTest.java | 5 + 7 files changed, 152 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/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 e088434..9f419b9 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,10 +22,12 @@ import java.lang.reflect.InvocationTargetException; import org.apache.commons.math3.Field; import org.apache.commons.math3.RealFieldElement; +import org.apache.commons.math3.ode.EquationsMapper; import org.apache.commons.math3.ode.FieldEquationsMapper; import org.apache.commons.math3.ode.FieldExpandableODE; import org.apache.commons.math3.ode.FieldFirstOrderDifferentialEquations; import org.apache.commons.math3.ode.FieldODEStateAndDerivative; +import org.apache.commons.math3.ode.sampling.AbstractFieldStepInterpolator; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.MathArrays; import org.junit.Assert; @@ -86,6 +88,49 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest { } + @Test + public abstract void nonFieldInterpolatorConsistency(); + + protected <T extends RealFieldElement<T>> void doNonFieldInterpolatorConsistency(final Field<T> field, + double epsilonSin, double epsilonCos, + double epsilonSinDot, double epsilonCosDot) { + + RungeKuttaFieldStepInterpolator<T> fieldInterpolator = + setUpInterpolator(field, new SinCos<>(field), 0.0, new double[] { 0.0, 1.0 }, 0.125); + RungeKuttaStepInterpolator regularInterpolator = convertInterpolator(fieldInterpolator); + + int n = 100; + double maxErrorSin = 0; + double maxErrorCos = 0; + double maxErrorSinDot = 0; + double maxErrorCosDot = 0; + for (int i = 0; i <= n; ++i) { + + T t = fieldInterpolator.getPreviousState().getTime().multiply(n - i). + add(fieldInterpolator.getCurrentState().getTime().multiply(i)). + divide(n); + + FieldODEStateAndDerivative<T> state = fieldInterpolator.getInterpolatedState(t); + T[] fieldY = state.getState(); + T[] fieldYDot = state.getDerivative(); + + regularInterpolator.setInterpolatedTime(t.getReal()); + double[] regularY = regularInterpolator.getInterpolatedState(); + double[] regularYDot = regularInterpolator.getInterpolatedDerivatives(); + + maxErrorSin = FastMath.max(maxErrorSin, fieldY[0].subtract(regularY[0]).abs().getReal()); + maxErrorCos = FastMath.max(maxErrorCos, fieldY[1].subtract(regularY[1]).abs().getReal()); + maxErrorSinDot = FastMath.max(maxErrorSinDot, fieldYDot[0].subtract(regularYDot[0]).abs().getReal()); + maxErrorCosDot = FastMath.max(maxErrorCosDot, fieldYDot[1].subtract(regularYDot[1]).abs().getReal()); + + } + Assert.assertEquals(0.0, maxErrorSin, epsilonSin); + Assert.assertEquals(0.0, maxErrorCos, epsilonCos); + Assert.assertEquals(0.0, maxErrorSinDot, epsilonSinDot); + Assert.assertEquals(0.0, maxErrorCosDot, epsilonCosDot); + + } + private <T extends RealFieldElement<T>> RungeKuttaFieldStepInterpolator<T> setUpInterpolator(final Field<T> field, final FieldFirstOrderDifferentialEquations<T> eqn, @@ -139,6 +184,81 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest { } + private <T extends RealFieldElement<T>> + RungeKuttaStepInterpolator convertInterpolator(final RungeKuttaFieldStepInterpolator<T> fieldInterpolator) { + + RungeKuttaStepInterpolator regularInterpolator = null; + try { + + String interpolatorName = fieldInterpolator.getClass().getName(); + String integratorName = interpolatorName.replaceAll("Field", ""); + @SuppressWarnings("unchecked") + Class<RungeKuttaStepInterpolator> clz = (Class<RungeKuttaStepInterpolator>) Class.forName(integratorName); + regularInterpolator = clz.newInstance(); + + double[][] yDotArray = null; + java.lang.reflect.Field fYD = RungeKuttaFieldStepInterpolator.class.getDeclaredField("yDotK"); + fYD.setAccessible(true); + @SuppressWarnings("unchecked") + T[][] fieldYDotk = (T[][]) fYD.get(fieldInterpolator); + yDotArray = new double[fieldYDotk.length][]; + for (int i = 0; i < yDotArray.length; ++i) { + yDotArray[i] = new double[fieldYDotk[i].length]; + for (int j = 0; j < yDotArray[i].length; ++j) { + yDotArray[i][j] = fieldYDotk[i][j].getReal(); + } + } + double[] y = new double[yDotArray[0].length]; + + EquationsMapper primaryMapper = null; + EquationsMapper[] secondaryMappers = null; + java.lang.reflect.Field fMapper = AbstractFieldStepInterpolator.class.getDeclaredField("mapper"); + fMapper.setAccessible(true); + @SuppressWarnings("unchecked") + FieldEquationsMapper<T> mapper = (FieldEquationsMapper<T>) fMapper.get(fieldInterpolator); + java.lang.reflect.Field fStart = FieldEquationsMapper.class.getDeclaredField("start"); + fStart.setAccessible(true); + int[] start = (int[]) fStart.get(mapper); + primaryMapper = new EquationsMapper(start[0], start[1]); + secondaryMappers = new EquationsMapper[mapper.getNumberOfEquations() - 1]; + for (int i = 0; i < secondaryMappers.length; ++i) { + secondaryMappers[i] = new EquationsMapper(start[i + 1], start[i + 2]); + } + + regularInterpolator.reinitialize(null, y, yDotArray, + fieldInterpolator.isForward(), + primaryMapper, secondaryMappers); + + T[] fieldPreviousY = fieldInterpolator.getPreviousState().getState(); + for (int i = 0; i < y.length; ++i) { + y[i] = fieldPreviousY[i].getReal(); + } + regularInterpolator.storeTime(fieldInterpolator.getPreviousState().getTime().getReal()); + + regularInterpolator.shift(); + + T[] fieldCurrentY = fieldInterpolator.getCurrentState().getState(); + for (int i = 0; i < y.length; ++i) { + y[i] = fieldCurrentY[i].getReal(); + } + regularInterpolator.storeTime(fieldInterpolator.getCurrentState().getTime().getReal()); + + } catch (ClassNotFoundException cnfe) { + Assert.fail(cnfe.getLocalizedMessage()); + } catch (InstantiationException ie) { + Assert.fail(ie.getLocalizedMessage()); + } catch (IllegalAccessException iae) { + Assert.fail(iae.getLocalizedMessage()); + } catch (NoSuchFieldException nsfe) { + Assert.fail(nsfe.getLocalizedMessage()); + } catch (IllegalArgumentException iae) { + Assert.fail(iae.getLocalizedMessage()); + } + + return regularInterpolator; + + } + private <T extends RealFieldElement<T>> RungeKuttaFieldIntegrator<T> createFieldIntegrator(final Field<T> field, final RungeKuttaFieldStepInterpolator<T> interpolator) { RungeKuttaFieldIntegrator<T> integrator = null; @@ -148,8 +268,8 @@ public abstract class AbstractRungeKuttaFieldStepInterpolatorTest { @SuppressWarnings("unchecked") Class<RungeKuttaFieldIntegrator<T>> clz = (Class<RungeKuttaFieldIntegrator<T>>) Class.forName(integratorName); try { - integrator = clz.getConstructor(Field.class, RealFieldElement.class).newInstance(field, - field.getOne()); + integrator = clz.getConstructor(Field.class, RealFieldElement.class). + newInstance(field, field.getOne()); } catch (NoSuchMethodException nsme) { try { integrator = clz.getConstructor(Field.class, http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungKuttaFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungKuttaFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungKuttaFieldStepInterpolatorTest.java index ba847c8..ed70fa7 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungKuttaFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/ClassicalRungKuttaFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class ClassicalRungKuttaFieldStepInterpolatorTest extends AbstractRungeKu doInterpolationInside(Decimal64Field.getInstance(), 2.6e-7, 3.6e-6); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 2.8e-17, 1.2e-16, 2.3e-16, 1.0e-50); + } + } http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/EulerFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/EulerFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/EulerFieldStepInterpolatorTest.java index 4c3c608..4e28c65 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/EulerFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/EulerFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class EulerFieldStepInterpolatorTest extends AbstractRungeKuttaFieldStepI doInterpolationInside(Decimal64Field.getInstance(), 3.3e-4, 7.9e-3); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.0e-50, 1.0e-50, 1.0e-50, 1.0e-50); + } + } http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/GillFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/GillFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/GillFieldStepInterpolatorTest.java index 3ed0b98..5d4c293 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/GillFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/GillFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class GillFieldStepInterpolatorTest extends AbstractRungeKuttaFieldStepIn doInterpolationInside(Decimal64Field.getInstance(), 2.6e-7, 3.6e-6); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.4e-17, 1.0e-50, 1.0e-50, 1.0e-50); + } + } http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherFieldStepInterpolatorTest.java index 916456b..6f34f8e 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/LutherFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class LutherFieldStepInterpolatorTest extends AbstractRungeKuttaFieldStep doInterpolationInside(Decimal64Field.getInstance(), 1.1e-7, 9.6e-9); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 8.4e-17, 2.3e-16, 2.1e-14, 1.3e-15); + } + } http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldStepInterpolatorTest.java index d962856..94ac932 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/MidpointFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class MidpointFieldStepInterpolatorTest extends AbstractRungeKuttaFieldSt doInterpolationInside(Decimal64Field.getInstance(), 3.3e-4, 1.1e-5); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.0e-50, 1.0e-50, 1.0e-50, 1.0e-50); + } + } http://git-wip-us.apache.org/repos/asf/commons-math/blob/d9431ea3/src/test/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldStepInterpolatorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldStepInterpolatorTest.java b/src/test/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldStepInterpolatorTest.java index 0b3c88f..f22af0b 100644 --- a/src/test/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldStepInterpolatorTest.java +++ b/src/test/java/org/apache/commons/math3/ode/nonstiff/ThreeEighthesFieldStepInterpolatorTest.java @@ -41,4 +41,9 @@ public class ThreeEighthesFieldStepInterpolatorTest extends AbstractRungeKuttaFi doInterpolationInside(Decimal64Field.getInstance(), 2.6e-7, 3.6e-6); } + @Test + public void nonFieldInterpolatorConsistency() { + doNonFieldInterpolatorConsistency(Decimal64Field.getInstance(), 1.4e-17, 1.2e-16, 1.0e-50, 1.0e-50); + } + }