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