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 import java.util.ArrayList; 21 import java.util.Collection; 22 import java.util.Collections; 23 import java.util.List; 24 25 import org.apache.commons.math.ConvergenceException; 26 import org.apache.commons.math.ode.DerivativeException; 27 import org.apache.commons.math.ode.IntegratorException; 28 import 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 fvr. 2011) $ 35 * @since 1.2 36 * @deprecated as of 2.2, this class is not used anymore 37 */ 38 @Deprecated 39 public 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