View Javadoc
1   /*
2    * Licensed to the Hipparchus project 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 Hipparchus project 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  package org.hipparchus.ode;
19  
20  import java.io.Serializable;
21  
22  import org.hipparchus.exception.LocalizedCoreFormats;
23  import org.hipparchus.exception.MathIllegalArgumentException;
24  
25  /**
26   * Class mapping the part of a complete state or derivative that pertains
27   * to a specific differential equation.
28   * <p>
29   * Instances of this class are guaranteed to be immutable.
30   * </p>
31   * @see SecondaryODE
32   */
33  public class EquationsMapper implements Serializable {
34  
35      /** Serializable UID. */
36      private static final long serialVersionUID = 20160327L;
37  
38      /** Start indices of the components. */
39      private final int[] start;
40  
41      /** Create a mapper by adding a new equation to another mapper.
42       * <p>
43       * The new equation will have index {@code mapper.}{@link #getNumberOfEquations()},
44       * or 0 if {@code mapper} is null.
45       * </p>
46       * @param mapper former mapper, with one equation less (null for first equation)
47       * @param dimension dimension of the equation state vector
48       */
49      EquationsMapper(final EquationsMapper mapper, final int dimension) {
50          final int index = (mapper == null) ? 0 : mapper.getNumberOfEquations();
51          this.start = new int[index + 2];
52          if (mapper == null) {
53              start[0] = 0;
54          } else {
55              System.arraycopy(mapper.start, 0, start, 0, index + 1);
56          }
57          start[index + 1] = start[index] + dimension;
58      }
59  
60      /** Get the number of equations mapped.
61       * @return number of equations mapped
62       */
63      public int getNumberOfEquations() {
64          return start.length - 1;
65      }
66  
67      /** Return the dimension of the complete set of equations.
68       * <p>
69       * The complete set of equations correspond to the primary set plus all secondary sets.
70       * </p>
71       * @return dimension of the complete set of equations
72       */
73      public int getTotalDimension() {
74          return start[start.length - 1];
75      }
76  
77      /** Map flat arrays to a state and derivative.
78       * @param t time
79       * @param y state array to map, including primary and secondary components
80       * @param yDot state derivative array to map, including primary and secondary components
81       * @return mapped state
82       * @exception MathIllegalArgumentException if an array does not match total dimension
83       */
84      public ODEStateAndDerivative mapStateAndDerivative(final double t, final double[] y, final double[] yDot)
85          throws MathIllegalArgumentException {
86  
87          if (y.length != getTotalDimension()) {
88              throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
89                                                     y.length, getTotalDimension());
90          }
91  
92          if (yDot.length != getTotalDimension()) {
93              throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
94                                                     yDot.length, getTotalDimension());
95          }
96  
97          final int n = getNumberOfEquations();
98          final double[] state      = extractEquationData(0, y);
99          final double[] derivative = extractEquationData(0, yDot);
100         if (n < 2) {
101             return new ODEStateAndDerivative(t, state, derivative);
102         } else {
103             final double[][] secondaryState      = new double[n - 1][];
104             final double[][] secondaryDerivative = new double[n - 1][];
105             for (int index = 1; index < getNumberOfEquations(); ++index) {
106                 secondaryState[index - 1]      = extractEquationData(index, y);
107                 secondaryDerivative[index - 1] = extractEquationData(index, yDot);
108             }
109             return new ODEStateAndDerivative(t, state, derivative, secondaryState, secondaryDerivative);
110         }
111     }
112 
113     /** Extract equation data from a complete state or derivative array.
114      * @param index index of the equation, must be between 0 included and
115      * {@link #getNumberOfEquations()} (excluded)
116      * @param complete complete state or derivative array from which
117      * equation data should be retrieved
118      * @return equation data
119      * @exception MathIllegalArgumentException if index is out of range
120      * @exception MathIllegalArgumentException if complete state has not enough elements
121      */
122     public double[] extractEquationData(final int index, final double[] complete)
123         throws MathIllegalArgumentException {
124         checkIndex(index);
125         final int begin     = start[index];
126         final int end       = start[index + 1];
127         if (complete.length < end) {
128             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
129                                                    complete.length, end);
130         }
131         final int dimension = end - begin;
132         final double[] equationData = new double[dimension];
133         System.arraycopy(complete, begin, equationData, 0, dimension);
134         return equationData;
135     }
136 
137     /** Insert equation data into a complete state or derivative array.
138      * @param index index of the equation, must be between 0 included and
139      * {@link #getNumberOfEquations()} (excluded)
140      * @param equationData equation data to be inserted into the complete array
141      * @param complete placeholder where to put equation data (only the
142      * part corresponding to the equation will be overwritten)
143      * @exception MathIllegalArgumentException if either array has not enough elements
144      */
145     public void insertEquationData(final int index, double[] equationData, double[] complete)
146         throws MathIllegalArgumentException {
147         checkIndex(index);
148         final int begin     = start[index];
149         final int end       = start[index + 1];
150         final int dimension = end - begin;
151         if (complete.length < end) {
152             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
153                                                    complete.length, end);
154         }
155         if (equationData.length != dimension) {
156             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
157                                                    equationData.length, dimension);
158         }
159         System.arraycopy(equationData, 0, complete, begin, dimension);
160     }
161 
162     /** Check equation index.
163      * @param index index of the equation, must be between 0 included and
164      * {@link #getNumberOfEquations()} (excluded)
165      * @exception MathIllegalArgumentException if index is out of range
166      */
167     private void checkIndex(final int index) throws MathIllegalArgumentException {
168         if (index < 0 || index > start.length - 2) {
169             throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE,
170                                                    index, 0, start.length - 2);
171         }
172     }
173 
174 }