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_MAXCHECK = 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          forward = t >= s0.getTime();
81          getHandler().init(s0, t, this);
82      }
83  
84      /** {@inheritDoc} */
85      @Override
86      public abstract double g(ODEStateAndDerivative s);
87  
88      /** {@inheritDoc} */
89      @Override
90      public AdaptableInterval getMaxCheckInterval() {
91          return maxCheck;
92      }
93  
94      /** {@inheritDoc} */
95      @Override
96      public int getMaxIterationCount() {
97          return maxIter;
98      }
99  
100     /** {@inheritDoc} */
101     @Override
102     public BracketedUnivariateSolver<UnivariateFunction> getSolver() {
103         return solver;
104     }
105 
106     /**
107      * Setup the maximum checking interval.
108      * <p>
109      * This will override a maximum checking interval if it has been configured previously.
110      * </p>
111      * @param newMaxCheck maximum checking interval
112      * @return a new detector with updated configuration (the instance is not changed)
113      */
114     public T withMaxCheck(final double newMaxCheck) {
115         return withMaxCheck(s -> newMaxCheck);
116     }
117 
118     /**
119      * Setup the maximum checking interval.
120      * <p>
121      * This will override a maximum checking interval if it has been configured previously.
122      * </p>
123      * @param newMaxCheck maximum checking interval
124      * @return a new detector with updated configuration (the instance is not changed)
125      * @since 3.0
126      */
127     public T withMaxCheck(final AdaptableInterval newMaxCheck) {
128         return create(newMaxCheck, getMaxIterationCount(), getSolver(), getHandler());
129     }
130 
131     /**
132      * Setup the maximum number of iterations in the event time search.
133      * <p>
134      * This will override a number of iterations if it has been configured previously.
135      * </p>
136      * @param newMaxIter maximum number of iterations in the event time search
137      * @return a new detector with updated configuration (the instance is not changed)
138      */
139     public T withMaxIter(final int newMaxIter) {
140         return create(getMaxCheckInterval(), newMaxIter, getSolver(), getHandler());
141     }
142 
143     /**
144      * Setup the convergence threshold.
145      * <p>
146      * This is equivalent to call {@code withSolver(new BracketingNthOrderBrentSolver(0,
147      * newThreshold, 0, 5))}, so it will override a solver if one has been configured previously.
148      * </p>
149      * @param newThreshold convergence threshold
150      * @return a new detector with updated configuration (the instance is not changed)
151      * @see #withSolver(BracketedUnivariateSolver)
152      */
153     public T withThreshold(final double newThreshold) {
154         return withSolver(new BracketingNthOrderBrentSolver(0, newThreshold, 0, 5));
155     }
156 
157     /**
158      * Setup the root-finding algorithm to use to detect state events.
159      * <p>
160      * This will override a solver if it has been configured previously.
161      * </p>
162      * @param newSolver root-finding algorithm to use to detect state events
163      * @return a new detector with updated configuration (the instance is not changed)
164      * @see #withThreshold(double)
165      */
166     public T withSolver(final BracketedUnivariateSolver<UnivariateFunction> newSolver) {
167         return create(getMaxCheckInterval(), getMaxIterationCount(), newSolver, getHandler());
168     }
169 
170     /**
171      * Setup the event handler to call at event occurrences.
172      * <p>
173      * This will override a handler if it has been configured previously.
174      * </p>
175      * @param newHandler event handler to call at event occurrences
176      * @return a new detector with updated configuration (the instance is not changed)
177      */
178     public T withHandler(final ODEEventHandler newHandler) {
179         return create(getMaxCheckInterval(), getMaxIterationCount(), getSolver(), newHandler);
180     }
181 
182     /** {@inheritDoc} */
183     @Override
184     public ODEEventHandler getHandler() {
185         return handler;
186     }
187 
188     /** Build a new instance.
189      * @param newMaxCheck maximum checking interval
190      * @param newmaxIter maximum number of iterations in the event time search
191      * @param newSolver root-finding algorithm to use to detect state events
192      * @param newHandler event handler to call at event occurrences
193      * @return a new instance of the appropriate sub-type
194      */
195     protected abstract T create(AdaptableInterval newMaxCheck, int newmaxIter,
196                                 BracketedUnivariateSolver<UnivariateFunction> newSolver,
197                                 ODEEventHandler newHandler);
198 
199     /** Check if the current propagation is forward or backward.
200      * @return true if the current propagation is forward
201      */
202     public boolean isForward() {
203         return forward;
204     }
205 
206 }