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