1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.ode;
24
25 import org.hipparchus.CalculusFieldElement;
26 import org.hipparchus.Field;
27 import org.hipparchus.exception.MathIllegalArgumentException;
28 import org.hipparchus.util.Binary64Field;
29 import org.hipparchus.util.MathArrays;
30 import org.junit.jupiter.api.Test;
31
32 import static org.junit.jupiter.api.Assertions.assertEquals;
33 import static org.junit.jupiter.api.Assertions.assertThrows;
34 import static org.junit.jupiter.api.Assertions.fail;
35
36 class FieldExpandableODETest {
37
38 @Test
39 void testOnlyMainEquation() {
40 doTestOnlyMainEquation(Binary64Field.getInstance());
41 }
42
43 private <T extends CalculusFieldElement<T>> void doTestOnlyMainEquation(final Field<T> field) {
44 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
45 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
46 assertEquals(main.getDimension(), equation.getMapper().getTotalDimension());
47 assertEquals(1, equation.getMapper().getNumberOfEquations());
48 T t0 = field.getZero().add(10);
49 T t = field.getZero().add(100);
50 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
51 for (int i = 0; i < complete.length; ++i) {
52 complete[i] = field.getZero().add(i);
53 }
54 T[] completeDot = equation.computeDerivatives(t0, complete);
55 equation.init(equation.getMapper().mapStateAndDerivative(t0, complete, completeDot), t);
56 FieldODEStateAndDerivative<T> state = equation.getMapper().mapStateAndDerivative(t0, complete, completeDot);
57 assertEquals(0, state.getNumberOfSecondaryStates());
58 T[] mainState = state.getPrimaryState();
59 T[] mainStateDot = state.getPrimaryDerivative();
60 assertEquals(main.getDimension(), mainState.length);
61 for (int i = 0; i < main.getDimension(); ++i) {
62 assertEquals(i, mainState[i].getReal(), 1.0e-15);
63 assertEquals(i, mainStateDot[i].getReal(), 1.0e-15);
64 assertEquals(i, completeDot[i].getReal(), 1.0e-15);
65 }
66 }
67
68 @Test
69 void testPrimaryAndSecondary() {
70 doTestPrimaryAndSecondary(Binary64Field.getInstance());
71 }
72
73 private <T extends CalculusFieldElement<T>> void doTestPrimaryAndSecondary(final Field<T> field) {
74
75 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
76 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
77 FieldSecondaryODE<T> secondary1 = new Linear<T>(field, 3, main.getDimension());
78 int i1 = equation.addSecondaryEquations(secondary1);
79 FieldSecondaryODE<T> secondary2 = new Linear<T>(field, 5, main.getDimension() + secondary1.getDimension());
80 int i2 = equation.addSecondaryEquations(secondary2);
81 assertEquals(main.getDimension() + secondary1.getDimension() + secondary2.getDimension(),
82 equation.getMapper().getTotalDimension());
83 assertEquals(3, equation.getMapper().getNumberOfEquations());
84 assertEquals(1, i1);
85 assertEquals(2, i2);
86
87 T t0 = field.getZero().add(10);
88 T t = field.getZero().add(100);
89 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
90 for (int i = 0; i < complete.length; ++i) {
91 complete[i] = field.getZero().add(i);
92 }
93 T[] completeDot = equation.computeDerivatives(t0, complete);
94 equation.init(equation.getMapper().mapStateAndDerivative(t0, complete, completeDot), t);
95
96 T[] mainState = equation.getMapper().extractEquationData(0, complete);
97 T[] mainStateDot = equation.getMapper().extractEquationData(0, completeDot);
98 assertEquals(main.getDimension(), mainState.length);
99 for (int i = 0; i < main.getDimension(); ++i) {
100 assertEquals(i, mainState[i].getReal(), 1.0e-15);
101 assertEquals(i, mainStateDot[i].getReal(), 1.0e-15);
102 assertEquals(i, completeDot[i].getReal(), 1.0e-15);
103 }
104
105 T[] secondaryState1 = equation.getMapper().extractEquationData(i1, complete);
106 T[] secondaryState1Dot = equation.getMapper().extractEquationData(i1, completeDot);
107 assertEquals(secondary1.getDimension(), secondaryState1.length);
108 for (int i = 0; i < secondary1.getDimension(); ++i) {
109 assertEquals(i + main.getDimension(), secondaryState1[i].getReal(), 1.0e-15);
110 assertEquals(-i, secondaryState1Dot[i].getReal(), 1.0e-15);
111 assertEquals(-i, completeDot[i + main.getDimension()].getReal(), 1.0e-15);
112 }
113
114 T[] secondaryState2 = equation.getMapper().extractEquationData(i2, complete);
115 T[] secondaryState2Dot = equation.getMapper().extractEquationData(i2, completeDot);
116 assertEquals(secondary2.getDimension(), secondaryState2.length);
117 for (int i = 0; i < secondary2.getDimension(); ++i) {
118 assertEquals(i + main.getDimension() + secondary1.getDimension(), secondaryState2[i].getReal(), 1.0e-15);
119 assertEquals(-i, secondaryState2Dot[i].getReal(), 1.0e-15);
120 assertEquals(-i, completeDot[i + main.getDimension() + secondary1.getDimension()].getReal(), 1.0e-15);
121 }
122
123 }
124
125 @Test
126 void testMap() {
127 doTestMap(Binary64Field.getInstance());
128 }
129
130 private <T extends CalculusFieldElement<T>> void doTestMap(final Field<T> field) {
131
132 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
133 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
134 FieldSecondaryODE<T> secondary1 = new Linear<T>(field, 3, main.getDimension());
135 int i1 = equation.addSecondaryEquations(secondary1);
136 FieldSecondaryODE<T> secondary2 = new Linear<T>(field, 5, main.getDimension() + secondary1.getDimension());
137 int i2 = equation.addSecondaryEquations(secondary2);
138 assertEquals(main.getDimension() + secondary1.getDimension() + secondary2.getDimension(),
139 equation.getMapper().getTotalDimension());
140 assertEquals(3, equation.getMapper().getNumberOfEquations());
141 assertEquals(1, i1);
142 assertEquals(2, i2);
143
144 T t0 = field.getZero().add(10);
145 T t = field.getZero().add(100);
146 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
147 for (int i = 0; i < complete.length; ++i) {
148 complete[i] = field.getZero().add(i);
149 }
150 T[] completeDot = equation.computeDerivatives(t0, complete);
151 equation.init(equation.getMapper().mapStateAndDerivative(t0, complete, completeDot), t);
152
153 try {
154 equation.getMapper().mapStateAndDerivative(t0, MathArrays.buildArray(field, complete.length + 1), completeDot);
155 fail("an exception should have been thrown");
156 } catch (MathIllegalArgumentException dme) {
157
158 }
159 try {
160 equation.getMapper().mapStateAndDerivative(t0, complete, MathArrays.buildArray(field, completeDot.length + 1));
161 fail("an exception should have been thrown");
162 } catch (MathIllegalArgumentException dme) {
163
164 }
165 FieldODEStateAndDerivative<T> state = equation.getMapper().mapStateAndDerivative(t0, complete, completeDot);
166 assertEquals(2, state.getNumberOfSecondaryStates());
167 assertEquals(main.getDimension(), state.getSecondaryStateDimension(0));
168 assertEquals(secondary1.getDimension(), state.getSecondaryStateDimension(i1));
169 assertEquals(secondary2.getDimension(), state.getSecondaryStateDimension(i2));
170
171 T[] mainState = state.getPrimaryState();
172 T[] mainStateDot = state.getPrimaryDerivative();
173 T[] mainStateAlternate = state.getSecondaryState(0);
174 T[] mainStateDotAlternate = state.getSecondaryDerivative(0);
175 assertEquals(main.getDimension(), mainState.length);
176 for (int i = 0; i < main.getDimension(); ++i) {
177 assertEquals(i, mainState[i].getReal(), 1.0e-15);
178 assertEquals(i, mainStateDot[i].getReal(), 1.0e-15);
179 assertEquals(i, mainStateAlternate[i].getReal(), 1.0e-15);
180 assertEquals(i, mainStateDotAlternate[i].getReal(), 1.0e-15);
181 assertEquals(i, completeDot[i].getReal(), 1.0e-15);
182 }
183
184 T[] secondaryState1 = state.getSecondaryState(i1);
185 T[] secondaryState1Dot = state.getSecondaryDerivative(i1);
186 assertEquals(secondary1.getDimension(), secondaryState1.length);
187 for (int i = 0; i < secondary1.getDimension(); ++i) {
188 assertEquals(i + main.getDimension(), secondaryState1[i].getReal(), 1.0e-15);
189 assertEquals(-i, secondaryState1Dot[i].getReal(), 1.0e-15);
190 assertEquals(-i, completeDot[i + main.getDimension()].getReal(), 1.0e-15);
191 }
192
193 T[] secondaryState2 = state.getSecondaryState(i2);
194 T[] secondaryState2Dot = state.getSecondaryDerivative(i2);
195 assertEquals(secondary2.getDimension(), secondaryState2.length);
196 for (int i = 0; i < secondary2.getDimension(); ++i) {
197 assertEquals(i + main.getDimension() + secondary1.getDimension(), secondaryState2[i].getReal(), 1.0e-15);
198 assertEquals(-i, secondaryState2Dot[i].getReal(), 1.0e-15);
199 assertEquals(-i, completeDot[i + main.getDimension() + secondary1.getDimension()].getReal(), 1.0e-15);
200 }
201
202 T[] remappedState = state.getCompleteState();
203 T[] remappedDerivative = state.getCompleteDerivative();
204 assertEquals(equation.getMapper().getTotalDimension(), remappedState.length);
205 assertEquals(equation.getMapper().getTotalDimension(), remappedDerivative.length);
206 for (int i = 0; i < remappedState.length; ++i) {
207 assertEquals(complete[i].getReal(), remappedState[i].getReal(), 1.0e-15);
208 assertEquals(completeDot[i].getReal(), remappedDerivative[i].getReal(), 1.0e-15);
209 }
210 }
211
212 @Test
213 void testExtractDimensionMismatch() {
214 assertThrows(MathIllegalArgumentException.class, () -> {
215 doTestExtractDimensionMismatch(Binary64Field.getInstance());
216 });
217 }
218
219 private <T extends CalculusFieldElement<T>> void doTestExtractDimensionMismatch(final Field<T> field)
220 throws MathIllegalArgumentException {
221
222 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
223 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
224 FieldSecondaryODE<T> secondary1 = new Linear<T>(field, 3, main.getDimension());
225 int i1 = equation.addSecondaryEquations(secondary1);
226 T[] tooShort = MathArrays.buildArray(field, main.getDimension());
227 equation.getMapper().extractEquationData(i1, tooShort);
228 }
229
230 @Test
231 void testInsertTooShortComplete() {
232 assertThrows(MathIllegalArgumentException.class, () -> {
233 doTestInsertTooShortComplete(Binary64Field.getInstance());
234 });
235 }
236
237 private <T extends CalculusFieldElement<T>> void doTestInsertTooShortComplete(final Field<T> field)
238 throws MathIllegalArgumentException {
239
240 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
241 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
242 FieldSecondaryODE<T> secondary1 = new Linear<T>(field, 3, main.getDimension());
243 int i1 = equation.addSecondaryEquations(secondary1);
244 T[] equationData = MathArrays.buildArray(field, secondary1.getDimension());
245 T[] tooShort = MathArrays.buildArray(field, main.getDimension());
246 equation.getMapper().insertEquationData(i1, equationData, tooShort);
247 }
248
249 @Test
250 void testInsertWrongEquationData() {
251 assertThrows(MathIllegalArgumentException.class, () -> {
252 doTestInsertWrongEquationData(Binary64Field.getInstance());
253 });
254 }
255
256 private <T extends CalculusFieldElement<T>> void doTestInsertWrongEquationData(final Field<T> field)
257 throws MathIllegalArgumentException {
258
259 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
260 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
261 FieldSecondaryODE<T> secondary1 = new Linear<T>(field, 3, main.getDimension());
262 int i1 = equation.addSecondaryEquations(secondary1);
263 T[] wrongEquationData = MathArrays.buildArray(field, secondary1.getDimension() + 1);
264 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
265 equation.getMapper().insertEquationData(i1, wrongEquationData, complete);
266 }
267
268 @Test
269 void testNegativeIndex() {
270 assertThrows(MathIllegalArgumentException.class, () -> {
271 doTestNegativeIndex(Binary64Field.getInstance());
272 });
273 }
274
275 private <T extends CalculusFieldElement<T>> void doTestNegativeIndex(final Field<T> field)
276 throws MathIllegalArgumentException {
277
278 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
279 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
280 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
281 equation.getMapper().extractEquationData(-1, complete);
282 }
283
284 @Test
285 void testTooLargeIndex() {
286 assertThrows(MathIllegalArgumentException.class, () -> {
287 doTestTooLargeIndex(Binary64Field.getInstance());
288 });
289 }
290
291 private <T extends CalculusFieldElement<T>> void doTestTooLargeIndex(final Field<T> field)
292 throws MathIllegalArgumentException {
293
294 FieldOrdinaryDifferentialEquation<T> main = new Linear<T>(field, 3, 0);
295 FieldExpandableODE<T> equation = new FieldExpandableODE<T>(main);
296 T[] complete = MathArrays.buildArray(field, equation.getMapper().getTotalDimension());
297 equation.getMapper().extractEquationData(+1, complete);
298 }
299
300 private static class Linear<T extends CalculusFieldElement<T>>
301 implements FieldOrdinaryDifferentialEquation<T>, FieldSecondaryODE<T> {
302
303 private final Field<T> field;
304 private final int dimension;
305 private final int start;
306
307 private Linear(final Field<T> field, final int dimension, final int start) {
308 this.field = field;
309 this.dimension = dimension;
310 this.start = start;
311 }
312
313 public int getDimension() {
314 return dimension;
315 }
316
317 public void init(final T t0, final T[] y0, final T finalTime) {
318 assertEquals(dimension, y0.length);
319 assertEquals(10.0, t0.getReal(), 1.0e-15);
320 assertEquals(100.0, finalTime.getReal(), 1.0e-15);
321 for (int i = 0; i < y0.length; ++i) {
322 assertEquals(i, y0[i].getReal(), 1.0e-15);
323 }
324 }
325
326 public T[] computeDerivatives(final T t, final T[] y) {
327 final T[] yDot = MathArrays.buildArray(field, dimension);
328 for (int i = 0; i < dimension; ++i) {
329 yDot[i] = field.getZero().add(i);
330 }
331 return yDot;
332 }
333
334 public void init(final T t0, final T[] primary0, final T[] secondary0, final T finalTime) {
335 assertEquals(dimension, secondary0.length);
336 assertEquals(10.0, t0.getReal(), 1.0e-15);
337 assertEquals(100.0, finalTime.getReal(), 1.0e-15);
338 for (int i = 0; i < primary0.length; ++i) {
339 assertEquals(i, primary0[i].getReal(), 1.0e-15);
340 }
341 for (int i = 0; i < secondary0.length; ++i) {
342 assertEquals(start + i, secondary0[i].getReal(), 1.0e-15);
343 }
344 }
345
346 public T[] computeDerivatives(final T t, final T[] primary, final T[] primaryDot, final T[] secondary) {
347 final T[] secondaryDot = MathArrays.buildArray(field, dimension);
348 for (int i = 0; i < dimension; ++i) {
349 secondaryDot[i] = field.getZero().subtract(i);
350 }
351 return secondaryDot;
352 }
353
354 }
355
356 }