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, 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, 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 }