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 }