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.CalculusFieldElement;
21  import org.hipparchus.analysis.solvers.BracketedRealFieldUnivariateSolver;
22  import org.hipparchus.ode.FieldODEStateAndDerivative;
23  
24  /** This interface represents a handler for discrete events triggered
25   * during ODE integration.
26   *
27   * <p>Some events can be triggered at discrete times as an ODE problem
28   * is solved. This occurs for example when the integration process
29   * should be stopped as some state is reached (G-stop facility) when the
30   * precise date is unknown a priori, or when the derivatives have
31   * states boundaries crossings.
32   * </p>
33   *
34   * <p>These events are defined as occurring when a <code>g</code>
35   * switching function sign changes.</p>
36   *
37   * <p>Since events are only problem-dependent and are triggered by the
38   * independent <i>time</i> variable and the state vector, they can
39   * occur at virtually any time, unknown in advance. The integrators will
40   * take care to avoid sign changes inside the steps, they will reduce
41   * the step size when such an event is detected in order to put this
42   * event exactly at the end of the current step. This guarantees that
43   * step interpolation (which always has a one step scope) is relevant
44   * even in presence of discontinuities. This is independent from the
45   * stepsize control provided by integrators that monitor the local
46   * error (this event handling feature is available for all integrators,
47   * including fixed step ones).</p>
48   *
49   * <p>
50   * Note that prior to Hipparchus 3.0, the methods in this interface were
51   * in the {@link FieldODEEventHandler} interface and the defunct
52   * {@code FieldEventHandlerConfiguration} interface. The interfaces have been
53   * reorganized to allow different objects to be used in event detection
54   * and event handling, hence allowing users to reuse predefined events
55   * detectors with custom handlers.
56   * </p>
57   *
58   * @see org.hipparchus.ode.events
59   * @since 3.0
60   * @param <T> the type of the field elements
61   */
62  public interface FieldODEEventDetector<T extends CalculusFieldElement<T>>  {
63  
64      /** Get the maximal time interval between events handler checks.
65       * @return maximal time interval between events handler checks
66       */
67      FieldAdaptableInterval<T> getMaxCheckInterval();
68  
69      /** Get the upper limit in the iteration count for event localization.
70       * @return upper limit in the iteration count for event localization
71       */
72      int getMaxIterationCount();
73  
74      /** Get the root-finding algorithm to use to detect state events.
75       * @return root-finding algorithm to use to detect state events
76       */
77      BracketedRealFieldUnivariateSolver<T> getSolver();
78  
79      /** Get the underlying event handler.
80       * @return underlying event handler
81       */
82      FieldODEEventHandler<T> getHandler();
83  
84      /** Initialize event detector at the start of an ODE integration.
85       * <p>
86       * This method is called once at the start of the integration. It
87       * may be used by the event detector to initialize some internal data
88       * if needed.
89       * </p>
90       * <p>
91       * The default implementation initializes the handler.
92       * </p>
93       * @param initialState initial time, state vector and derivative
94       * @param finalTime target time for the integration
95       */
96      default void init(FieldODEStateAndDerivative<T> initialState, T finalTime) {
97          getHandler().init(initialState, finalTime, this);
98      }
99  
100     /** Reset event detector during integration.
101      * <p>
102      * This method is called during integration if the derivatives or the state variables themselves are reset.
103      * </p>
104      * <p>
105      * The default implementation does nothing.
106      * </p>
107      * @param intermediateState intermediate time, state vector and derivative
108      * @param finalTime target time for the integration
109      * @since 4.0
110      */
111     default void reset(FieldODEStateAndDerivative<T> intermediateState, T finalTime) {
112         // nothing by default
113     }
114 
115     /** Compute the value of the switching function.
116 
117      * <p>The discrete events are generated when the sign of this
118      * switching function changes. The integrator will take care to change
119      * the stepsize in such a way these events occur exactly at step boundaries.
120      * The switching function must be continuous in its roots neighborhood
121      * (but not necessarily smooth), as the integrator will need to find its
122      * roots to locate precisely the events.</p>
123      * <p>Also note that the integrator expect that once an event has occurred,
124      * the sign of the switching function at the start of the next step (i.e.
125      * just after the event) is the opposite of the sign just before the event.
126      * This consistency between the steps <strong>must</strong> be preserved,
127      * otherwise {@link org.hipparchus.exception.MathIllegalArgumentException
128      * exceptions} related to root not being bracketed will occur.</p>
129      * <p>This need for consistency is sometimes tricky to achieve. A typical
130      * example is using an event to model a ball bouncing on the floor. The first
131      * idea to represent this would be to have {@code g(state) = h(state)} where h is the
132      * height above the floor at time {@code state.getTime()}. When {@code g(state)} reaches 0, the
133      * ball is on the floor, so it should bounce and the typical way to do this is
134      * to reverse its vertical velocity. However, this would mean that before the
135      * event {@code g(state)} was decreasing from positive values to 0, and after the
136      * event {@code g(state)} would be increasing from 0 to positive values again.
137      * Consistency is broken here! The solution here is to have {@code g(state) = sign
138      * * h(state)}, where sign is a variable with initial value set to {@code +1}. Each
139      * time {@link FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative,
140      * FieldODEEventDetector, boolean) eventOccurred}
141      * method is called, {@code sign} is reset to {@code -sign}. This allows the
142      * {@code g(state)} function to remain continuous (and even smooth) even across events,
143      * despite {@code h(state)} is not. Basically, the event is used to <em>fold</em>
144      * {@code h(state)} at bounce points, and {@code sign} is used to <em>unfold</em> it
145      * back, so the solvers sees a {@code g(state)} function which behaves smoothly even
146      * across events.</p>
147      *
148      * <p>This method is idempotent, that is calling this multiple times with the same
149      * state will result in the same value, with two exceptions. First, the definition of
150      * the g function may change when an {@link
151      * FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative, FieldODEEventDetector,
152      * boolean) event occurs} on the handler, as in the above example. Second, the
153      * definition of the g function may change when the {@link
154      * FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative, FieldODEEventDetector,
155      * boolean) event occurs} method of any other event handler in the same integrator returns
156      * {@link Action#RESET_EVENTS}, {@link Action#RESET_DERIVATIVES}, or {@link Action#RESET_STATE}.
157      *
158      * @param state current value of the independent <i>time</i> variable, state vector
159      * and derivative
160      * @return value of the g switching function
161      */
162     T g(FieldODEStateAndDerivative<T> state);
163 
164 }