1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
40 final int p = 2;
41 final int q = 3;
42 final Field<Complex> field = ComplexField.getInstance();
43
44 final Complex actualFraction = FieldExplicitRungeKuttaIntegrator.fraction(field, p, q);
45
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
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
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
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
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
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
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 }