diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem1.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem1.java
new file mode 100644
index 000000000..f79fad028
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem1.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+
+ *
This specific problem is the following differential equation :
+ *
+ * y' = -y
+ *
+ * the solution of this equation is a simple exponential function :
+ *
+ * y (t) = y (t0) exp (t0-t)
+ *
+ *
+
+ * @param the type of the field elements
+ */
+public class TestFieldProblem1>
+ extends TestFieldProblemAbstract {
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem1(Field field) {
+ super(field);
+ setInitialConditions(convert(0.0), convert(1.0, 0.1));
+ setFinalConditions(convert(4.0));
+ setErrorScale(convert(1.0, 1.0));
+ }
+
+ @Override
+ public T[] doComputeDerivatives(T t, T[] y) {
+
+ final T[] yDot = MathArrays.buildArray(getField(), getDimension());
+
+ // compute the derivatives
+ for (int i = 0; i < getDimension(); ++i) {
+ yDot[i] = y[i].negate();
+ }
+
+ return yDot;
+
+ }
+
+ @Override
+ public T[] computeTheoreticalState(T t) {
+ final T[] y0 = getInitialState();
+ final T[] y = MathArrays.buildArray(getField(), getDimension());
+ T c = getInitialTime().subtract(t).exp();
+ for (int i = 0; i < getDimension(); ++i) {
+ y[i] = c.multiply(y0[i]);
+ }
+ return y;
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem2.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem2.java
new file mode 100644
index 000000000..7f5b0e375
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem2.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+
+ * This specific problem is the following differential equation :
+ *
+ * y' = t^3 - t y
+ *
+ * with the initial condition y (0) = 0. The solution of this equation
+ * is the following function :
+ *
+ * y (t) = t^2 + 2 (exp (- t^2 / 2) - 1)
+ *
+ *
+
+ * @param the type of the field elements
+ */
+public class TestFieldProblem2>
+ extends TestFieldProblemAbstract {
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem2(Field field) {
+ super(field);
+ setInitialConditions(convert(0.0), convert(new double[] { 0.0 }));
+ setFinalConditions(convert(1.0));
+ setErrorScale(convert(new double[] { 1.0 }));
+ }
+
+ @Override
+ public T[] doComputeDerivatives(T t, T[] y) {
+
+ final T[] yDot = MathArrays.buildArray(getField(), getDimension());
+ // compute the derivatives
+ for (int i = 0; i < getDimension(); ++i) {
+ yDot[i] = t.multiply(t.multiply(t).subtract(y[i]));
+ }
+
+ return yDot;
+
+ }
+
+ @Override
+ public T[] computeTheoreticalState(T t) {
+ final T[] y = MathArrays.buildArray(getField(), getDimension());
+ T t2 = t.multiply(t);
+ T c = t2.add(t2.multiply(-0.5).exp().subtract(1).multiply(2));
+ for (int i = 0; i < getDimension(); ++i) {
+ y[i] = c;
+ }
+ return y;
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem3.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem3.java
new file mode 100644
index 000000000..9540e81bc
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem3.java
@@ -0,0 +1,124 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+
+ * This specific problem is the following differential equation :
+ *
+ * y1'' = -y1/r^3 y1 (0) = 1-e y1' (0) = 0
+ * y2'' = -y2/r^3 y2 (0) = 0 y2' (0) =sqrt((1+e)/(1-e))
+ * r = sqrt (y1^2 + y2^2), e = 0.9
+ *
+ * This is a two-body problem in the plane which can be solved by
+ * Kepler's equation
+ *
+ * y1 (t) = ...
+ *
+ *
+
+ * @param the type of the field elements
+ */
+public class TestFieldProblem3>
+extends TestFieldProblemAbstract {
+
+ /** Eccentricity */
+ T e;
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ * @param e eccentricity
+ */
+ public TestFieldProblem3(Field field, T e) {
+ super(field);
+ this.e = e;
+ T[] y0 = MathArrays.buildArray(field, 4);
+ y0[0] = e.subtract(1).negate();
+ y0[1] = field.getZero();
+ y0[2] = field.getZero();
+ y0[3] = e.add(1).divide(y0[0]).sqrt();
+ setInitialConditions(convert(0.0), y0);
+ setFinalConditions(convert(20.0));
+ setErrorScale(convert(1.0, 1.0, 1.0, 1.0));
+ }
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem3(Field field) {
+ this(field, field.getZero().add(0.1));
+ }
+
+ @Override
+ public T[] doComputeDerivatives(T t, T[] y) {
+
+ final T[] yDot = MathArrays.buildArray(getField(), getDimension());
+
+ // current radius
+ T r2 = y[0].multiply(y[0]).add(y[1].multiply(y[1]));
+ T invR3 = r2.multiply(r2.sqrt()).reciprocal();
+
+ // compute the derivatives
+ yDot[0] = y[2];
+ yDot[1] = y[3];
+ yDot[2] = invR3.negate().multiply(y[0]);
+ yDot[3] = invR3.negate().multiply(y[1]);
+
+ return yDot;
+
+ }
+
+ @Override
+ public T[] computeTheoreticalState(T t) {
+
+ final T[] y = MathArrays.buildArray(getField(), getDimension());
+
+ // solve Kepler's equation
+ T E = t;
+ T d = convert(0);
+ T corr = convert(999.0);
+ for (int i = 0; (i < 50) && (corr.abs().getReal() > 1.0e-12); ++i) {
+ T f2 = e.multiply(E.sin());
+ T f0 = d.subtract(f2);
+ T f1 = e.multiply(E.cos()).subtract(1).negate();
+ T f12 = f1.add(f1);
+ corr = f0.multiply(f12).divide(f1.multiply(f12).subtract(f0.multiply(f2)));
+ d = d.subtract(corr);
+ E = t.add(d);
+ }
+
+ T cosE = E.cos();
+ T sinE = E.sin();
+
+ y[0] = cosE.subtract(e);
+ y[1] = e.multiply(e).subtract(1).negate().sqrt().multiply(sinE);
+ y[2] = sinE.divide(e.multiply(cosE).subtract(1));
+ y[3] = e.multiply(e).subtract(1).negate().sqrt().multiply(cosE).divide(e.multiply(cosE).subtract(1).negate());
+
+ return y;
+
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem4.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem4.java
new file mode 100644
index 000000000..0f76c2506
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem4.java
@@ -0,0 +1,160 @@
+/*
+ * 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;
+
+import java.lang.reflect.Array;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.events.Action;
+import org.apache.commons.math3.ode.events.FieldEventHandler;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+
+ * This specific problem is the following differential equation :
+ *
+ * x'' = -x
+ *
+ * And when x decreases down to 0, the state should be changed as follows :
+ *
+ * x' -> -x'
+ *
+ * The theoretical solution of this problem is x = |sin(t+a)|
+ *
+
+ * @param the type of the field elements
+ */
+public class TestFieldProblem4>
+ extends TestFieldProblemAbstract {
+
+ /** Time offset. */
+ private T a;
+
+ /** Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem4(Field field) {
+ super(field);
+ a = convert(1.2);
+ T[] y0 = MathArrays.buildArray(field, 2);
+ y0[0] = a.sin();
+ y0[1] = a.cos();;
+ setInitialConditions(convert(0.0), y0);
+ setFinalConditions(convert(15));
+ setErrorScale(convert(1.0, 0.0));
+ }
+
+ @Override
+ public FieldEventHandler[] getEventsHandlers() {
+ @SuppressWarnings("unchecked")
+ FieldEventHandler[] handlers =
+ (FieldEventHandler[]) Array.newInstance(FieldEventHandler.class, 2);
+ handlers[0] = new Bounce();
+ handlers[1] = new Stop();
+ return handlers;
+ }
+
+ /**
+ * Get the theoretical events times.
+ * @return theoretical events times
+ */
+ @Override
+ public T[] getTheoreticalEventsTimes() {
+ T[] array = MathArrays.buildArray(getField(), 5);
+ array[0] = a.negate().add(1 * FastMath.PI);
+ array[1] = a.negate().add(2 * FastMath.PI);
+ array[2] = a.negate().add(3 * FastMath.PI);
+ array[3] = a.negate().add(4 * FastMath.PI);
+ array[4] = convert(120.0);
+ return array;
+ }
+
+ @Override
+ public T[] doComputeDerivatives(T t, T[] y) {
+ final T[] yDot = MathArrays.buildArray(getField(), getDimension());
+ yDot[0] = y[1];
+ yDot[1] = y[0].negate();
+ return yDot;
+ }
+
+ @Override
+ public T[] computeTheoreticalState(T t) {
+ T sin = t.add(a).sin();
+ T cos = t.add(a).cos();
+ final T[] y = MathArrays.buildArray(getField(), getDimension());
+ y[0] = sin.abs();
+ y[1] = (sin.getReal() >= 0) ? cos : cos.negate();
+ return y;
+ }
+
+ private static class Bounce> implements FieldEventHandler {
+
+ private int sign;
+
+ public Bounce() {
+ sign = +1;
+ }
+
+ public void init(FieldODEStateAndDerivative state0, T t) {
+ }
+
+ public T g(FieldODEStateAndDerivative state) {
+ return state.getState()[0].multiply(sign);
+ }
+
+ public Action eventOccurred(FieldODEStateAndDerivative state, boolean increasing) {
+ // this sign change is needed because the state will be reset soon
+ sign = -sign;
+ return Action.RESET_STATE;
+ }
+
+ public FieldODEState resetState(FieldODEStateAndDerivative state) {
+ T[] y = state.getState();
+ y[0] = y[0].negate();
+ y[1] = y[1].negate();
+ return new FieldODEState(state.getTime(), y);
+ }
+
+ }
+
+ private static class Stop> implements FieldEventHandler {
+
+ public Stop() {
+ }
+
+ public void init(FieldODEStateAndDerivative state0, T t) {
+ }
+
+ public T g(FieldODEStateAndDerivative state) {
+ return state.getTime().subtract(12.0);
+ }
+
+ public Action eventOccurred(FieldODEStateAndDerivative state, boolean increasing) {
+ return Action.STOP;
+ }
+
+ public FieldODEState resetState(FieldODEStateAndDerivative state) {
+ return state;
+ }
+
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem5.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem5.java
new file mode 100644
index 000000000..f84781ace
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem5.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+ * This is the same as problem 1 except integration is done
+ * backward in time
+ * @param the type of the field elements
+ */
+public class TestFieldProblem5>
+ extends TestFieldProblem1 {
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem5(Field field) {
+ super(field);
+ setFinalConditions(getInitialTime().multiply(2).subtract(getFinalTime()));
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblem6.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem6.java
new file mode 100644
index 000000000..cb4cd3eb6
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblem6.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used in the junit tests for the ODE integrators.
+
+ * This specific problem is the following differential equation :
+ *
+ * y' = 3x^5 - y
+ *
+ * when the initial condition is y(0) = -360, the solution of this
+ * equation degenerates to a simple quintic polynomial function :
+ *
+ * y (t) = 3x^5 - 15x^4 + 60x^3 - 180x^2 + 360x - 360
+ *
+ *
+
+ * @param the type of the field elements
+ */
+public class TestFieldProblem6>
+ extends TestFieldProblemAbstract {
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ public TestFieldProblem6(Field field) {
+ super(field);
+ setInitialConditions(convert(0.0), convert( new double[] { -360.0 }));
+ setFinalConditions(convert(1.0));
+ setErrorScale(convert( new double[] { 1.0 }));
+ }
+
+ @Override
+ public T[] doComputeDerivatives(T t, T[] y) {
+
+ final T[] yDot = MathArrays.buildArray(getField(), getDimension());
+
+ // compute the derivatives
+ T t2 = t.multiply(t);
+ T t4 = t2.multiply(t2);
+ T t5 = t4.multiply(t);
+ for (int i = 0; i < getDimension(); ++i) {
+ yDot[i] = t5.multiply(3).subtract(y[i]);
+ }
+
+ return yDot;
+
+ }
+
+ @Override
+ public T[] computeTheoreticalState(T t) {
+
+ final T[] y = MathArrays.buildArray(getField(), getDimension());
+
+ for (int i = 0; i < getDimension(); ++i) {
+ y[i] = t.multiply(3).subtract(15).multiply(t).add(60).multiply(t).subtract(180).multiply(t).add(360).multiply(t).subtract(360);
+ }
+
+ return y;
+
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblemAbstract.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblemAbstract.java
new file mode 100644
index 000000000..09a10d810
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblemAbstract.java
@@ -0,0 +1,209 @@
+/*
+ * 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;
+
+import java.lang.reflect.Array;
+
+import org.apache.commons.math3.Field;
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.events.FieldEventHandler;
+import org.apache.commons.math3.util.MathArrays;
+
+/**
+ * This class is used as the base class of the problems that are
+ * integrated during the junit tests for the ODE integrators.
+ * @param the type of the field elements
+ */
+public abstract class TestFieldProblemAbstract>
+ implements FieldFirstOrderDifferentialEquations {
+
+ /** Field to which elements belong. */
+ private Field field;
+
+ /** Dimension of the problem. */
+ private int n;
+
+ /** Number of functions calls. */
+ private int calls;
+
+ /** Initial time */
+ private T t0;
+
+ /** Initial state */
+ private T[] y0;
+
+ /** Final time */
+ private T t1;
+
+ /** Error scale */
+ private T[] errorScale;
+
+ /**
+ * Simple constructor.
+ * @param field field to which elements belong
+ */
+ protected TestFieldProblemAbstract(Field field) {
+ this.field = field;
+ n = 0;
+ calls = 0;
+ t0 = field.getZero();
+ y0 = null;
+ t1 = field.getZero();
+ errorScale = null;
+ }
+
+ /**
+ * Set the initial conditions
+ * @param t0 initial time
+ * @param y0 initial state vector
+ */
+ protected void setInitialConditions(T t0, T[] y0) {
+ calls = 0;
+ n = y0.length;
+ this.t0 = t0;
+ this.y0 = y0.clone();
+ }
+
+ /**
+ * Set the final conditions.
+ * @param t1 final time
+ */
+ protected void setFinalConditions(T t1) {
+ this.t1 = t1;
+ }
+
+ /**
+ * Set the error scale
+ * @param errorScale error scale
+ */
+ protected void setErrorScale(T[] errorScale) {
+ this.errorScale = errorScale.clone();
+ }
+
+ /** get the filed to which elements belong.
+ * @return field to which elements belong
+ */
+ public Field getField() {
+ return field;
+ }
+
+ /** Get the problem dimension.
+ * @return problem dimension
+ */
+ public int getDimension() {
+ return n;
+ }
+
+ /**
+ * Get the initial time.
+ * @return initial time
+ */
+ public T getInitialTime() {
+ return t0;
+ }
+
+ /**
+ * Get the initial state vector.
+ * @return initial state vector
+ */
+ public T[] getInitialState() {
+ return y0;
+ }
+
+ /**
+ * Get the final time.
+ * @return final time
+ */
+ public T getFinalTime() {
+ return t1;
+ }
+
+ /**
+ * Get the error scale.
+ * @return error scale
+ */
+ public T[] getErrorScale() {
+ return errorScale;
+ }
+
+ /**
+ * Get the events handlers.
+ * @return events handlers */
+ public FieldEventHandler[] getEventsHandlers() {
+ @SuppressWarnings("unchecked")
+ final FieldEventHandler[] empty =
+ (FieldEventHandler[]) Array.newInstance(FieldEventHandler.class, 0);
+ return empty;
+ }
+
+ /**
+ * Get the theoretical events times.
+ * @return theoretical events times
+ */
+ public T[] getTheoreticalEventsTimes() {
+ return MathArrays.buildArray(field, 0);
+ }
+
+ /**
+ * Get the number of calls.
+ * @return nuber of calls
+ */
+ public int getCalls() {
+ return calls;
+ }
+
+ /** {@inheritDoc} */
+ public void init(T t0, T[] y0, T t) {
+ }
+
+ /** {@inheritDoc} */
+ public T[] computeDerivatives(T t, T[] y) {
+ ++calls;
+ return doComputeDerivatives(t, y);
+ }
+
+ abstract public T[] doComputeDerivatives(T t, T[] y);
+
+ /**
+ * Compute the theoretical state at the specified time.
+ * @param t time at which the state is required
+ * @return state vector at time t
+ */
+ abstract public T[] computeTheoreticalState(T t);
+
+ /** Convert a double.
+ * @param d double to convert
+ * @return converted double
+ */
+ protected T convert(double d) {
+ return field.getZero().add(d);
+ }
+
+ /** Convert a one dimension array.
+ * @param elements array elements
+ * @return converted array
+ */
+ protected T[] convert(double ... elements) {
+ T[] array = MathArrays.buildArray(field, elements.length);
+ for (int i = 0; i < elements.length; ++i) {
+ array[i] = convert(elements[i]);
+ }
+ return array;
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/math3/ode/TestFieldProblemHandler.java b/src/test/java/org/apache/commons/math3/ode/TestFieldProblemHandler.java
new file mode 100644
index 000000000..d4e20e606
--- /dev/null
+++ b/src/test/java/org/apache/commons/math3/ode/TestFieldProblemHandler.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.exception.MaxCountExceededException;
+import org.apache.commons.math3.ode.sampling.FieldStepHandler;
+import org.apache.commons.math3.ode.sampling.FieldStepInterpolator;
+import org.apache.commons.math3.util.MathUtils;
+
+/**
+ * This class is used to handle steps for the test problems
+ * integrated during the junit tests for the ODE integrators.
+ * @param the type of the field elements
+ */
+public class TestFieldProblemHandler>
+ implements FieldStepHandler {
+
+ /** Associated problem. */
+ private TestFieldProblemAbstract problem;
+
+ /** Maximal errors encountered during the integration. */
+ private T maxValueError;
+ private T maxTimeError;
+
+ /** Error at the end of the integration. */
+ private T lastError;
+
+ /** Time at the end of integration. */
+ private T lastTime;
+
+ /** ODE solver used. */
+ private FieldFirstOrderIntegrator integrator;
+
+ /** Expected start for step. */
+ private T expectedStepStart;
+
+ /**
+ * Simple constructor.
+ * @param problem problem for which steps should be handled
+ * @param integrator ODE solver used
+ */
+ public TestFieldProblemHandler(TestFieldProblemAbstract problem, FieldFirstOrderIntegrator integrator) {
+ this.problem = problem;
+ this.integrator = integrator;
+ maxValueError = problem.getField().getZero();
+ maxTimeError = problem.getField().getZero();
+ lastError = problem.getField().getZero();
+ expectedStepStart = null;
+ }
+
+ public void init(FieldODEStateAndDerivative state0, T t) {
+ maxValueError = problem.getField().getZero();
+ maxTimeError = problem.getField().getZero();
+ lastError = problem.getField().getZero();
+ expectedStepStart = null;
+ }
+
+ public void handleStep(FieldStepInterpolator interpolator, boolean isLast) throws MaxCountExceededException {
+
+ T start = integrator.getCurrentStepStart().getTime();
+ if (start.subtract(problem.getInitialTime()).divide(integrator.getCurrentSignedStepsize()).abs().getReal() > 0.001) {
+ // multistep integrators do not handle the first steps themselves
+ // so we have to make sure the integrator we look at has really started its work
+ if (expectedStepStart != null) {
+ // the step should either start at the end of the integrator step
+ // or at an event if the step is split into several substeps
+ T stepError = MathUtils.max(maxTimeError, start.subtract(expectedStepStart).abs());
+ for (T eventTime : problem.getTheoreticalEventsTimes()) {
+ stepError = MathUtils.min(stepError, start.subtract(eventTime).abs());
+ }
+ maxTimeError = MathUtils.max(maxTimeError, stepError);
+ }
+ expectedStepStart = start.add(integrator.getCurrentSignedStepsize());
+ }
+
+ T pT = interpolator.getPreviousState().getTime();
+ T cT = interpolator.getCurrentState().getTime();
+ T[] errorScale = problem.getErrorScale();
+
+ // store the error at the last step
+ if (isLast) {
+ T[] interpolatedY = interpolator.getInterpolatedState(cT).getState();
+ T[] theoreticalY = problem.computeTheoreticalState(cT);
+ for (int i = 0; i < interpolatedY.length; ++i) {
+ T error = interpolatedY[i].subtract(theoreticalY[i]).abs();
+ lastError = MathUtils.max(error, lastError);
+ }
+ lastTime = cT;
+ }
+
+ // walk through the step
+ for (int k = 0; k <= 20; ++k) {
+
+ T time = pT.add(cT.subtract(pT).multiply(k).divide(20));
+ T[] interpolatedY = interpolator.getInterpolatedState(time).getState();
+ T[] theoreticalY = problem.computeTheoreticalState(time);
+
+ // update the errors
+ for (int i = 0; i < interpolatedY.length; ++i) {
+ T error = errorScale[i].multiply(interpolatedY[i].subtract(theoreticalY[i]).abs());
+ maxValueError = MathUtils.max(error, maxValueError);
+ }
+ }
+ }
+
+ /**
+ * Get the maximal value error encountered during integration.
+ * @return maximal value error
+ */
+ public T getMaximalValueError() {
+ return maxValueError;
+ }
+
+ /**
+ * Get the maximal time error encountered during integration.
+ * @return maximal time error
+ */
+ public T getMaximalTimeError() {
+ return maxTimeError;
+ }
+
+ /**
+ * Get the error at the end of the integration.
+ * @return error at the end of the integration
+ */
+ public T getLastError() {
+ return lastError;
+ }
+
+ /**
+ * Get the time at the end of the integration.
+ * @return time at the end of the integration.
+ */
+ public T getLastTime() {
+ return lastTime;
+ }
+
+}