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.nonstiff;
19  
20  import org.hipparchus.Field;
21  import org.hipparchus.complex.Complex;
22  import org.hipparchus.complex.ComplexField;
23  import org.hipparchus.ode.ExpandableODE;
24  import org.hipparchus.ode.FieldExpandableODE;
25  import org.hipparchus.ode.FieldOrdinaryDifferentialEquation;
26  import org.hipparchus.ode.OrdinaryDifferentialEquation;
27  import org.hipparchus.util.FastMath;
28  import org.hipparchus.util.FieldSinCos;
29  import org.hipparchus.util.MathArrays;
30  import org.hipparchus.util.SinCos;
31  import org.junit.jupiter.api.Test;
32  
33  import static org.junit.jupiter.api.Assertions.assertEquals;
34  
35  class FieldExplicitRungeKuttaIntegratorTest {
36  
37      @Test
38      void testFraction() {
39          // GIVEN
40          final int p = 2;
41          final int q = 3;
42          final Field<Complex> field = ComplexField.getInstance();
43          // WHEN
44          final Complex actualFraction = FieldExplicitRungeKuttaIntegrator.fraction(field, p, q);
45          // THEN
46          final Complex expectedFraction = FieldExplicitRungeKuttaIntegrator.fraction(field, (double) p, (double) q);
47          assertEquals(expectedFraction.getReal(), actualFraction.getReal(), 0);
48      }
49  
50      @Test
51      void testVersusNonField() {
52          // GIVEN
53          final TestFieldEquations testFieldEquations = new TestFieldEquations();
54          final FieldExpandableODE<Complex> fieldExpandableODE = new FieldExpandableODE<>(testFieldEquations);
55  
56          final ComplexField field = ComplexField.getInstance();
57          final Complex t0 = Complex.ZERO;
58          final Complex[] y0 = new Complex[] { Complex.ONE, Complex.ZERO };
59          final Complex h = new Complex(0.1);
60          final FieldButcherArrayProvider<Complex> fieldExplicitRungeKutta = new ThreeEighthesFieldIntegrator<>(field,
61                  Complex.NaN);
62  
63          // WHEN
64          final Complex[][] yDotK = MathArrays.buildArray(field, 4, 2);
65          yDotK[0] = fieldExpandableODE.computeDerivatives(t0, y0);
66          FieldExplicitRungeKuttaIntegrator.applyInternalButcherWeights(fieldExpandableODE, t0, y0, h,
67                  fieldExplicitRungeKutta.getA(), fieldExplicitRungeKutta.getC(), yDotK);
68          final Complex[] actualState = FieldExplicitRungeKuttaIntegrator.applyExternalButcherWeights(y0, yDotK, h,
69                  fieldExplicitRungeKutta.getB());
70  
71          // THEN
72          final double[] y0Real = new double[] { y0[0].getReal(), y0[1].getReal() };
73          final double[][] yDotKReal = new double[yDotK.length][yDotK[0].length];
74          final ExpandableODE expandableODE = new ExpandableODE(new TestEquations());
75          yDotKReal[0] = expandableODE.computeDerivatives(t0.getReal(), y0Real);
76          final ButcherArrayProvider explicitRungeKutta = new ThreeEighthesIntegrator(Double.NaN);
77          ExplicitRungeKuttaIntegrator.applyInternalButcherWeights(expandableODE, t0.getReal(), y0Real, h.getReal(),
78                  explicitRungeKutta.getA(), explicitRungeKutta.getC(), yDotKReal);
79          final double[] expectedState = ExplicitRungeKuttaIntegrator.applyExternalButcherWeights(y0Real, yDotKReal, h.getReal(),
80                  explicitRungeKutta.getB());
81          for (int i = 0; i < expectedState.length; i++) {
82              assertEquals(expectedState[i], actualState[i].getReal(), 0);
83          }
84      }
85  
86      @Test
87      void testRealCoefficientsVersusField() {
88          // GIVEN
89          final TestFieldEquations testFieldEquations = new TestFieldEquations();
90          final FieldExpandableODE<Complex> fieldExpandableODE = new FieldExpandableODE<>(testFieldEquations);
91          final ComplexField field = ComplexField.getInstance();
92          final Complex t0 = Complex.ZERO;
93          final Complex[] y0 = new Complex[] { Complex.ONE, Complex.ZERO };
94          final Complex h = new Complex(0.1);
95          final FieldExplicitRungeKuttaIntegrator<Complex> fieldExplicitRungeKutta = new ThreeEighthesFieldIntegrator<>(field,
96                  Complex.NaN);
97  
98          // WHEN
99          final Complex[][] yDotK = MathArrays.buildArray(field, 4, 2);
100         yDotK[0] = fieldExpandableODE.computeDerivatives(t0, y0);
101         FieldExplicitRungeKuttaIntegrator.applyInternalButcherWeights(fieldExpandableODE, t0, y0, h,
102                 fieldExplicitRungeKutta.getA(), fieldExplicitRungeKutta.getC(), yDotK);
103         final Complex[] actualState = FieldExplicitRungeKuttaIntegrator.applyExternalButcherWeights(y0, yDotK, h,
104                 fieldExplicitRungeKutta.getB());
105 
106         // THEN
107         FieldExplicitRungeKuttaIntegrator.applyInternalButcherWeights(fieldExpandableODE, t0, y0, h,
108                 fieldExplicitRungeKutta.getRealA(), fieldExplicitRungeKutta.getRealC(), yDotK);
109         final Complex[] expectedState = FieldExplicitRungeKuttaIntegrator.applyExternalButcherWeights(y0, yDotK, h,
110                 fieldExplicitRungeKutta.getRealB());
111         for (int i = 0; i < expectedState.length; i++) {
112             assertEquals(expectedState[i], actualState[i]);
113         }
114     }
115 
116     private static class TestFieldEquations implements FieldOrdinaryDifferentialEquation<Complex> {
117 
118         @Override
119         public int getDimension() {
120             return 2;
121         }
122 
123         @Override
124         public Complex[] computeDerivatives(Complex t, Complex[] y) {
125 
126             final FieldSinCos<Complex> sinCos = FastMath.sinCos(t);
127             return new Complex[] { sinCos.sin(), sinCos.cos().multiply(y[0]) };
128         }
129 
130     }
131 
132     private static class TestEquations implements OrdinaryDifferentialEquation {
133 
134         @Override
135         public int getDimension() {
136             return 2;
137         }
138 
139         @Override
140         public double[] computeDerivatives(double t, double[] y) {
141             final SinCos sinCos = FastMath.sinCos(t);
142             return new double[] { sinCos.sin(), sinCos.cos() * y[0] };
143         }
144     } 
145     
146 }