Home | History | Annotate | Download | only in events
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) 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 ASF 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 
     18 package org.apache.commons.math.ode.events;
     19 
     20 /** This interface represents a handler for discrete events triggered
     21  * during ODE integration.
     22  *
     23  * <p>Some events can be triggered at discrete times as an ODE problem
     24  * is solved. This occurs for example when the integration process
     25  * should be stopped as some state is reached (G-stop facility) when the
     26  * precise date is unknown a priori, or when the derivatives have
     27  * discontinuities, or simply when the user wants to monitor some
     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  * @version $Revision: 1067500 $ $Date: 2011-02-05 21:11:30 +0100 (sam. 05 fvr. 2011) $
     47  * @since 1.2
     48  */
     49 
     50 public interface EventHandler  {
     51 
     52   /** Stop indicator.
     53    * <p>This value should be used as the return value of the {@link
     54    * #eventOccurred eventOccurred} method when the integration should be
     55    * stopped after the event ending the current step.</p>
     56    */
     57   int STOP = 0;
     58 
     59   /** Reset state indicator.
     60    * <p>This value should be used as the return value of the {@link
     61    * #eventOccurred eventOccurred} method when the integration should
     62    * go on after the event ending the current step, with a new state
     63    * vector (which will be retrieved thanks to the {@link #resetState
     64    * resetState} method).</p>
     65    */
     66   int RESET_STATE = 1;
     67 
     68   /** Reset derivatives indicator.
     69    * <p>This value should be used as the return value of the {@link
     70    * #eventOccurred eventOccurred} method when the integration should
     71    * go on after the event ending the current step, with a new derivatives
     72    * vector (which will be retrieved thanks to the {@link
     73    * org.apache.commons.math.ode.FirstOrderDifferentialEquations#computeDerivatives}
     74    * method).</p>
     75    */
     76   int RESET_DERIVATIVES = 2;
     77 
     78   /** Continue indicator.
     79    * <p>This value should be used as the return value of the {@link
     80    * #eventOccurred eventOccurred} method when the integration should go
     81    * on after the event ending the current step.</p>
     82    */
     83   int CONTINUE = 3;
     84 
     85   /** Compute the value of the switching function.
     86 
     87    * <p>The discrete events are generated when the sign of this
     88    * switching function changes. The integrator will take care to change
     89    * the stepsize in such a way these events occur exactly at step boundaries.
     90    * The switching function must be continuous in its roots neighborhood
     91    * (but not necessarily smooth), as the integrator will need to find its
     92    * roots to locate precisely the events.</p>
     93    *
     94    * @param t current value of the independent <i>time</i> variable
     95    * @param y array containing the current value of the state vector
     96    * @return value of the g switching function
     97    * @exception EventException if the switching function cannot be evaluated
     98    */
     99   double g(double t, double[] y) throws EventException;
    100 
    101   /** Handle an event and choose what to do next.
    102 
    103    * <p>This method is called when the integrator has accepted a step
    104    * ending exactly on a sign change of the function, just <em>before</em>
    105    * the step handler itself is called (see below for scheduling). It
    106    * allows the user to update his internal data to acknowledge the fact
    107    * the event has been handled (for example setting a flag in the {@link
    108    * org.apache.commons.math.ode.FirstOrderDifferentialEquations
    109    * differential equations} to switch the derivatives computation in
    110    * case of discontinuity), or to direct the integrator to either stop
    111    * or continue integration, possibly with a reset state or derivatives.</p>
    112    *
    113    * <ul>
    114    *   <li>if {@link #STOP} is returned, the step handler will be called
    115    *   with the <code>isLast</code> flag of the {@link
    116    *   org.apache.commons.math.ode.sampling.StepHandler#handleStep handleStep}
    117    *   method set to true and the integration will be stopped,</li>
    118    *   <li>if {@link #RESET_STATE} is returned, the {@link #resetState
    119    *   resetState} method will be called once the step handler has
    120    *   finished its task, and the integrator will also recompute the
    121    *   derivatives,</li>
    122    *   <li>if {@link #RESET_DERIVATIVES} is returned, the integrator
    123    *   will recompute the derivatives,
    124    *   <li>if {@link #CONTINUE} is returned, no specific action will
    125    *   be taken (apart from having called this method) and integration
    126    *   will continue.</li>
    127    * </ul>
    128    *
    129    * <p>The scheduling between this method and the {@link
    130    * org.apache.commons.math.ode.sampling.StepHandler StepHandler} method {@link
    131    * org.apache.commons.math.ode.sampling.StepHandler#handleStep(
    132    * org.apache.commons.math.ode.sampling.StepInterpolator, boolean)
    133    * handleStep(interpolator, isLast)} is to call this method first and
    134    * <code>handleStep</code> afterwards. This scheduling allows the integrator to
    135    * pass <code>true</code> as the <code>isLast</code> parameter to the step
    136    * handler to make it aware the step will be the last one if this method
    137    * returns {@link #STOP}. As the interpolator may be used to navigate back
    138    * throughout the last step (as {@link
    139    * org.apache.commons.math.ode.sampling.StepNormalizer StepNormalizer}
    140    * does for example), user code called by this method and user
    141    * code called by step handlers may experience apparently out of order values
    142    * of the independent time variable. As an example, if the same user object
    143    * implements both this {@link EventHandler EventHandler} interface and the
    144    * {@link org.apache.commons.math.ode.sampling.FixedStepHandler FixedStepHandler}
    145    * interface, a <em>forward</em> integration may call its
    146    * <code>eventOccurred</code> method with t = 10 first and call its
    147    * <code>handleStep</code> method with t = 9 afterwards. Such out of order
    148    * calls are limited to the size of the integration step for {@link
    149    * org.apache.commons.math.ode.sampling.StepHandler variable step handlers} and
    150    * to the size of the fixed step for {@link
    151    * org.apache.commons.math.ode.sampling.FixedStepHandler fixed step handlers}.</p>
    152    *
    153    * @param t current value of the independent <i>time</i> variable
    154    * @param y array containing the current value of the state vector
    155    * @param increasing if true, the value of the switching function increases
    156    * when times increases around event (note that increase is measured with respect
    157    * to physical time, not with respect to integration which may go backward in time)
    158    * @return indication of what the integrator should do next, this
    159    * value must be one of {@link #STOP}, {@link #RESET_STATE},
    160    * {@link #RESET_DERIVATIVES} or {@link #CONTINUE}
    161    * @exception EventException if the event occurrence triggers an error
    162    */
    163   int eventOccurred(double t, double[] y, boolean increasing) throws EventException;
    164 
    165   /** Reset the state prior to continue the integration.
    166 
    167    * <p>This method is called after the step handler has returned and
    168    * before the next step is started, but only when {@link
    169    * #eventOccurred} has itself returned the {@link #RESET_STATE}
    170    * indicator. It allows the user to reset the state vector for the
    171    * next step, without perturbing the step handler of the finishing
    172    * step. If the {@link #eventOccurred} never returns the {@link
    173    * #RESET_STATE} indicator, this function will never be called, and it is
    174    * safe to leave its body empty.</p>
    175    *
    176    * @param t current value of the independent <i>time</i> variable
    177    * @param y array containing the current value of the state vector
    178    * the new state should be put in the same array
    179    * @exception EventException if the state cannot be reseted
    180    */
    181   void resetState(double t, double[] y) throws EventException;
    182 
    183 }
    184