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 Hipparchus project 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  package org.hipparchus.ode.nonstiff;
19  
20  
21  import org.hipparchus.analysis.differentiation.DerivativeStructure;
22  import org.hipparchus.ode.ODEStateAndDerivative;
23  import org.hipparchus.ode.OrdinaryDifferentialEquation;
24  import org.hipparchus.ode.sampling.AbstractODEStateInterpolator;
25  import org.hipparchus.ode.sampling.ODEStateInterpolator;
26  import org.hipparchus.util.FastMath;
27  import org.junit.Assert;
28  import org.junit.Test;
29  
30  public abstract class ODEStateInterpolatorAbstractTest {
31  
32      @Test
33      public abstract void interpolationAtBounds();
34  
35      protected void doInterpolationAtBounds(double epsilon) {
36          ODEStateInterpolator interpolator = setUpInterpolator(new SinCos(), 0.0, new double[] { 0.0, 1.0 }, 0.125);
37  
38          Assert.assertEquals(0.0, interpolator.getPreviousState().getTime(), 1.0e-15);
39          for (int i = 0; i < 2; ++i) {
40              Assert.assertEquals(interpolator.getPreviousState().getPrimaryState()[i],
41                                  interpolator.getInterpolatedState(interpolator.getPreviousState().getTime()).getPrimaryState()[i],
42                                  epsilon);
43          }
44          Assert.assertEquals(0.125, interpolator.getCurrentState().getTime(), 1.0e-15);
45          for (int i = 0; i < 2; ++i) {
46              Assert.assertEquals(interpolator.getCurrentState().getPrimaryState()[i],
47                                  interpolator.getInterpolatedState(interpolator.getCurrentState().getTime()).getPrimaryState()[i],
48                                  epsilon);
49          }
50          Assert.assertEquals(false, interpolator.isPreviousStateInterpolated());
51          Assert.assertEquals(false, interpolator.isCurrentStateInterpolated());
52      }
53  
54      @Test
55      public abstract void interpolationInside();
56  
57      protected void doInterpolationInside(double epsilonSin, double epsilonCos) {
58  
59          SinCos sinCos = new SinCos();
60          ODEStateInterpolator interpolator = setUpInterpolator(sinCos, 0.0, new double[] { 0.0, 1.0 }, 0.0125);
61  
62          int n = 100;
63          double maxErrorSin = 0;
64          double maxErrorCos = 0;
65          for (int i = 0; i <= n; ++i) {
66              double t =     ((n - i) * interpolator.getPreviousState().getTime() +
67                                   i  * interpolator.getCurrentState().getTime()) / n;
68              final double[] interpolated = interpolator.getInterpolatedState(t).getPrimaryState();
69              double[] reference = sinCos.theoreticalState(t);
70              maxErrorSin = FastMath.max(maxErrorSin, FastMath.abs(interpolated[0] - reference[0]));
71              maxErrorCos = FastMath.max(maxErrorCos, FastMath.abs(interpolated[1] - reference[1]));
72          }
73  
74          Assert.assertEquals(0.0, maxErrorSin, epsilonSin);
75          Assert.assertEquals(0.0, maxErrorCos, epsilonCos);
76  
77          Assert.assertEquals(false, interpolator.isPreviousStateInterpolated());
78          Assert.assertEquals(false, interpolator.isCurrentStateInterpolated());
79      }
80  
81      @Test
82      public abstract void restrictPrevious();
83  
84      protected void doRestrictPrevious(double epsilon, double epsilonDot) {
85  
86          AbstractODEStateInterpolator original   = setUpInterpolator(new SinCos(), 0.0, new double[] { 0.0, 1.0 }, 0.125);
87  
88          Assert.assertEquals(false, original.isPreviousStateInterpolated());
89          Assert.assertEquals(false, original.isCurrentStateInterpolated());
90  
91          AbstractODEStateInterpolator restricted = original.restrictStep(original.getInterpolatedState(1.0 / 32),
92                                                                          original.getCurrentState());
93  
94          Assert.assertSame(original.getPreviousState(),       original.getGlobalPreviousState());
95          Assert.assertSame(original.getCurrentState(),        original.getGlobalCurrentState());
96          Assert.assertSame(original.getGlobalPreviousState(), restricted.getGlobalPreviousState());
97          Assert.assertSame(original.getGlobalCurrentState(),  restricted.getGlobalCurrentState());
98          Assert.assertNotSame(restricted.getPreviousState(),  restricted.getGlobalPreviousState());
99          Assert.assertSame(restricted.getCurrentState(),      restricted.getGlobalCurrentState());
100         Assert.assertEquals(1.0 / 32, restricted.getPreviousState().getTime(), 1.0e-15);
101         Assert.assertEquals(true, restricted.isPreviousStateInterpolated());
102         Assert.assertEquals(false, restricted.isCurrentStateInterpolated());
103 
104         checkRestricted(original, restricted, epsilon, epsilonDot);
105 
106     }
107 
108     @Test
109     public abstract void restrictCurrent();
110 
111     protected void doRestrictCurrent(double epsilon, double epsilonDot) {
112 
113         AbstractODEStateInterpolator original   = setUpInterpolator(new SinCos(), 0.0, new double[] { 0.0, 1.0 }, 0.125);
114 
115         Assert.assertEquals(false, original.isPreviousStateInterpolated());
116         Assert.assertEquals(false, original.isCurrentStateInterpolated());
117 
118         AbstractODEStateInterpolator restricted = original.restrictStep(original.getPreviousState(),
119                                                                         original.getInterpolatedState(3.0 / 32));
120 
121         Assert.assertSame(original.getPreviousState(),       original.getGlobalPreviousState());
122         Assert.assertSame(original.getCurrentState(),        original.getGlobalCurrentState());
123         Assert.assertSame(original.getGlobalPreviousState(), restricted.getGlobalPreviousState());
124         Assert.assertSame(original.getGlobalCurrentState(),  restricted.getGlobalCurrentState());
125         Assert.assertSame(restricted.getPreviousState(),     restricted.getGlobalPreviousState());
126         Assert.assertNotSame(restricted.getCurrentState(),   restricted.getGlobalCurrentState());
127         Assert.assertEquals(3.0 / 32, restricted.getCurrentState().getTime(), 1.0e-15);
128         Assert.assertEquals(false, restricted.isPreviousStateInterpolated());
129         Assert.assertEquals(true, restricted.isCurrentStateInterpolated());
130 
131         checkRestricted(original, restricted, epsilon, epsilonDot);
132 
133     }
134 
135     @Test
136     public abstract void restrictBothEnds();
137 
138     protected void doRestrictBothEnds(double epsilon, double epsilonDot) {
139 
140         AbstractODEStateInterpolator original   = setUpInterpolator(new SinCos(), 0.0, new double[] { 0.0, 1.0 }, 0.125);
141 
142         Assert.assertEquals(false, original.isPreviousStateInterpolated());
143         Assert.assertEquals(false, original.isCurrentStateInterpolated());
144 
145         AbstractODEStateInterpolator restricted = original.restrictStep(original.getInterpolatedState(1.0 / 32),
146                                                                         original.getInterpolatedState(3.0 / 32));
147 
148         Assert.assertSame(original.getPreviousState(),       original.getGlobalPreviousState());
149         Assert.assertSame(original.getCurrentState(),        original.getGlobalCurrentState());
150         Assert.assertSame(original.getGlobalPreviousState(), restricted.getGlobalPreviousState());
151         Assert.assertSame(original.getGlobalCurrentState(),  restricted.getGlobalCurrentState());
152         Assert.assertNotSame(restricted.getPreviousState(),  restricted.getGlobalPreviousState());
153         Assert.assertNotSame(restricted.getCurrentState(),   restricted.getGlobalCurrentState());
154         Assert.assertEquals(1.0 / 32, restricted.getPreviousState().getTime(), 1.0e-15);
155         Assert.assertEquals(3.0 / 32, restricted.getCurrentState().getTime(), 1.0e-15);
156         Assert.assertEquals(true, restricted.isPreviousStateInterpolated());
157         Assert.assertEquals(true, restricted.isCurrentStateInterpolated());
158 
159         checkRestricted(original, restricted, epsilon, epsilonDot);
160 
161     }
162 
163     @Test
164     public abstract void degenerateInterpolation();
165 
166     protected void doDegenerateInterpolation() {
167         AbstractODEStateInterpolator interpolator = setUpInterpolator(new SinCos(), 0.0, new double[] { 0.0, 1.0 }, 0.0);
168         ODEStateAndDerivative interpolatedState = interpolator.getInterpolatedState(0.0);
169         Assert.assertEquals(0.0, interpolatedState.getTime(), 0.0);
170         Assert.assertEquals(0.0, interpolatedState.getPrimaryState()[0], 0.0);
171         Assert.assertEquals(1.0, interpolatedState.getPrimaryState()[1], 0.0);
172         Assert.assertEquals(1.0, interpolatedState.getPrimaryDerivative()[0], 0.0);
173         Assert.assertEquals(0.0, interpolatedState.getPrimaryDerivative()[1], 0.0);
174     }
175 
176     private void checkRestricted(AbstractODEStateInterpolator original, AbstractODEStateInterpolator restricted,
177                                  double epsilon, double epsilonDot) {
178         for (double t = restricted.getPreviousState().getTime();
179              t <= restricted.getCurrentState().getTime();
180              t += 1.0 / 256) {
181             ODEStateAndDerivative originalInterpolated   = original.getInterpolatedState(t);
182             ODEStateAndDerivative restrictedInterpolated = restricted.getInterpolatedState(t);
183             Assert.assertEquals(t, originalInterpolated.getTime(), 1.0e-15);
184             Assert.assertEquals(t, restrictedInterpolated.getTime(), 1.0e-15);
185             Assert.assertEquals(originalInterpolated.getPrimaryState()[0],
186                                 restrictedInterpolated.getPrimaryState()[0],
187                                 epsilon);
188             Assert.assertEquals(originalInterpolated.getPrimaryState()[1],
189                                 restrictedInterpolated.getPrimaryState()[1],
190                                 epsilon);
191             Assert.assertEquals(originalInterpolated.getPrimaryDerivative()[0],
192                                 restrictedInterpolated.getPrimaryDerivative()[0],
193                                 epsilonDot);
194             Assert.assertEquals(originalInterpolated.getPrimaryDerivative()[1],
195                                 restrictedInterpolated.getPrimaryDerivative()[1],
196                                 epsilonDot);
197         }
198 
199     }
200 
201     public interface ReferenceODE extends OrdinaryDifferentialEquation {
202         double[]              theoreticalState(double t);
203         DerivativeStructure[] theoreticalState(DerivativeStructure t);
204     }
205 
206     protected abstract AbstractODEStateInterpolator setUpInterpolator(final ReferenceODE eqn,
207                                                                       final double t0, final double[] y0,
208                                                                       final double t1);
209 
210     private static class SinCos implements ReferenceODE {
211         public int getDimension() {
212             return 2;
213         }
214         public double[] computeDerivatives(final double t, final double[] y) {
215             return new double[] {
216                 y[1], -y[0]
217             };
218         }
219         public double[] theoreticalState(final double t) {
220             return new double[] {
221                 FastMath.sin(t), FastMath.cos(t)
222             };
223         }
224         public DerivativeStructure[] theoreticalState(final DerivativeStructure t) {
225             return new DerivativeStructure[] {
226                 t.sin(), t.cos()
227             };
228         }
229     }
230 
231 }