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
18package org.apache.commons.math.ode.events;
19
20import java.util.ArrayList;
21import java.util.Collection;
22import java.util.Collections;
23import java.util.List;
24
25import org.apache.commons.math.ConvergenceException;
26import org.apache.commons.math.ode.DerivativeException;
27import org.apache.commons.math.ode.IntegratorException;
28import org.apache.commons.math.ode.sampling.StepInterpolator;
29
30/** This class manages several {@link EventHandler event handlers} during integration.
31 *
32 * @see EventHandler
33 * @see EventState
34 * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $
35 * @since 1.2
36 * @deprecated as of 2.2, this class is not used anymore
37 */
38@Deprecated
39public class CombinedEventsManager {
40
41    /** Events states. */
42    private final List<EventState> states;
43
44    /** First active event. */
45    private EventState first;
46
47    /** Initialization indicator. */
48    private boolean initialized;
49
50    /** Simple constructor.
51     * Create an empty manager
52     */
53    public CombinedEventsManager() {
54        states      = new ArrayList<EventState>();
55        first       = null;
56        initialized = false;
57    }
58
59    /** Add an events handler.
60     * @param handler event handler
61     * @param maxCheckInterval maximal time interval between events
62     * checks (this interval prevents missing sign changes in
63     * case the integration steps becomes very large)
64     * @param convergence convergence threshold in the event time search
65     * @param maxIterationCount upper limit of the iteration count in
66     * the event time search
67     * @see #getEventsHandlers()
68     * @see #clearEventsHandlers()
69     */
70    public void addEventHandler(final EventHandler handler, final double maxCheckInterval,
71                                final double convergence, final int maxIterationCount) {
72        states.add(new EventState(handler, maxCheckInterval,
73                                  convergence, maxIterationCount));
74    }
75
76    /** Get all the events handlers that have been added to the manager.
77     * @return an unmodifiable collection of the added event handlers
78     * @see #addEventHandler(EventHandler, double, double, int)
79     * @see #clearEventsHandlers()
80     * @see #getEventsStates()
81     */
82    public Collection<EventHandler> getEventsHandlers() {
83        final List<EventHandler> list = new ArrayList<EventHandler>();
84        for (EventState state : states) {
85            list.add(state.getEventHandler());
86        }
87        return Collections.unmodifiableCollection(list);
88    }
89
90    /** Remove all the events handlers that have been added to the manager.
91     * @see #addEventHandler(EventHandler, double, double, int)
92     * @see #getEventsHandlers()
93     */
94    public void clearEventsHandlers() {
95        states.clear();
96    }
97
98    /** Get all the events state wrapping the handlers that have been added to the manager.
99     * @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}
250