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    *      http://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.events;
18  
19  import org.hipparchus.analysis.solvers.BracketedRealFieldUnivariateSolver;
20  import org.hipparchus.analysis.solvers.FieldBracketingNthOrderBrentSolver;
21  import org.hipparchus.ode.FieldExpandableODE;
22  import org.hipparchus.ode.FieldODEIntegrator;
23  import org.hipparchus.ode.FieldODEState;
24  import org.hipparchus.ode.FieldODEStateAndDerivative;
25  import org.hipparchus.ode.FieldOrdinaryDifferentialEquation;
26  import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
27  import org.hipparchus.util.Binary64;
28  import org.hipparchus.util.Binary64Field;
29  import org.hipparchus.util.FastMath;
30  import org.junit.Assert;
31  import org.junit.Test;
32  
33  /** Tests for variable check interval.
34   */
35  public class FieldVariableCheckInterval implements FieldOrdinaryDifferentialEquation<Binary64> {
36  
37      @Test
38      public void testFixedInterval() {
39          double tZero = 7.0;
40          double width = 0.25;
41          doTest(tZero, width, s -> width / 25, 710);
42      }
43  
44      @Test
45      public void testWidthAwareInterval() {
46          double tZero = 7.0;
47          double width = 0.25;
48          doTest(tZero, width,
49                 s -> {
50                     if (s.getTime().getReal() < tZero - 0.5 * width) {
51                         return tZero - 0.25 * width - s.getTime().getReal();
52                     } else if (s.getTime().getReal() > tZero + 0.5 * width) {
53                         return s.getTime().getReal() - (tZero + 0.25 * width);
54                     } else {
55                         return width / 25;
56                     }
57                 },
58                 21);
59      }
60  
61      private void doTest(final double tZero, final double width, final FieldAdaptableInterval<Binary64> checkInterval,
62                          final int expectedCalls) {
63          double e = 1e-15;
64          FieldODEIntegrator<Binary64> integrator = new DormandPrince853FieldIntegrator<>(Binary64Field.getInstance(),
65                                                                                          e, 100.0, 1e-7, 1e-7);
66          Event evt = new Event(checkInterval, e, 999, tZero, width);
67          integrator.addEventDetector(evt);
68          Binary64 t = new Binary64(0.0);
69          Binary64 tEnd = new Binary64(9.75);
70          Binary64[] y = { new Binary64(0.0), new Binary64(0.0) };
71          final FieldODEStateAndDerivative<Binary64> finalState =
72                          integrator.integrate(new FieldExpandableODE<>(this), new FieldODEState<>(t, y), tEnd);
73          t = finalState.getTime();
74          Assert.assertEquals(tZero, finalState.getTime().getReal(), e);
75          Assert.assertEquals(expectedCalls, evt.count);
76       }
77  
78      /** {@inheritDoc} */
79      public int getDimension() {
80          return 2;
81      }
82  
83      /** {@inheritDoc} */
84      public Binary64[] computeDerivatives(Binary64 t, Binary64[] y) {
85          return new Binary64[] { new Binary64(1.0), new Binary64(2.0) };
86      }
87  
88      /** State events for this unit test. */
89      private class Event implements FieldODEEventDetector<Binary64> {
90  
91          private final FieldAdaptableInterval<Binary64>             maxCheck;
92          private final int                                          maxIter;
93          private final FieldBracketingNthOrderBrentSolver<Binary64> solver;
94          private final Binary64                                     tZero;
95          private final Binary64                                     width;
96          private       int                                          count;
97  
98          /** Constructor for the {@link Event} class.
99           * @param maxCheck maximum checking interval
100          * @param threshold convergence threshold (s)
101          * @param maxIter maximum number of iterations in the event time search
102          * @param tZero time of zero crossing event
103          * @param width width of variation interval
104          */
105         public Event(final FieldAdaptableInterval<Binary64> maxCheck, final double threshold, final int maxIter,
106                      final double tZero, final double width) {
107             this.maxCheck  = maxCheck;
108             this.maxIter   = maxIter;
109             this.solver    = new FieldBracketingNthOrderBrentSolver<>(Binary64.ZERO, new Binary64(threshold),
110                                                                       Binary64.ZERO, 5);
111             this.tZero     = new Binary64(tZero);
112             this.width     = new Binary64(width);
113         }
114 
115         public FieldAdaptableInterval<Binary64> getMaxCheckInterval() {
116             return maxCheck;
117         }
118 
119         public int getMaxIterationCount() {
120             return maxIter;
121         }
122 
123         public BracketedRealFieldUnivariateSolver<Binary64> getSolver() {
124             return solver;
125         }
126 
127         public FieldODEEventHandler<Binary64> getHandler() {
128             return (state, detector, increasing) -> Action.STOP;
129         }
130 
131         /** {@inheritDoc} */
132         public Binary64 g(final FieldODEStateAndDerivative<Binary64> s) {
133             ++count;
134             final Binary64 t = s.getTime();
135             return FastMath.max(width.multiply(-0.5), FastMath.min(width.multiply(0.5), t.subtract(tZero)));
136         }
137 
138         /** {@inheritDoc} */
139         public void init(final FieldODEStateAndDerivative<Binary64> initialState, final Binary64 finalTime) {
140             count = 0;
141         }
142 
143     }
144 
145 }