Repository: commons-math
Updated Branches:
  refs/heads/field-ode 4685d0376 -> 5c647c12e


Interfaces and normalizer for step handling.

This corresponds to a continuous output feature. It basically allow to
navigate throughout current step instead of having only discrete grid
points. It is a major feature of our ode package.

JIRA: MATH-1288

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

Branch: refs/heads/field-ode
Commit: 5c647c12e6910b27bd8815b07978f9dc51638795
Parents: 4685d03
Author: Luc Maisonobe <l...@apache.org>
Authored: Wed Nov 11 21:23:35 2015 +0100
Committer: Luc Maisonobe <l...@apache.org>
Committed: Wed Nov 11 21:23:35 2015 +0100

----------------------------------------------------------------------
 .../ode/sampling/FieldFixedStepHandler.java     |  69 +++++
 .../math3/ode/sampling/FieldStepHandler.java    |  75 +++++
 .../ode/sampling/FieldStepInterpolator.java     |  78 ++++++
 .../math3/ode/sampling/FieldStepNormalizer.java | 272 +++++++++++++++++++
 .../ode/sampling/StepNormalizerBounds.java      |   1 +
 .../math3/ode/sampling/StepNormalizerMode.java  |   1 +
 6 files changed, 496 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/FieldFixedStepHandler.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/FieldFixedStepHandler.java
 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldFixedStepHandler.java
