FieldODEEventDetector.java

  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. package org.hipparchus.ode.events;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.analysis.solvers.BracketedRealFieldUnivariateSolver;
  20. import org.hipparchus.ode.FieldODEStateAndDerivative;

  21. /** This interface represents a handler for discrete events triggered
  22.  * during ODE integration.
  23.  *
  24.  * <p>Some events can be triggered at discrete times as an ODE problem
  25.  * is solved. This occurs for example when the integration process
  26.  * should be stopped as some state is reached (G-stop facility) when the
  27.  * precise date is unknown a priori, or when the derivatives have
  28.  * states boundaries crossings.
  29.  * </p>
  30.  *
  31.  * <p>These events are defined as occurring when a <code>g</code>
  32.  * switching function sign changes.</p>
  33.  *
  34.  * <p>Since events are only problem-dependent and are triggered by the
  35.  * independent <i>time</i> variable and the state vector, they can
  36.  * occur at virtually any time, unknown in advance. The integrators will
  37.  * take care to avoid sign changes inside the steps, they will reduce
  38.  * the step size when such an event is detected in order to put this
  39.  * event exactly at the end of the current step. This guarantees that
  40.  * step interpolation (which always has a one step scope) is relevant
  41.  * even in presence of discontinuities. This is independent from the
  42.  * stepsize control provided by integrators that monitor the local
  43.  * error (this event handling feature is available for all integrators,
  44.  * including fixed step ones).</p>
  45.  *
  46.  * <p>
  47.  * Note that prior to Hipparchus 3.0, the methods in this interface were
  48.  * in the {@link FieldODEEventHandler} interface and the defunct
  49.  * {@code FieldEventHandlerConfiguration} interface. The interfaces have been
  50.  * reorganized to allow different objects to be used in event detection
  51.  * and event handling, hence allowing users to reuse predefined events
  52.  * detectors with custom handlers.
  53.  * </p>
  54.  *
  55.  * @see org.hipparchus.ode.events
  56.  * @since 3.0
  57.  * @param <T> the type of the field elements
  58.  */
  59. public interface FieldODEEventDetector<T extends CalculusFieldElement<T>>  {

  60.     /** Get the maximal time interval between events handler checks.
  61.      * @return maximal time interval between events handler checks
  62.      */
  63.     FieldAdaptableInterval<T> getMaxCheckInterval();

  64.     /** Get the upper limit in the iteration count for event localization.
  65.      * @return upper limit in the iteration count for event localization
  66.      */
  67.     int getMaxIterationCount();

  68.     /** Get the root-finding algorithm to use to detect state events.
  69.      * @return root-finding algorithm to use to detect state events
  70.      */
  71.     BracketedRealFieldUnivariateSolver<T> getSolver();

  72.     /** Get the underlying event handler.
  73.      * @return underlying event handler
  74.      */
  75.     FieldODEEventHandler<T> getHandler();

  76.     /** Initialize event detector at the start of an ODE integration.
  77.      * <p>
  78.      * This method is called once at the start of the integration. It
  79.      * may be used by the event detector to initialize some internal data
  80.      * if needed.
  81.      * </p>
  82.      * <p>
  83.      * The default implementation initializes the handler.
  84.      * </p>
  85.      * @param initialState initial time, state vector and derivative
  86.      * @param finalTime target time for the integration
  87.      */
  88.     default void init(FieldODEStateAndDerivative<T> initialState, T finalTime) {
  89.         getHandler().init(initialState, finalTime, this);
  90.     }

  91.     /** Reset event detector during integration.
  92.      * <p>
  93.      * This method is called during integration if the derivatives or the state variables themselves are reset.
  94.      * </p>
  95.      * <p>
  96.      * The default implementation does nothing.
  97.      * </p>
  98.      * @param intermediateState intermediate time, state vector and derivative
  99.      * @param finalTime target time for the integration
  100.      * @since 4.0
  101.      */
  102.     default void reset(FieldODEStateAndDerivative<T> intermediateState, T finalTime) {
  103.         // nothing by default
  104.     }

  105.     /** Compute the value of the switching function.

  106.      * <p>The discrete events are generated when the sign of this
  107.      * switching function changes. The integrator will take care to change
  108.      * the stepsize in such a way these events occur exactly at step boundaries.
  109.      * The switching function must be continuous in its roots neighborhood
  110.      * (but not necessarily smooth), as the integrator will need to find its
  111.      * roots to locate precisely the events.</p>
  112.      * <p>Also note that the integrator expect that once an event has occurred,
  113.      * the sign of the switching function at the start of the next step (i.e.
  114.      * just after the event) is the opposite of the sign just before the event.
  115.      * This consistency between the steps <strong>must</strong> be preserved,
  116.      * otherwise {@link org.hipparchus.exception.MathIllegalArgumentException
  117.      * exceptions} related to root not being bracketed will occur.</p>
  118.      * <p>This need for consistency is sometimes tricky to achieve. A typical
  119.      * example is using an event to model a ball bouncing on the floor. The first
  120.      * idea to represent this would be to have {@code g(state) = h(state)} where h is the
  121.      * height above the floor at time {@code state.getTime()}. When {@code g(state)} reaches 0, the
  122.      * ball is on the floor, so it should bounce and the typical way to do this is
  123.      * to reverse its vertical velocity. However, this would mean that before the
  124.      * event {@code g(state)} was decreasing from positive values to 0, and after the
  125.      * event {@code g(state)} would be increasing from 0 to positive values again.
  126.      * Consistency is broken here! The solution here is to have {@code g(state) = sign
  127.      * * h(state)}, where sign is a variable with initial value set to {@code +1}. Each
  128.      * time {@link FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative,
  129.      * FieldODEEventDetector, boolean) eventOccurred}
  130.      * method is called, {@code sign} is reset to {@code -sign}. This allows the
  131.      * {@code g(state)} function to remain continuous (and even smooth) even across events,
  132.      * despite {@code h(state)} is not. Basically, the event is used to <em>fold</em>
  133.      * {@code h(state)} at bounce points, and {@code sign} is used to <em>unfold</em> it
  134.      * back, so the solvers sees a {@code g(state)} function which behaves smoothly even
  135.      * across events.</p>
  136.      *
  137.      * <p>This method is idempotent, that is calling this multiple times with the same
  138.      * state will result in the same value, with two exceptions. First, the definition of
  139.      * the g function may change when an {@link
  140.      * FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative, FieldODEEventDetector,
  141.      * boolean) event occurs} on the handler, as in the above example. Second, the
  142.      * definition of the g function may change when the {@link
  143.      * FieldODEEventHandler#eventOccurred(FieldODEStateAndDerivative, FieldODEEventDetector,
  144.      * boolean) event occurs} method of any other event handler in the same integrator returns
  145.      * {@link Action#RESET_EVENTS}, {@link Action#RESET_DERIVATIVES}, or {@link Action#RESET_STATE}.
  146.      *
  147.      * @param state current value of the independent <i>time</i> variable, state vector
  148.      * and derivative
  149.      * @return value of the g switching function
  150.      */
  151.     T g(FieldODEStateAndDerivative<T> state);

  152. }