View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.ode;
24  
25  import java.io.Serializable;
26  
27  import org.hipparchus.CalculusFieldElement;
28  import org.hipparchus.exception.LocalizedCoreFormats;
29  import org.hipparchus.exception.MathIllegalArgumentException;
30  import org.hipparchus.util.MathArrays;
31  import org.hipparchus.util.MathUtils;
32  
33  /**
34   * Class mapping the part of a complete state or derivative that pertains
35   * to a set of differential equations.
36   * <p>
37   * Instances of this class are guaranteed to be immutable.
38   * </p>
39   * @see FieldExpandableODE
40   * @param <T> the type of the field elements
41   */
42  public class FieldEquationsMapper<T extends CalculusFieldElement<T>> implements Serializable {
43  
44      /** Serializable UID. */
45      private static final long serialVersionUID = 20151114L;
46  
47      /** Start indices of the components. */
48      private final int[] start;
49  
50      /** Create a mapper by adding a new equation to another mapper.
51       * <p>
52       * The new equation will have index {@code mapper.}{@link #getNumberOfEquations()},
53       * or 0 if {@code mapper} is null.
54       * </p>
55       * @param mapper former mapper, with one equation less (null for first equation)
56       * @param dimension dimension of the equation state vector
57       */
58      FieldEquationsMapper(final FieldEquationsMapper<T> mapper, final int dimension) {
59          final int index = (mapper == null) ? 0 : mapper.getNumberOfEquations();
60          this.start = new int[index + 2];
61          if (mapper == null) {
62              start[0] = 0;
63          } else {
64              System.arraycopy(mapper.start, 0, start, 0, index + 1);
65          }
66          start[index + 1] = start[index] + dimension;
67      }
68  
69      /** Get the number of equations mapped.
70       * @return number of equations mapped
71       */
72      public int getNumberOfEquations() {
73          return start.length - 1;
74      }
75  
76      /** Return the dimension of the complete set of equations.
77       * <p>
78       * The complete set of equations correspond to the primary set plus all secondary sets.
79       * </p>
80       * @return dimension of the complete set of equations
81       */
82      public int getTotalDimension() {
83          return start[start.length - 1];
84      }
85  
86      /** Map flat arrays to a state and derivative.
87       * @param t time
88       * @param y state array to map, including primary and secondary components
89       * @param yDot state derivative array to map, including primary and secondary components
90       * @return mapped state
91       * @exception MathIllegalArgumentException if an array does not match total dimension
92       */
93      public FieldODEStateAndDerivative<T> mapStateAndDerivative(final T t, final T[] y, final T[] yDot)
94          throws MathIllegalArgumentException {
95  
96          if (y.length != getTotalDimension()) {
97              throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
98                                                     y.length, getTotalDimension());
99          }
100 
101         if (yDot.length != getTotalDimension()) {
102             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
103                                                    yDot.length, getTotalDimension());
104         }
105 
106         final int n = getNumberOfEquations();
107         final T[] state      = extractEquationData(0, y);
108         final T[] derivative = extractEquationData(0, yDot);
109         if (n < 2) {
110             return new FieldODEStateAndDerivative<T>(t, state, derivative);
111         } else {
112             final T[][] secondaryState      = MathArrays.buildArray(t.getField(), n - 1, -1);
113             final T[][] secondaryDerivative = MathArrays.buildArray(t.getField(), n - 1, -1);
114             for (int index = 1; index < getNumberOfEquations(); ++index) {
115                 secondaryState[index - 1]      = extractEquationData(index, y);
116                 secondaryDerivative[index - 1] = extractEquationData(index, yDot);
117             }
118             return new FieldODEStateAndDerivative<T>(t, state, derivative, secondaryState, secondaryDerivative);
119         }
120     }
121 
122     /** Extract equation data from a complete state or derivative array.
123      * @param index index of the equation, must be between 0 included and
124      * {@link #getNumberOfEquations()} (excluded)
125      * @param complete complete state or derivative array from which
126      * equation data should be retrieved
127      * @return equation data
128      * @exception MathIllegalArgumentException if index is out of range
129      * @exception MathIllegalArgumentException if complete state has not enough elements
130      */
131     public T[] extractEquationData(final int index, final T[] complete)
132         throws MathIllegalArgumentException {
133         checkIndex(index);
134         final int begin     = start[index];
135         final int end       = start[index + 1];
136         if (complete.length < end) {
137             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
138                                                    complete.length, end);
139         }
140         final int dimension = end - begin;
141         final T[] equationData = MathArrays.buildArray(complete[0].getField(), dimension);
142         System.arraycopy(complete, begin, equationData, 0, dimension);
143         return equationData;
144     }
145 
146     /** Insert equation data into a complete state or derivative array.
147      * @param index index of the equation, must be between 0 included and
148      * {@link #getNumberOfEquations()} (excluded)
149      * @param equationData equation data to be inserted into the complete array
150      * @param complete placeholder where to put equation data (only the
151      * part corresponding to the equation will be overwritten)
152      * @exception MathIllegalArgumentException if either array has not enough elements
153      */
154     public void insertEquationData(final int index, T[] equationData, T[] complete)
155         throws MathIllegalArgumentException {
156         checkIndex(index);
157         final int begin     = start[index];
158         final int end       = start[index + 1];
159         final int dimension = end - begin;
160         if (complete.length < end) {
161             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
162                                                    complete.length, end);
163         }
164         if (equationData.length != dimension) {
165             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
166                                                    equationData.length, dimension);
167         }
168         System.arraycopy(equationData, 0, complete, begin, dimension);
169     }
170 
171     /** Check equation index.
172      * @param index index of the equation, must be between 0 included and
173      * {@link #getNumberOfEquations()} (excluded)
174      * @exception MathIllegalArgumentException if index is out of range
175      */
176     private void checkIndex(final int index) throws MathIllegalArgumentException {
177         MathUtils.checkRangeInclusive(index, 0, start.length - 2);
178     }
179 
180 }