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 }