Repository: commons-math
Updated Branches:
  refs/heads/field-ode ea4bea1d8 -> 136f644e2


Separate equations from mapper.

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

Branch: refs/heads/field-ode
Commit: 136f644e22defc023b688c8845bb999a2a1145d8
Parents: ea4bea1
Author: Luc Maisonobe <l...@apache.org>
Authored: Sat Nov 14 14:52:09 2015 +0100
Committer: Luc Maisonobe <l...@apache.org>
Committed: Sat Nov 14 14:52:09 2015 +0100

----------------------------------------------------------------------
 .../math3/ode/AbstractFieldIntegrator.java      |   4 +-
 .../commons/math3/ode/FieldEquationsMapper.java | 167 ++++++++++++++++---
 .../commons/math3/ode/FieldExpandableODE.java   | 154 +++--------------
 3 files changed, 166 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-math/blob/136f644e/src/main/java/org/apache/commons/math3/ode/AbstractFieldIntegrator.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/AbstractFieldIntegrator.java 
b/src/main/java/org/apache/commons/math3/ode/AbstractFieldIntegrator.java
index eebef53..aa53c05 100644
--- a/src/main/java/org/apache/commons/math3/ode/AbstractFieldIntegrator.java
+++ b/src/main/java/org/apache/commons/math3/ode/AbstractFieldIntegrator.java
@@ -332,10 +332,10 @@ public abstract class AbstractFieldIntegrator<T extends 
RealFieldElement<T>> imp
                 if (needReset) {
                     // some event handler has triggered changes that
                     // invalidate the derivatives, we need to recompute them
-                    final T[] y    = equations.mapState(eventState);
+                    final T[] y    = 
equations.getMapper().mapState(eventState);
                     final T[] yDot = computeDerivatives(eventState.getTime(), 
y);
                     resetOccurred = true;
-                    return 
equations.mapStateAndDerivative(eventState.getTime(), y, yDot);
+                    return 
equations.getMapper().mapStateAndDerivative(eventState.getTime(), y, yDot);
                 }
 
                 // prepare handling of the remaining part of the step

http://git-wip-us.apache.org/repos/asf/commons-math/blob/136f644e/src/main/java/org/apache/commons/math3/ode/FieldEquationsMapper.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/commons/math3/ode/FieldEquationsMapper.java 
b/src/main/java/org/apache/commons/math3/ode/FieldEquationsMapper.java
index 38cb803..9590984 100644
--- a/src/main/java/org/apache/commons/math3/ode/FieldEquationsMapper.java
+++ b/src/main/java/org/apache/commons/math3/ode/FieldEquationsMapper.java
@@ -17,68 +17,185 @@
 
 package org.apache.commons.math3.ode;
 
+import java.io.Serializable;
+import java.lang.reflect.Array;
+
 import org.apache.commons.math3.RealFieldElement;
+import org.apache.commons.math3.exception.MathIllegalArgumentException;
+import org.apache.commons.math3.exception.util.LocalizedFormats;
 import org.apache.commons.math3.util.MathArrays;
 
 /**
  * Class mapping the part of a complete state or derivative that pertains
- * to a specific differential equation.
+ * to a set of differential equations.
  * <p>
  * Instances of this class are guaranteed to be immutable.
  * </p>
- * @see FieldSecondaryEquations
+ * @see FieldExpandableODE
  * @param <T> the type of the field elements
  * @since 3.6
  */
