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 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             // expected
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             // expected
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 }