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 java.util.ArrayList;
021    import java.util.Collection;
022    import java.util.Collections;
023    import java.util.List;
024    
025    import org.apache.commons.math.ConvergenceException;
026    import org.apache.commons.math.ode.DerivativeException;
027    import org.apache.commons.math.ode.IntegratorException;
028    import org.apache.commons.math.ode.sampling.StepInterpolator;
029    
030    /** This class manages several {@link EventHandler event handlers} during integration.
031     *
032     * @see EventHandler
033     * @see EventState
034     * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 f??vr. 2011) $
035     * @since 1.2
036     * @deprecated as of 2.2, this class is not used anymore
037     */
038    @Deprecated
039    public class CombinedEventsManager {
040    
041        /** Events states. */
042        private final List<EventState> states;
043    
044        /** First active event. */
045        private EventState first;
046    
047        /** Initialization indicator. */
048        private boolean initialized;
049    
050        /** Simple constructor.
051         * Create an empty manager
052         */
053        public CombinedEventsManager() {
054            states      = new ArrayList<EventState>();
055            first       = null;
056            initialized = false;
057        }
058    
059        /** Add an events handler.
060         * @param handler event handler
061         * @param maxCheckInterval maximal time interval between events
062         * checks (this interval prevents missing sign changes in
063         * case the integration steps becomes very large)
064         * @param convergence convergence threshold in the event time search
065         * @param maxIterationCount upper limit of the iteration count in
066         * the event time search
067         * @see #getEventsHandlers()
068         * @see #clearEventsHandlers()
069         */
070        public void addEventHandler(final EventHandler handler, final double maxCheckInterval,
071                                    final double convergence, final int maxIterationCount) {
072            states.add(new EventState(handler, maxCheckInterval,
073                                      convergence, maxIterationCount));
074        }
075    
076        /** Get all the events handlers that have been added to the manager.
077         * @return an unmodifiable collection of the added event handlers
078         * @see #addEventHandler(EventHandler, double, double, int)
079         * @see #clearEventsHandlers()
080         * @see #getEventsStates()
081         */
082        public Collection<EventHandler> getEventsHandlers() {
083            final List<EventHandler> list = new ArrayList<EventHandler>();
084            for (EventState state : states) {
085                list.add(state.getEventHandler());
086            }
087            return Collections.unmodifiableCollection(list);
088        }
089    
090        /** Remove all the events handlers that have been added to the manager.
091         * @see #addEventHandler(EventHandler, double, double, int)
092         * @see #getEventsHandlers()
093         */
094        public void clearEventsHandlers() {
095            states.clear();
096        }
097    
098        /** Get all the events state wrapping the handlers that have been added to the manager.
099         * @return a collection of the events states
100         * @see #getEventsHandlers()
101         */
102        public Collection<EventState> getEventsStates() {
103            return states;
104        }
105    
106        /** Check if the manager does not manage any event handlers.
107         * @return true if manager is empty
108         */
109        public boolean isEmpty() {
110            return states.isEmpty();
111        }
112    
113        /** Evaluate the impact of the proposed step on all managed
114         * event handlers.
115         * @param interpolator step interpolator for the proposed step
116         * @return true if at least one event handler triggers an event
117         * before the end of the proposed step (this implies the step should
118         * be rejected)
119         * @exception DerivativeException if the interpolator fails to
120         * compute the function somewhere within the step
121         * @exception IntegratorException if an event cannot be located
122         */
123        public boolean evaluateStep(final StepInterpolator interpolator)
124        throws DerivativeException, IntegratorException {
125    
126            try {
127    
128                first = null;
129                if (states.isEmpty()) {
130                    // there is nothing to do, return now to avoid setting the
131                    // interpolator time (and hence avoid unneeded calls to the
132                    // user function due to interpolator finalization)
133                    return false;
134                }
135    
136                if (! initialized) {
137    
138                    // initialize the events states
139                    for (EventState state : states) {
140                        state.reinitializeBegin(interpolator);
141                    }
142    
143                    initialized = true;
144    
145                }
146    
147                // check events occurrence
148                for (EventState state : states) {
149    
150                    if (state.evaluateStep(interpolator)) {
151                        if (first == null) {
152                            first = state;
153                        } else {
154                            if (interpolator.isForward()) {
155                                if (state.getEventTime() < first.getEventTime()) {
156                                    first = state;
157                                }
158                            } else {
159                                if (state.getEventTime() > first.getEventTime()) {
160                                    first = state;
161                                }
162                            }
163                        }
164                    }
165    
166                }
167    
168                return first != null;
169    
170            } catch (EventException se) {
171                final Throwable cause = se.getCause();
172                if ((cause != null) && (cause instanceof DerivativeException)) {
173                    throw (DerivativeException) cause;
174                }
175                throw new IntegratorException(se);
176            } catch (ConvergenceException ce) {
177                throw new IntegratorException(ce);
178            }
179    
180        }
181    
182        /** Get the occurrence time of the first event triggered in the
183         * last evaluated step.
184         * @return occurrence time of the first event triggered in the last
185         * evaluated step, or </code>Double.NaN</code> if no event is
186         * triggered
187         */
188        public double getEventTime() {
189            return (first == null) ? Double.NaN : first.getEventTime();
190        }
191    
192        /** Inform the event handlers that the step has been accepted
193         * by the integrator.
194         * @param t value of the independent <i>time</i> variable at the
195         * end of the step
196         * @param y array containing the current value of the state vector
197         * at the end of the step
198         * @exception IntegratorException if the value of one of the
199         * events states cannot be evaluated
200         */
201        public void stepAccepted(final double t, final double[] y)
202        throws IntegratorException {
203            try {
204                for (EventState state : states) {
205                    state.stepAccepted(t, y);
206                }
207            } catch (EventException se) {
208                throw new IntegratorException(se);
209            }
210        }
211    
212        /** Check if the integration should be stopped at the end of the
213         * current step.
214         * @return true if the integration should be stopped
215         */
216        public boolean stop() {
217            for (EventState state : states) {
218                if (state.stop()) {
219                    return true;
220                }
221            }
222            return false;
223        }
224    
225        /** Let the event handlers reset the state if they want.
226         * @param t value of the independent <i>time</i> variable at the
227         * beginning of the next step
228         * @param y array were to put the desired state vector at the beginning
229         * of the next step
230         * @return true if the integrator should reset the derivatives too
231         * @exception IntegratorException if one of the events states
232         * that should reset the state fails to do it
233         */
234        public boolean reset(final double t, final double[] y)
235            throws IntegratorException {
236            try {
237                boolean resetDerivatives = false;
238                for (EventState state : states) {
239                    if (state.reset(t, y)) {
240                        resetDerivatives = true;
241                    }
242                }
243                return resetDerivatives;
244            } catch (EventException se) {
245                throw new IntegratorException(se);
246            }
247        }
248    
249    }