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.events;
19  
20  import org.hipparchus.analysis.UnivariateFunction;
21  import org.hipparchus.analysis.solvers.BracketedUnivariateSolver;
22  import org.hipparchus.analysis.solvers.BracketingNthOrderBrentSolver;
23  import org.hipparchus.ode.ODEStateAndDerivative;
24  
25  /** Base class for #@link {@link ODEEventDetector}.
26   * @param <T> type of the detector
27   * @since 3.0
28   */
29  public abstract class AbstractODEDetector<T extends AbstractODEDetector<T>> implements ODEEventDetector {
30  
31      /** Default maximum checking interval (s). */
32      public static final double DEFAULT_MAX_CHECK = 600;
33  
34      /** Default convergence threshold (s). */
35      public static final double DEFAULT_THRESHOLD = 1.e-6;
36  
37      /** Default maximum number of iterations in the event time search. */
38      public static final int DEFAULT_MAX_ITER = 100;
39  
40      /** Max check interval. */
41      private final AdaptableInterval maxCheck;
42  
43      /** Maximum number of iterations in the event time search. */
44      private final int maxIter;
45  
46      /** Root-finding algorithm to use to detect state events. */
47      private final BracketedUnivariateSolver<UnivariateFunction> solver;
48  
49      /** Default handler for event overrides. */
50      private final ODEEventHandler handler;
51  
52      /** Propagation direction. */
53      private boolean forward;
54  
55      /** Build a new instance.
56       * @param maxCheck maximum checking interval, must be strictly positive (s)
57       * @param maxIter maximum number of iterations in the event time search
58       * @param solver root-finding algorithm to use to detect state events
59       * @param handler event handler to call at event occurrences
60       */
61      protected AbstractODEDetector(final AdaptableInterval maxCheck, final int maxIter,
62                                    final BracketedUnivariateSolver<UnivariateFunction> solver,
63                                    final ODEEventHandler handler) {
64          this.maxCheck  = maxCheck;
65          this.maxIter   = maxIter;
66          this.solver    = solver;
67          this.handler   = handler;
68          this.forward   = true;
69      }
70  
71      /**
72       * {@inheritDoc}
73       *
74       * <p> This implementation sets the direction of integration and initializes the event
75       * handler. If a subclass overrides this method it should call {@code
76       * super.init(s0, t)}.
77       */
78      @Override
79      public void init(final ODEStateAndDerivative s0, final double t) {
80          ODEEventDetector.super.init(s0, t);
81          forward = t >= s0.getTime();
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public AdaptableInterval getMaxCheckInterval() {
87          return maxCheck;
88      }
89  
90      /** {@inheritDoc} */
91      @Override
92      public int getMaxIterationCount() {
93          return maxIter;
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      public BracketedUnivariateSolver<UnivariateFunction> getSolver() {
99          return solver;
100     }
101 
102     /**
103      * Setup the maximum checking interval.
104      * <p>
105      * This will override a maximum checking interval if it has been configured previously.
106      * </p>
107      * @param newMaxCheck maximum checking interval
108      * @return a new detector with updated configuration (the instance is not changed)
109      */
110     public T withMaxCheck(final double newMaxCheck) {
111         return withMaxCheck(AdaptableInterval.of(newMaxCheck));
112     }
113 
114     /**
115      * Setup the maximum checking interval.
116      * <p>
117      * This will override a maximum checking interval if it has been configured previously.
118      * </p>
119      * @param newMaxCheck maximum checking interval
120      * @return a new detector with updated configuration (the instance is not changed)
121      * @since 3.0
122      */
123     public T withMaxCheck(final AdaptableInterval newMaxCheck) {
124         return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler());
125     }
126 
127     /**
128      * Setup the maximum number of iterations in the event time search.
129      * <p>
130      * This will override a number of iterations if it has been configured previously.
131      * </p>
132      * @param newMaxIter maximum number of iterations in the event time search
133      * @return a new detector with updated configuration (the instance is not changed)
134      */
135     public T withMaxIter(final int newMaxIter) {
136         return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler());
137     }
138 
139     /**
140      * Setup the convergence threshold.
141      * <p>
142      * This is equivalent to call {@code withSolver(new BracketingNthOrderBrentSolver(0,
143      * newThreshold, 0, 5))}, so it will override a solver if one has been configured previously.
144      * </p>
145      * @param newThreshold convergence threshold
146      * @return a new detector with updated configuration (the instance is not changed)
147      * @see #withSolver(BracketedUnivariateSolver)
148      */
149     public T withThreshold(final double newThreshold) {
150         return withSolver(new BracketingNthOrderBrentSolver(0, newThreshold, 0, 5));
151     }
152 
153     /**
154      * Setup the root-finding algorithm to use to detect state events.
155      * <p>
156      * This will override a solver if it has been configured previously.
157      * </p>
158      * @param newSolver root-finding algorithm to use to detect state events
159      * @return a new detector with updated configuration (the instance is not changed)
160      * @see #withThreshold(double)
161      */
162     public T withSolver(final BracketedUnivariateSolver<UnivariateFunction> newSolver) {
163         return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler());
164     }
165 
166     /**
167      * Setup the event handler to call at event occurrences.
168      * <p>
169      * This will override a handler if it has been configured previously.
170      * </p>
171      * @param newHandler event handler to call at event occurrences
172      * @return a new detector with updated configuration (the instance is not changed)
173      */
174     public T withHandler(final ODEEventHandler newHandler) {
175         return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler);
176     }
177 
178     /** {@inheritDoc} */
179     @Override
180     public ODEEventHandler getHandler() {
181         return handler;
182     }
183 
184     /** Build a new instance.
185      * @param newMaxCheck maximum checking interval
186      * @param newmaxIter maximum number of iterations in the event time search
187      * @param newSolver root-finding algorithm to use to detect state events
188      * @param newHandler event handler to call at event occurrences
189      * @return a new instance of the appropriate sub-type
190      */
191     protected abstract T create(AdaptableInterval newMaxCheck, int newmaxIter,
192                                 BracketedUnivariateSolver<UnivariateFunction> newSolver,
193                                 ODEEventHandler newHandler);
194 
195     /** Check if the current propagation is forward or backward.
196      * @return true if the current propagation is forward
197      */
198     public boolean isForward() {
199         return forward;
200     }
201 
202 }