new file mode 100644
index 0000000..9d4fd70
--- /dev/null
+++ 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldFixedStepHandler.java
@@ -0,0 +1,69 @@
+/*
+ * 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.sampling;
+
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
+
+/**
+ * This interface represents a handler that should be called after
+ * each successful fixed step.
+
+ * <p>This interface should be implemented by anyone who is interested
+ * in getting the solution of an ordinary differential equation at
+ * fixed time steps. Objects implementing this interface should be
+ * wrapped within an instance of {@link FieldStepNormalizer} that itself
+ * is used as the general {@link FieldStepHandler} by the integrator. The
+ * {@link FieldStepNormalizer} object is called according to the integrator
+ * internal algorithms and it calls objects implementing this
+ * interface as necessary at fixed time steps.</p>
+ *
+ * @see FieldStepHandler
+ * @see FieldStepNormalizer
+ * @see FieldStepInterpolator
+ * @param <T> the type of the field elements
+ * @since 3.6
+ */
+
+public interface FieldFixedStepHandler<T extends RealFieldElement<T>> {
+
+    /** Initialize step handler at the start of an ODE integration.
+     * <p>
+     * This method is called once at the start of the integration. It
+     * may be used by the step handler to initialize some internal data
+     * if needed.
+     * </p>
+     * @param initialState initial time, state vector and derivative
+     * @param finalTime target time for the integration
+     */
+    void init(FieldODEStateAndDerivative<T> initialState, T finalTime);
+
+    /**
+     * Handle the last accepted step
+     * @param state current value of the independent <i>time</i> variable,
+     * state vector and derivative
+     * For efficiency purposes, the {@link FieldStepNormalizer} class reuses
+     * the same array on each call, so if
+     * the instance wants to keep it across all calls (for example to
+     * provide at the end of the integration a complete array of all
+     * steps), it should build a local copy store this copy.
+     * @param isLast true if the step is the last one
+     */
+    void handleStep(FieldODEStateAndDerivative<T> state, boolean isLast);
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepHandler.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepHandler.java 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepHandler.java
new file mode 100644
index 0000000..f46cc06
--- /dev/null
+++ b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepHandler.java
@@ -0,0 +1,75 @@
+/*
+ * 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.sampling;
+
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.exception.MaxCountExceededException;
+import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
+
+/**
+ * This interface represents a handler that should be called after
+ * each successful step.
+ *
+ * <p>The ODE integrators compute the evolution of the state vector at
+ * some grid points that depend on their own internal algorithm. Once
+ * they have found a new grid point (possibly after having computed
+ * several evaluation of the derivative at intermediate points), they
+ * provide it to objects implementing this interface. These objects
+ * typically either ignore the intermediate steps and wait for the
+ * last one, store the points in an ephemeris, or forward them to
+ * specialized processing or output methods.</p>
+ *
+ * @see org.apache.commons.math3.ode.FieldFirstOrderIntegrator
+ * @see FieldStepInterpolator
+ * @param <T> the type of the field elements
+ * @since 3.6
+ */
+
+public interface FieldStepHandler<T extends RealFieldElement<T>> {
+
+    /** Initialize step handler at the start of an ODE integration.
+     * <p>
+     * This method is called once at the start of the integration. It
+     * may be used by the step handler to initialize some internal data
+     * if needed.
+     * </p>
+     * @param initialState initial time, state vector and derivative
+     * @param finalTime target time for the integration
+     */
+    void init(FieldODEStateAndDerivative<T> initialState, T finalTime);
+
+    /**
+     * Handle the last accepted step
+     * @param interpolator interpolator for the last accepted step. For
+     * efficiency purposes, the various integrators reuse the same
+     * object on each call, so if the instance wants to keep it across
+     * all calls (for example to provide at the end of the integration a
+     * continuous model valid throughout the integration range, as the
+     * {@link org.apache.commons.math3.ode.ContinuousOutputModel
+     * ContinuousOutputModel} class does), it should build a local copy
+     * using the clone method of the interpolator and store this copy.
+     * Keeping only a reference to the interpolator and reusing it will
+     * result in unpredictable behavior (potentially crashing the application).
+     * @param isLast true if the step is the last one
+     * @exception MaxCountExceededException if the interpolator throws one 
because
+     * the number of functions evaluations is exceeded
+     */
+    void handleStep(FieldStepInterpolator<T> interpolator, boolean isLast)
+        throws MaxCountExceededException;
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepInterpolator.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepInterpolator.java
 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepInterpolator.java
new file mode 100644
index 0000000..b732bc8
--- /dev/null
+++ 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepInterpolator.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.sampling;
+
+import java.io.Externalizable;
+
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
+
+/** This interface represents an interpolator over the last step
+ * during an ODE integration.
+ *
+ * <p>The various ODE integrators provide objects implementing this
+ * interface to the step handlers. These objects are often custom
+ * objects tightly bound to the integrator internal algorithms. The
+ * handlers can use these objects to retrieve the state vector at
+ * intermediate times between the previous and the current grid points
+ * (this feature is often called dense output).</p>
+ *
+ * @param <T> the type of the field elements
+ * @see org.apache.commons.math3.ode.FieldFirstOrderIntegrator
+ * @see FieldStepHandler
+ * @since 3.6
+ */
+
+public interface FieldStepInterpolator<T extends RealFieldElement<T>> extends 
Externalizable {
+
+  /**
+   * Get the state at previous grid point time.
+   * @return state at previous grid point time
+   */
+  FieldODEStateAndDerivative<T> getPreviousState();
+
+  /**
+   * Get the state at current grid point time.
+   * @return state at current grid point time
+   */
+  FieldODEStateAndDerivative<T> getCurrentState();
+
+  /**
+   * Get the state at interpolated time.
+   * <p>Setting the time outside of the current step is allowed, but
+   * should be used with care since the accuracy of the interpolator will
+   * probably be very poor far from this step. This allowance has been
+   * added to simplify implementation of search algorithms near the
+   * step endpoints.</p>
+   * @param time time of the interpolated point
+   * @return state at interpolated time
+   */
+  FieldODEStateAndDerivative<T> getInterpolatedState(T time);
+
+  /** Check if the natural integration direction is forward.
+   * <p>This method provides the integration direction as specified by
+   * the integrator itself, it avoid some nasty problems in
+   * degenerated cases like null steps due to cancellation at step
+   * initialization, step control or discrete events
+   * triggering.</p>
+   * @return true if the integration variable (time) increases during
+   * integration
+   */
+  boolean isForward();
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepNormalizer.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepNormalizer.java 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepNormalizer.java
new file mode 100644
index 0000000..49a5077
--- /dev/null
+++ 
b/src/main/java/org/apache/commons/math3/ode/sampling/FieldStepNormalizer.java
@@ -0,0 +1,272 @@
+/*
+ * 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.sampling;
+
+import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.exception.MaxCountExceededException;
+import org.apache.commons.math3.ode.FieldODEStateAndDerivative;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.Precision;
+
+/**
+ * This class wraps an object implementing {@link FieldFixedStepHandler}
+ * into a {@link FieldStepHandler}.
+
+ * <p>This wrapper allows to use fixed step handlers with general
+ * integrators which cannot guaranty their integration steps will
+ * remain constant and therefore only accept general step
+ * handlers.</p>
+ *
+ * <p>The stepsize used is selected at construction time. The {@link
+ * FieldFixedStepHandler#handleStep handleStep} method of the underlying
+ * {@link FieldFixedStepHandler} object is called at normalized times. The
+ * normalized times can be influenced by the {@link StepNormalizerMode} and
+ * {@link StepNormalizerBounds}.</p>
+ *
+ * <p>There is no constraint on the integrator, it can use any time step
+ * it needs (time steps longer or shorter than the fixed time step and
+ * non-integer ratios are all allowed).</p>
+ *
+ * <p>
+ * <table border="1" align="center">
+ * <tr BGCOLOR="#CCCCFF"><td colspan=6><font size="+2">Examples (step size = 
0.5)</font></td></tr>
+ * <tr BGCOLOR="#EEEEFF"><font size="+1"><td>Start time</td><td>End time</td>
+ *  <td>Direction</td><td>{@link StepNormalizerMode Mode}</td>
+ *  <td>{@link StepNormalizerBounds Bounds}</td><td>Output</td></font></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>0.8, 1.3, 1.8, 2.3, 2.8</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>0.3, 0.8, 1.3, 1.8, 2.3, 2.8</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>0.8, 1.3, 1.8, 2.3, 2.8, 3.1</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>0.3, 0.8, 1.3, 1.8, 2.3, 2.8, 
3.1</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>0.3, 0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 
3.1</td></tr>
+ * <tr><td>0.3</td><td>3.1</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>0.3, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 
3.1</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>0.5, 1.0, 1.5, 2.0, 2.5, 3.0</td></tr>
+ * <tr><td>0.0</td><td>3.0</td><td>forward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 
3.0</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>2.6, 2.1, 1.6, 1.1, 0.6</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>3.1, 2.6, 2.1, 1.6, 1.1, 0.6</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>2.6, 2.1, 1.6, 1.1, 0.6, 0.3</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>3.1, 2.6, 2.1, 1.6, 1.1, 0.6, 
0.3</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 
0.5</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>3.1, 3.0, 2.5, 2.0, 1.5, 1.0, 
0.5</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.3</td></tr>
+ * <tr><td>3.1</td><td>0.3</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>3.1, 3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.3</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#INCREMENT INCREMENT}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#NEITHER NEITHER}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#FIRST FIRST}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#LAST LAST}</td><td>2.5, 2.0, 1.5, 1.0, 0.5, 0.0</td></tr>
+ * <tr><td>3.0</td><td>0.0</td><td>backward</td><td>{@link 
StepNormalizerMode#MULTIPLES MULTIPLES}</td><td>{@link 
StepNormalizerBounds#BOTH BOTH}</td><td>3.0, 2.5, 2.0, 1.5, 1.0, 0.5, 
0.0</td></tr>
+ * </table>
+ * </p>
+ *
+ * @param <T> the type of the field elements
+ * @see FieldStepHandler
+ * @see FieldFixedStepHandler
+ * @see StepNormalizerMode
+ * @see StepNormalizerBounds
+ * @since 3.6
+ */
+
+public class FieldStepNormalizer<T extends RealFieldElement<T>> implements 
FieldStepHandler<T> {
+    /** Fixed time step. */
+    private double h;
+
+    /** Underlying step handler. */
+    private final FieldFixedStepHandler<T> handler;
+
+    /** First step state. */
+    private FieldODEStateAndDerivative<T> first;
+
+    /** Last step step. */
+    private FieldODEStateAndDerivative<T> last;
+
+    /** Integration direction indicator. */
+    private boolean forward;
+
+    /** The step normalizer bounds settings to use. */
+    private final StepNormalizerBounds bounds;
+
+    /** The step normalizer mode to use. */
+    private final StepNormalizerMode mode;
+
+    /** Simple constructor. Uses {@link StepNormalizerMode#INCREMENT INCREMENT}
+     * mode, and {@link StepNormalizerBounds#FIRST FIRST} bounds setting, for
+     * backwards compatibility.
+     * @param h fixed time step (sign is not used)
+     * @param handler fixed time step handler to wrap
+     */
+    public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> 
handler) {
+        this(h, handler, StepNormalizerMode.INCREMENT,
+             StepNormalizerBounds.FIRST);
+    }
+
+    /** Simple constructor. Uses {@link StepNormalizerBounds#FIRST FIRST}
+     * bounds setting.
+     * @param h fixed time step (sign is not used)
+     * @param handler fixed time step handler to wrap
+     * @param mode step normalizer mode to use
+     * @since 3.0
+     */
+    public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> 
handler,
+                               final StepNormalizerMode mode) {
+        this(h, handler, mode, StepNormalizerBounds.FIRST);
+    }
+
+    /** Simple constructor. Uses {@link StepNormalizerMode#INCREMENT INCREMENT}
+     * mode.
+     * @param h fixed time step (sign is not used)
+     * @param handler fixed time step handler to wrap
+     * @param bounds step normalizer bounds setting to use
+     * @since 3.0
+     */
+    public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> 
handler,
+                               final StepNormalizerBounds bounds) {
+        this(h, handler, StepNormalizerMode.INCREMENT, bounds);
+    }
+
+    /** Simple constructor.
+     * @param h fixed time step (sign is not used)
+     * @param handler fixed time step handler to wrap
+     * @param mode step normalizer mode to use
+     * @param bounds step normalizer bounds setting to use
+     * @since 3.0
+     */
+    public FieldStepNormalizer(final double h, final FieldFixedStepHandler<T> 
handler,
+                               final StepNormalizerMode mode, final 
StepNormalizerBounds bounds) {
+        this.h       = FastMath.abs(h);
+        this.handler = handler;
+        this.mode    = mode;
+        this.bounds  = bounds;
+        first        = null;
+        last         = null;
+        forward      = true;
+    }
+
+    /** {@inheritDoc} */
+    public void init(final FieldODEStateAndDerivative<T> initialState, final T 
finalTime) {
+
+        first   = null;
+        last    = null;
+        forward = true;
+
+        // initialize the underlying handler
+        handler.init(initialState, finalTime);
+
+    }
+
+    /**
+     * Handle the last accepted step
+     * @param interpolator interpolator for the last accepted step. For
+     * efficiency purposes, the various integrators reuse the same
+     * object on each call, so if the instance wants to keep it across
+     * all calls (for example to provide at the end of the integration a
+     * continuous model valid throughout the integration range), it
+     * should build a local copy using the clone method and store this
+     * copy.
+     * @param isLast true if the step is the last one
+     * @exception MaxCountExceededException if the interpolator throws one 
because
+     * the number of functions evaluations is exceeded
+     */
+    public void handleStep(final FieldStepInterpolator<T> interpolator, final 
boolean isLast)
+        throws MaxCountExceededException {
+        // The first time, update the last state with the start information.
+        if (last == null) {
+
+            first   = interpolator.getPreviousState();
+            last    = first;
+
+            // Take the integration direction into account.
+            forward = interpolator.isForward();
+            if (!forward) {
+                h = -h;
+            }
+        }
+
+        // Calculate next normalized step time.
+        T nextTime = (mode == StepNormalizerMode.INCREMENT) ?
+                     last.getTime().add(h) :
+                     
last.getTime().getField().getZero().add((FastMath.floor(last.getTime().getReal()
 / h) + 1) * h);
+        if (mode == StepNormalizerMode.MULTIPLES &&
+            Precision.equals(nextTime.getReal(), last.getTime().getReal(), 1)) 
{
+            nextTime = nextTime.add(h);
+        }
+
+        // Process normalized steps as long as they are in the current step.
+        boolean nextInStep = isNextInStep(nextTime, interpolator);
+        while (nextInStep) {
+            // Output the stored previous step.
+            doNormalizedStep(false);
+
+            // Store the next step as last step.
+            last = interpolator.getInterpolatedState(nextTime);
+
+            // Move on to the next step.
+            nextTime = nextTime.add(h);
+            nextInStep = isNextInStep(nextTime, interpolator);
+        }
+
+        if (isLast) {
+            // There will be no more steps. The stored one should be given to
+            // the handler. We may have to output one more step. Only the last
+            // one of those should be flagged as being the last.
+            final boolean addLast = bounds.lastIncluded() &&
+                                    last.getTime().getReal() != 
interpolator.getCurrentState().getTime().getReal();
+            doNormalizedStep(!addLast);
+            if (addLast) {
+                last = interpolator.getCurrentState();
+                doNormalizedStep(true);
+            }
+        }
+    }
+
+    /**
+     * Returns a value indicating whether the next normalized time is in the
+     * current step.
+     * @param nextTime the next normalized time
+     * @param interpolator interpolator for the last accepted step, to use to
+     * get the end time of the current step
+     * @return value indicating whether the next normalized time is in the
+     * current step
+     */
+    private boolean isNextInStep(final T nextTime, final 
FieldStepInterpolator<T> interpolator) {
+        return forward ?
+               nextTime.getReal() <= 
interpolator.getCurrentState().getTime().getReal() :
+               nextTime.getReal() >= 
interpolator.getCurrentState().getTime().getReal();
+    }
+
+    /**
+     * Invokes the underlying step handler for the current normalized step.
+     * @param isLast true if the step is the last one
+     */
+    private void doNormalizedStep(final boolean isLast) {
+        if (!bounds.firstIncluded() && first.getTime().getReal() == 
last.getTime().getReal()) {
+            return;
+        }
+        handler.handleStep(last, isLast);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerBounds.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerBounds.java 
b/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerBounds.java
index 0ccc58a..ca35e82 100644
--- 
a/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerBounds.java
+++ 
b/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerBounds.java
@@ -22,6 +22,7 @@ package org.apache.commons.math3.ode.sampling;
  * and last points. Note that if the last point coincides with a normalized
  * point, then the underlying fixed step size step handler is always called,
  * regardless of these settings.
+ * @see FieldStepNormalizer
  * @see StepNormalizer
  * @see StepNormalizerMode
  * @since 3.0

http://git-wip-us.apache.org/repos/asf/commons-math/blob/5c647c12/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerMode.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerMode.java 
b/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerMode.java
index 0a2ddc9..c6f4c69 100644
--- 
a/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerMode.java
+++ 
b/src/main/java/org/apache/commons/math3/ode/sampling/StepNormalizerMode.java
@@ -20,6 +20,7 @@ package org.apache.commons.math3.ode.sampling;
 
 /** {@link StepNormalizer Step normalizer} modes. Determines how the step size
  * is interpreted.
+ * @see FieldStepNormalizer
  * @see StepNormalizer
  * @see StepNormalizerBounds
  * @since 3.0

Reply via email to