001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.ode.events;
019    
020    import org.apache.commons.math.ode.FirstOrderDifferentialEquations;
021    import org.apache.commons.math.ode.sampling.StepHandler;
022    
023    /** This interface represents a handler for discrete events triggered
024     * during ODE integration.
025     *
026     * <p>Some events can be triggered at discrete times as an ODE problem
027     * is solved. These occurs for example when the integration process
028     * should be stopped as some state is reached (G-stop facility) when the
029     * precise date is unknown a priori, or when the derivatives have
030     * discontinuities, or simply when the user wants to monitor some
031     * states boundaries crossings.
032     * </p>
033     * 
034     * <p>These events are defined as occurring when a <code>g</code>
035     * switching function sign changes.</p>
036     *
037     * <p>Since events are only problem-dependent and are triggered by the
038     * independent <i>time</i> variable and the state vector, they can
039     * occur at virtually any time, unknown in advance. The integrators will
040     * take care to avoid sign changes inside the steps, they will reduce
041     * the step size when such an event is detected in order to put this
042     * event exactly at the end of the current step. This guarantees that
043     * step interpolation (which always has a one step scope) is relevant
044     * even in presence of discontinuities. This is independent from the
045     * stepsize control provided by integrators that monitor the local
046     * error (this event handling feature is available for all integrators,
047     * including fixed step ones).</p>
048     *
049     * @version $Revision: 785473 $ $Date: 2009-06-17 00:02:35 -0400 (Wed, 17 Jun 2009) $
050     * @since 1.2
051     */
052    
053    public interface EventHandler  {
054    
055      /** Stop indicator.
056       * <p>This value should be used as the return value of the {@link
057       * #eventOccurred eventOccurred} method when the integration should be
058       * stopped after the event ending the current step.</p>
059       */
060      public static final int STOP = 0;
061    
062      /** Reset state indicator.
063       * <p>This value should be used as the return value of the {@link
064       * #eventOccurred eventOccurred} method when the integration should
065       * go on after the event ending the current step, with a new state
066       * vector (which will be retrieved thanks to the {@link #resetState
067       * resetState} method).</p>
068       */
069      public static final int RESET_STATE = 1;
070    
071      /** Reset derivatives indicator.
072       * <p>This value should be used as the return value of the {@link
073       * #eventOccurred eventOccurred} method when the integration should
074       * go on after the event ending the current step, with a new derivatives
075       * vector (which will be retrieved thanks to the {@link
076       * FirstOrderDifferentialEquations#computeDerivatives} method).</p>
077       */
078      public static final int RESET_DERIVATIVES = 2;
079    
080      /** Continue indicator.
081       * <p>This value should be used as the return value of the {@link
082       * #eventOccurred eventOccurred} method when the integration should go
083       * on after the event ending the current step.</p>
084       */
085      public static final int CONTINUE = 3;
086    
087      /** Compute the value of the switching function.
088    
089       * <p>The discrete events are generated when the sign of this 
090       * switching function changes. The integrator will take care to change
091       * the stepsize in such a way these events occur exactly at step boundaries.
092       * The switching function must be continuous in its roots neighborhood
093       * (but not necessarily smooth), as the integrator will need to find its
094       * roots to locate precisely the events.</p>
095    
096       * @param t current value of the independent <i>time</i> variable
097       * @param y array containing the current value of the state vector
098       * @return value of the g switching function
099       * @exception EventException if the switching function cannot be evaluated
100       */
101      public double g(double t, double[] y) throws EventException;
102    
103      /** Handle an event and choose what to do next.
104    
105       * <p>This method is called when the integrator has accepted a step
106       * ending exactly on a sign change of the function, just before the
107       * step handler itself is called. It allows the user to update his
108       * internal data to acknowledge the fact the event has been handled
109       * (for example setting a flag in the {@link
110       * FirstOrderDifferentialEquations differential equations} to switch
111       * the derivatives computation in case of discontinuity), or to
112       * direct the integrator to either stop or continue integration,
113       * possibly with a reset state or derivatives.</p>
114    
115       * <ul>
116       *   <li>if {@link #STOP} is returned, the step handler will be called
117       *   with the <code>isLast</code> flag of the {@link
118       *   StepHandler#handleStep handleStep} method set to true and the
119       *   integration will be stopped,</li>
120       *   <li>if {@link #RESET_STATE} is returned, the {@link #resetState
121       *   resetState} method will be called once the step handler has
122       *   finished its task, and the integrator will also recompute the
123       *   derivatives,</li>
124       *   <li>if {@link #RESET_DERIVATIVES} is returned, the integrator
125       *   will recompute the derivatives,
126       *   <li>if {@link #CONTINUE} is returned, no specific action will
127       *   be taken (apart from having called this method) and integration
128       *   will continue.</li>
129       * </ul>
130    
131       * @param t current value of the independent <i>time</i> variable
132       * @param y array containing the current value of the state vector
133       * @param increasing if true, the value of the switching function increases
134       * when times increases around event (note that increase is measured with respect
135       * to physical time, not with respect to integration which may go backward in time)
136       * @return indication of what the integrator should do next, this
137       * value must be one of {@link #STOP}, {@link #RESET_STATE},
138       * {@link #RESET_DERIVATIVES} or {@link #CONTINUE}
139       * @exception EventException if the event occurrence triggers an error
140       */
141      public int eventOccurred(double t, double[] y, boolean increasing) throws EventException;
142      
143      /** Reset the state prior to continue the integration.
144    
145       * <p>This method is called after the step handler has returned and
146       * before the next step is started, but only when {@link
147       * #eventOccurred} has itself returned the {@link #RESET_STATE}
148       * indicator. It allows the user to reset the state vector for the
149       * next step, without perturbing the step handler of the finishing
150       * step. If the {@link #eventOccurred} never returns the {@link
151       * #RESET_STATE} indicator, this function will never be called, and it is
152       * safe to leave its body empty.</p>
153    
154       * @param t current value of the independent <i>time</i> variable
155       * @param y array containing the current value of the state vector
156       * the new state should be put in the same array
157       * @exception EventException if the state cannot be reseted
158       */
159      public void resetState(double t, double[] y) throws EventException;
160    
161    }