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