You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2015/11/14 14:52:34 UTC
[math] Separate equations from mapper.
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 <lu...@apache.org>
Authored: Sat Nov 14 14:52:09 2015 +0100
Committer: Luc Maisonobe <lu...@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());
- }
-
- }
-
}