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 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  package org.hipparchus.ode.sampling;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.ode.FieldExpandableODE;
21  import org.hipparchus.ode.FieldODEIntegrator;
22  import org.hipparchus.ode.FieldODEState;
23  import org.hipparchus.ode.FieldODEStateAndDerivative;
24  import org.hipparchus.ode.FieldOrdinaryDifferentialEquation;
25  import org.hipparchus.ode.TestFieldProblem3;
26  import org.hipparchus.ode.TestFieldProblemAbstract;
27  import org.hipparchus.ode.nonstiff.DormandPrince54FieldIntegrator;
28  import org.hipparchus.util.Binary64;
29  import org.hipparchus.util.Binary64Field;
30  import org.hipparchus.util.FastMath;
31  import org.junit.jupiter.api.Test;
32  
33  import static org.junit.jupiter.api.Assertions.assertEquals;
34  
35  
36  class FieldStepNormalizerTest {
37  
38      @Test
39      void testBoundariesDefault() {
40          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
41          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
42          final Binary64 stepSize = range.divide(5.5);
43          doTestBoundaries(pb, null, stepSize,
44                           pb.getInitialTime(),
45                           pb.getInitialTime().add(FastMath.floor(range.divide(stepSize)).multiply(stepSize)));
46      }
47  
48      @Test
49      void testBoundariesNeither() {
50          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
51          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
52          final Binary64 stepSize = range.divide(5.5);
53          doTestBoundaries(pb, StepNormalizerBounds.NEITHER, stepSize,
54                           pb.getInitialTime().add(stepSize),
55                           pb.getInitialTime().add(FastMath.floor(range.divide(stepSize)).multiply(stepSize)));
56      }
57  
58      @Test
59      void testBoundariesFirst() {
60          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
61          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
62          final Binary64 stepSize = range.divide(5.5);
63          doTestBoundaries(pb, StepNormalizerBounds.FIRST, stepSize,
64                           pb.getInitialTime(),
65                           pb.getInitialTime().add(FastMath.floor(range.divide(stepSize)).multiply(stepSize)));
66      }
67  
68      @Test
69      void testBoundariesLast() {
70          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
71          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
72          final Binary64 stepSize = range.divide(5.5);
73          doTestBoundaries(pb, StepNormalizerBounds.LAST, stepSize,
74                           pb.getInitialTime().add(stepSize),
75                           pb.getFinalTime());
76      }
77  
78      @Test
79      void testBoundariesBoth() {
80          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
81          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
82          final Binary64 stepSize = range.divide(5.5);
83          doTestBoundaries(pb, StepNormalizerBounds.BOTH, stepSize,
84                           pb.getInitialTime(),
85                           pb.getFinalTime());
86      }
87  
88      @Test
89      void testBeforeEnd() {
90          final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
91          final Binary64 range = pb.getFinalTime().subtract(pb.getInitialTime());
92          final Binary64 stepSize = range.divide(10.5);
93          doTestBoundaries(pb, null, stepSize,
94                           pb.getInitialTime(),
95                           pb.getFinalTime().subtract(range.divide(21.0)));
96      }
97  
98      @Test
99      void testModeForwardMultiples() {
100         doTestStepsAtIntegerTimes(StepNormalizerMode.MULTIPLES, 2.0, 7.5, 2.5, 7.5, 4.0);
101     }
102 
103     @Test
104     void testModeForwardIncrement() {
105         doTestStepsAtIntegerTimes(StepNormalizerMode.INCREMENT, 2.0, 7.5, 2.5, 7.5, 3.5);
106     }
107 
108     @Test
109     void testModeBackwardMultiples() {
110         doTestStepsAtIntegerTimes(StepNormalizerMode.MULTIPLES, 2.0, 2.5, 7.5, 2.5, 6.0);
111     }
112 
113     @Test
114     void testModeBackwardIncrement() {
115         doTestStepsAtIntegerTimes(StepNormalizerMode.INCREMENT, 2.0, 2.5, 7.5, 2.5, 6.5);
116     }
117 
118     private <T extends CalculusFieldElement<T>> void doTestBoundaries(final TestFieldProblemAbstract<T> pb,
119                                                                   final StepNormalizerBounds bounds,
120                                                                   final T stepSize,
121                                                                   final T expectedFirst,
122                                                                   final T expectedLast) {
123         double minStep = 0;
124         double maxStep = pb.getFinalTime().getReal() - pb.getInitialTime().getReal();
125         FieldODEIntegrator<T> integ =
126                         new DormandPrince54FieldIntegrator<>(stepSize.getField(),
127                                                              minStep, maxStep, 10.e-8, 1.0e-8);
128         final Checker<T> checker = new Checker<>();
129         if (bounds == null) {            
130             integ.addStepHandler(new FieldStepNormalizer<>(stepSize.getReal(), checker));
131         } else {
132             integ.addStepHandler(new FieldStepNormalizer<>(stepSize.getReal(), checker, bounds));
133         }
134         integ.integrate(new FieldExpandableODE<>(pb), pb.getInitialState(), pb.getFinalTime());
135         assertEquals(expectedFirst.getReal(), checker.firstTime.getReal(), 1.0e-10);
136         assertEquals(expectedLast.getReal(),  checker.lastTime.getReal(),  1.0e-10);
137     }
138 
139     private void doTestStepsAtIntegerTimes(final StepNormalizerMode mode,
140                                            final double stepSize,
141                                            final double t0, final double t1,
142                                            final double expectedFirst,
143                                            final double expectedLast) {
144         final TestFieldProblemAbstract<Binary64> pb = new TestFieldProblem3<Binary64>(new Binary64(0.9));
145         double minStep = 0;
146         double maxStep = pb.getFinalTime().getReal() - pb.getInitialTime().getReal();
147         FieldODEIntegrator<Binary64> integ =
148                         new DormandPrince54FieldIntegrator<>(Binary64Field.getInstance(),
149                                                              minStep, maxStep, 10.e-8, 1.0e-8);
150         final Checker<Binary64> checker = new Checker<>();
151         integ.addStepHandler(new FieldStepNormalizer<Binary64>(stepSize, checker, mode));
152         integ.integrate(new FieldExpandableODE<>(new FieldOrdinaryDifferentialEquation<Binary64>() {
153             public int getDimension() { return 1; }
154             public Binary64[] computeDerivatives(Binary64 t, Binary64[] y) { return y; }
155         }), new FieldODEState<>(new Binary64(t0), new Binary64[] { new Binary64(0) }), new Binary64(t1));
156         assertEquals(expectedFirst, checker.firstTime.getReal(), 1.0e-10);
157         assertEquals(expectedLast, checker.lastTime.getReal(),  1.0e-10);
158     }
159 
160     private static class Checker<T extends CalculusFieldElement<T>> implements FieldODEFixedStepHandler<T> {
161 
162         private T firstTime = null;
163         private T lastTime = null;
164 
165         public void handleStep(FieldODEStateAndDerivative<T> s, boolean isLast) {
166             if (firstTime == null) {
167                 firstTime = s.getTime();
168             }
169             if (isLast) {
170                 lastTime = s.getTime();
171             }
172         }
173 
174     }
175 
176 }