-public class FieldEquationsMapper<T extends RealFieldElement<T>> {
+class FieldEquationsMapper<T extends RealFieldElement<T>> implements 
Serializable {
+
+    /** Serializable UID. */
+    private static final long serialVersionUID = 20151114L;
+
+    /** Start indices of the components. */
+    private final int[] start;
+
+    /** Create a mapper by adding a new equation to another mapper.
+     * <p>
+     * The new equation will have index {@code mapper.}{@link 
#getNumberOfEquations()},
+     * or 0 if {@code mapper} is null.
+     * </p>
+     * @param mapper former mapper, with one equation less (null for first 
equation)
+     * @param dimension dimension of the equation state vector
+     */
+    FieldEquationsMapper(final FieldEquationsMapper<T> mapper, final int 
dimension) {
+        final int index = (mapper == null) ? 0 : mapper.getNumberOfEquations();
+        this.start = new int[index + 2];
+        if (mapper == null) {
+            start[0] = 0;
+        } else {
+            System.arraycopy(mapper.start, 0, start, 0, index);
+        }
+        start[index + 1] = start[index] + dimension;
+    }
+
+    /** Get the number of equations mapped.
+     * @return number of equations mapped
+     */
+    public int getNumberOfEquations() {
+        return start.length - 1;
+    }
 
-    /** Index of the first equation element in complete state arrays. */
-    private final int firstIndex;
+    /** Return the dimension of the complete set of equations.
+     * <p>
+     * The complete set of equations correspond to the primary set plus all 
secondary sets.
+     * </p>
+     * @return dimension of the complete set of equations
+     */
+    public int getTotalDimension() {
+        return start[start.length - 1];
+    }
 
-    /** Dimension of the secondary state parameters. */
-    private final int dimension;
+    /** Map a state to a complete flat array.
+     * @param state state to map
+     * @return flat array containing the mapped state, including primary and 
secondary components
+     */
+    public T[] mapState(final FieldODEState<T> state) {
+        final T[] y = MathArrays.buildArray(state.getTime().getField(), 
getTotalDimension());
+        int index = 0;
+        insertEquationData(index, state.getState(), y);
+        while (++index < getNumberOfEquations()) {
+            insertEquationData(index, state.getSecondaryState(index - 1), y);
+        }
+        return y;
+    }
 
-    /** simple constructor.
-     * @param firstIndex index of the first equation element in complete state 
arrays
-     * @param dimension dimension of the secondary state parameters
+    /** Map a state derivative to a complete flat array.
+     * @param state state to map
+     * @return flat array containing the mapped state derivative, including 
primary and secondary components
      */
-    FieldEquationsMapper(final int firstIndex, final int dimension) {
-        this.firstIndex = firstIndex;
-        this.dimension  = dimension;
+    public T[] mapDerivative(final FieldODEStateAndDerivative<T> state) {
+        final T[] yDot = MathArrays.buildArray(state.getTime().getField(), 
getTotalDimension());
+        int index = 0;
+        insertEquationData(index, state.getDerivative(), yDot);
+        while (++index < getNumberOfEquations()) {
+            insertEquationData(index, state.getSecondaryDerivative(index - 1), 
yDot);
+        }
+        return yDot;
     }
 
-    /** Get the index of the first equation element in complete state arrays.
-     * @return index of the first equation element in complete state arrays
+    /** Map a flat array to a state.
+     * @param t time
+     * @param y array to map, including primary and secondary components
+     * @return mapped state
      */
-    public int getFirstIndex() {
-        return firstIndex;
+    public FieldODEState<T> mapState(final T t, final T[] y) {
+        final int n = getNumberOfEquations();
+        int index = 0;
+        final T[] state = extractEquationData(index, y);
+        if (n < 2) {
+            return new FieldODEState<T>(t, state);
+        } else {
+            @SuppressWarnings("unchecked")
+            final T[][] secondaryState = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), n - 1);
+            while (++index < n) {
+                secondaryState[index - 1] = extractEquationData(index, y);
+            }
+            return new FieldODEState<T>(t, state, secondaryState);
+        }
     }
 
-    /** Get the dimension of the secondary state parameters.
-     * @return dimension of the secondary state parameters
+    /** Map flat arrays to a state and derivative.
+     * @param t time
+     * @param y state array to map, including primary and secondary components
+     * @param yDot state derivative array to map, including primary and 
secondary components
+     * @return mapped state
      */
-    public int getDimension() {
-        return dimension;
+    public FieldODEStateAndDerivative<T> mapStateAndDerivative(final T t, 
final T[] y, final T[] yDot) {
+        final int n = getNumberOfEquations();
+        int index = 0;
+        final T[] state      = extractEquationData(index, y);
+        final T[] derivative = extractEquationData(index, yDot);
+        if (n < 2) {
+            return new FieldODEStateAndDerivative<T>(t, state, derivative);
+        } else {
+            @SuppressWarnings("unchecked")
+            final T[][] secondaryState      = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), n - 1);
+            @SuppressWarnings("unchecked")
+            final T[][] secondaryDerivative = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), n - 1);
+            while (++index < getNumberOfEquations()) {
+                secondaryState[index - 1]      = extractEquationData(index, y);
+                secondaryDerivative[index - 1] = extractEquationData(index, 
yDot);
+            }
+            return new FieldODEStateAndDerivative<T>(t, state, derivative, 
secondaryState, secondaryDerivative);
+        }
     }
 
     /** Extract equation data from a complete state or derivative array.
+     * @param index index of the equation, must be between 0 included and
+     * {@link #getNumberOfEquations()} (excluded)
      * @param complete complete state or derivative array from which
      * equation data should be retrieved
      * @return equation data
+     * @exception MathIllegalArgumentException if index is out of range
      */
-    public T[] extractEquationData(T[] complete) {
+    public T[] extractEquationData(final int index, final T[] complete)
+        throws MathIllegalArgumentException {
+        checkIndex(index);
+        final int begin     = start[index];
+        final int dimension = start[index + 1] - begin;
         final T[] equationData = MathArrays.buildArray(complete[0].getField(), 
dimension);
-        System.arraycopy(complete, firstIndex, equationData, 0, dimension);
+        System.arraycopy(complete, begin, equationData, 0, dimension);
         return equationData;
     }
 
     /** Insert equation data into a complete state or derivative array.
+     * @param index index of the equation, must be between 0 included and
+     * {@link #getNumberOfEquations()} (excluded)
      * @param equationData equation data to be inserted into the complete array
      * @param complete placeholder where to put equation data (only the
      * part corresponding to the equation will be overwritten)
      */
-    public void insertEquationData(T[] equationData, T[] complete) {
-        System.arraycopy(equationData, 0, complete, firstIndex, dimension);
+    public void insertEquationData(final int index, T[] equationData, T[] 
complete) {
+        checkIndex(index);
+        final int begin     = start[index];
+        final int dimension = start[index + 1] - begin;
+        System.arraycopy(equationData, 0, complete, begin, dimension);
+    }
+
+    /** Check equation index.
+     * @param index index of the equation, must be between 0 included and
+     * {@link #getNumberOfEquations()} (excluded)
+     * @exception MathIllegalArgumentException if index is out of range
+     */
+    private void checkIndex(final int index) throws 
MathIllegalArgumentException {
+        if (index < 0 || index > start.length - 2) {
+            throw new 
MathIllegalArgumentException(LocalizedFormats.ARGUMENT_OUTSIDE_DOMAIN,
+                                                   index, 0, start.length - 2);
+        }
     }
 
 }

http://git-wip-us.apache.org/repos/asf/commons-math/blob/136f644e/src/main/java/org/apache/commons/math3/ode/FieldExpandableODE.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/math3/ode/FieldExpandableODE.java 
b/src/main/java/org/apache/commons/math3/ode/FieldExpandableODE.java
index 289d2e6..341b1c7 100644
--- a/src/main/java/org/apache/commons/math3/ode/FieldExpandableODE.java
+++ b/src/main/java/org/apache/commons/math3/ode/FieldExpandableODE.java
@@ -16,7 +16,6 @@
  */
 package org.apache.commons.math3.ode;
 
-import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -52,26 +51,22 @@ import org.apache.commons.math3.util.MathArrays;
 
 public class FieldExpandableODE<T extends RealFieldElement<T>> {
 
-    /** Total dimension. */
-    private int dimension;
-
     /** Primary differential equation. */
     private final FieldFirstOrderDifferentialEquations<T> primary;
 
-    /** Mapper for primary equation. */
-    private final FieldEquationsMapper<T> primaryMapper;
-
     /** Components of the expandable ODE. */
-    private List<FieldSecondaryComponent<T>> components;
+    private List<FieldSecondaryEquations<T>> components;
+
+    /** Mapper for all equations. */
+    private FieldEquationsMapper<T> mapper;
 
     /** Build an expandable set from its primary ODE set.
      * @param primary the primary set of differential equations to be 
integrated.
      */
     public FieldExpandableODE(final FieldFirstOrderDifferentialEquations<T> 
primary) {
-        this.dimension     = primary.getDimension();
-        this.primary       = primary;
-        this.primaryMapper = new FieldEquationsMapper<T>(0, 
primary.getDimension());
-        this.components    = new 
ArrayList<FieldExpandableODE.FieldSecondaryComponent<T>>();
+        this.primary    = primary;
+        this.components = new ArrayList<FieldSecondaryEquations<T>>();
+        this.mapper     = new FieldEquationsMapper<T>(null, 
primary.getDimension());
     }
 
     /** Get the primary set of differential equations.
@@ -81,14 +76,11 @@ public class FieldExpandableODE<T extends 
RealFieldElement<T>> {
         return primary;
     }
 
-    /** Return the dimension of the complete set of equations.
-     * <p>
-     * The complete set of equations correspond to the primary set plus all 
secondary sets.
-     * </p>
-     * @return dimension of the complete set of equations
+    /** Get the mapper for the set of equations.
+     * @return mapper for the set of equations
      */
-    public int getTotalDimension() {
-        return dimension;
+    FieldEquationsMapper<T> getMapper() {
+        return mapper;
     }
 
     /** Add a set of secondary equations to be integrated along with the 
primary set.
@@ -99,95 +91,13 @@ public class FieldExpandableODE<T extends 
RealFieldElement<T>> {
      */
     public int addSecondaryEquations(final FieldSecondaryEquations<T> 
secondary) {
 
-        final int firstIndex;
-        if (components.isEmpty()) {
-            // lazy creation of the components list
-            components = new 
ArrayList<FieldExpandableODE.FieldSecondaryComponent<T>>();
-            firstIndex = primary.getDimension();
-        } else {
-            final FieldSecondaryComponent<T> last = 
components.get(components.size() - 1);
-            firstIndex = last.mapper.getFirstIndex() + 
last.mapper.getDimension();
-        }
-
-        final FieldSecondaryComponent<T> component = new 
FieldSecondaryComponent<T>(secondary, firstIndex);
-        components.add(component);
-
-        // update total dimension
-        dimension = component.mapper.getFirstIndex() + 
component.mapper.getDimension();
+        components.add(secondary);
+        mapper = new FieldEquationsMapper<>(mapper, secondary.getDimension());
 
         return components.size() - 1;
 
     }
 
-    /** Map a state to a complete flat array.
-     * @param state state to map
-     * @return flat array containing the mapped state, including primary and 
secondary components
-     */
-    public T[] mapState(final FieldODEState<T> state) {
-        final T[] y = MathArrays.buildArray(state.getTime().getField(), 
getTotalDimension());
-        primaryMapper.insertEquationData(state.getState(), y);
-        for (int i = 0; i < components.size(); ++i) {
-            
components.get(i).mapper.insertEquationData(state.getSecondaryState(i), y);
-        }
-        return y;
-    }
-
-    /** Map a state derivative to a complete flat array.
-     * @param state state to map
-     * @return flat array containing the mapped state derivative, including 
primary and secondary components
-     */
-    public T[] mapDerivative(final FieldODEStateAndDerivative<T> state) {
-        final T[] yDot = MathArrays.buildArray(state.getTime().getField(), 
getTotalDimension());
-        primaryMapper.insertEquationData(state.getDerivative(), yDot);
-        for (int i = 0; i < components.size(); ++i) {
-            
components.get(i).mapper.insertEquationData(state.getSecondaryDerivative(i), 
yDot);
-        }
-        return yDot;
-    }
-
-    /** Map a flat array to a state.
-     * @param t time
-     * @param y array to map, including primary and secondary components
-     * @return mapped state
-     */
-    public FieldODEState<T> mapState(final T t, final T[] y) {
-        final T[] state = primaryMapper.extractEquationData(y);
-        if (components.isEmpty()) {
-            return new FieldODEState<T>(t, state);
-        } else {
-            @SuppressWarnings("unchecked")
-            final T[][] secondaryState = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), components.size());
-            for (int i = 0; i < components.size(); ++i) {
-                secondaryState[i] = 
components.get(i).mapper.extractEquationData(y);
-            }
-            return new FieldODEState<T>(t, state, secondaryState);
-        }
-    }
-
-    /** Map flat arrays to a state and derivative.
-     * @param t time
-     * @param y state array to map, including primary and secondary components
-     * @param yDot state derivative array to map, including primary and 
secondary components
-     * @return mapped state
-     */
-    public FieldODEStateAndDerivative<T> mapStateAndDerivative(final T t, 
final T[] y, final T[] yDot) {
-        final T[] state      = primaryMapper.extractEquationData(y);
-        final T[] derivative = primaryMapper.extractEquationData(yDot);
-        if (components.isEmpty()) {
-            return new FieldODEStateAndDerivative<T>(t, state, derivative);
-        } else {
-            @SuppressWarnings("unchecked")
-            final T[][] secondaryState      = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), components.size());
-            @SuppressWarnings("unchecked")
-            final T[][] secondaryDerivative = (T[][]) 
Array.newInstance(t.getField().getRuntimeClass(), components.size());
-            for (int i = 0; i < components.size(); ++i) {
-                secondaryState[i]      = 
components.get(i).mapper.extractEquationData(y);
-                secondaryDerivative[i] = 
components.get(i).mapper.extractEquationData(yDot);
-            }
-            return new FieldODEStateAndDerivative<T>(t, state, derivative, 
secondaryState, secondaryDerivative);
-        }
-    }
-
     /** Get the current time derivative of the complete state vector.
      * @param t current value of the independent <I>time</I> variable
      * @param y array containing the current value of the complete state vector
@@ -198,44 +108,24 @@ public class FieldExpandableODE<T extends 
RealFieldElement<T>> {
     public T[] computeDerivatives(final T t, final T[] y)
         throws MaxCountExceededException, DimensionMismatchException {
 
-        final T[] yDot = MathArrays.buildArray(t.getField(), 
getTotalDimension());
+        final T[] yDot = MathArrays.buildArray(t.getField(), 
mapper.getTotalDimension());
 
         // compute derivatives of the primary equations
-        final T[] primaryState    = primaryMapper.extractEquationData(y);
+        int index = 0;
+        final T[] primaryState    = mapper.extractEquationData(index, y);
         final T[] primaryStateDot = primary.computeDerivatives(t, 
primaryState);
-        primaryMapper.insertEquationData(primaryStateDot, yDot);
+        mapper.insertEquationData(index, primaryStateDot, yDot);
 
         // Add contribution for secondary equations
-        for (final FieldSecondaryComponent<T> component : components) {
-            final T[] componentState    = 
component.mapper.extractEquationData(y);
-            final T[] componentStateDot = 
component.equation.computeDerivatives(t, primaryState, primaryStateDot, 
componentState);
-            component.mapper.insertEquationData(componentStateDot, yDot);
+        while (++index < mapper.getNumberOfEquations()) {
+            final T[] componentState    = mapper.extractEquationData(index, y);
+            final T[] componentStateDot = components.get(index - 
1).computeDerivatives(t, primaryState, primaryStateDot,
+                                                                               
        componentState);
+            mapper.insertEquationData(index, componentStateDot, yDot);
         }
 
         return yDot;
 
     }
 
-    /** Components of the compound ODE.
-     * @param <S> the type of the field elements
-     */
-    private static class FieldSecondaryComponent<S extends 
RealFieldElement<S>> {
-
-        /** Secondary differential equation. */
-        private final FieldSecondaryEquations<S> equation;
-
-        /** Mapper between local and complete arrays. */
-        private final FieldEquationsMapper<S> mapper;
-
-        /** Simple constructor.
-         * @param equation secondary differential equation
-         * @param firstIndex index to use for the first element in the 
complete arrays
-         */
-        FieldSecondaryComponent(final FieldSecondaryEquations<S> equation, 
final int firstIndex) {
-            this.equation = equation;
-            this.mapper   = new FieldEquationsMapper<S>(firstIndex, 
equation.getDimension());
-        }
-
-    }
-
 }

Reply via email to