| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.commons.math.ode.events; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.apache.commons.math.ConvergenceException; |
| import org.apache.commons.math.ode.DerivativeException; |
| import org.apache.commons.math.ode.IntegratorException; |
| import org.apache.commons.math.ode.sampling.StepInterpolator; |
| |
| /** This class manages several {@link EventHandler event handlers} during integration. |
| * |
| * @see EventHandler |
| * @see EventState |
| * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $ |
| * @since 1.2 |
| * @deprecated as of 2.2, this class is not used anymore |
| */ |
| @Deprecated |
| public class CombinedEventsManager { |
| |
| /** Events states. */ |
| private final List<EventState> states; |
| |
| /** First active event. */ |
| private EventState first; |
| |
| /** Initialization indicator. */ |
| private boolean initialized; |
| |
| /** Simple constructor. |
| * Create an empty manager |
| */ |
| public CombinedEventsManager() { |
| states = new ArrayList<EventState>(); |
| first = null; |
| initialized = false; |
| } |
| |
| /** Add an events handler. |
| * @param handler event handler |
| * @param maxCheckInterval maximal time interval between events |
| * checks (this interval prevents missing sign changes in |
| * case the integration steps becomes very large) |
| * @param convergence convergence threshold in the event time search |
| * @param maxIterationCount upper limit of the iteration count in |
| * the event time search |
| * @see #getEventsHandlers() |
| * @see #clearEventsHandlers() |
| */ |
| public void addEventHandler(final EventHandler handler, final double maxCheckInterval, |
| final double convergence, final int maxIterationCount) { |
| states.add(new EventState(handler, maxCheckInterval, |
| convergence, maxIterationCount)); |
| } |
| |
| /** Get all the events handlers that have been added to the manager. |
| * @return an unmodifiable collection of the added event handlers |
| * @see #addEventHandler(EventHandler, double, double, int) |
| * @see #clearEventsHandlers() |
| * @see #getEventsStates() |
| */ |
| public Collection<EventHandler> getEventsHandlers() { |
| final List<EventHandler> list = new ArrayList<EventHandler>(); |
| for (EventState state : states) { |
| list.add(state.getEventHandler()); |
| } |
| return Collections.unmodifiableCollection(list); |
| } |
| |
| /** Remove all the events handlers that have been added to the manager. |
| * @see #addEventHandler(EventHandler, double, double, int) |
| * @see #getEventsHandlers() |
| */ |
| public void clearEventsHandlers() { |
| states.clear(); |
| } |
| |
| /** Get all the events state wrapping the handlers that have been added to the manager. |
| * @return a collection of the events states |
| * @see #getEventsHandlers() |
| */ |
| public Collection<EventState> getEventsStates() { |
| return states; |
| } |
| |
| /** Check if the manager does not manage any event handlers. |
| * @return true if manager is empty |
| */ |
| public boolean isEmpty() { |
| return states.isEmpty(); |
| } |
| |
| /** Evaluate the impact of the proposed step on all managed |
| * event handlers. |
| * @param interpolator step interpolator for the proposed step |
| * @return true if at least one event handler triggers an event |
| * before the end of the proposed step (this implies the step should |
| * be rejected) |
| * @exception DerivativeException if the interpolator fails to |
| * compute the function somewhere within the step |
| * @exception IntegratorException if an event cannot be located |
| */ |
| public boolean evaluateStep(final StepInterpolator interpolator) |
| throws DerivativeException, IntegratorException { |
| |
| try { |
| |
| first = null; |
| if (states.isEmpty()) { |
| // there is nothing to do, return now to avoid setting the |
| // interpolator time (and hence avoid unneeded calls to the |
| // user function due to interpolator finalization) |
| return false; |
| } |
| |
| if (! initialized) { |
| |
| // initialize the events states |
| for (EventState state : states) { |
| state.reinitializeBegin(interpolator); |
| } |
| |
| initialized = true; |
| |
| } |
| |
| // check events occurrence |
| for (EventState state : states) { |
| |
| if (state.evaluateStep(interpolator)) { |
| if (first == null) { |
| first = state; |
| } else { |
| if (interpolator.isForward()) { |
| if (state.getEventTime() < first.getEventTime()) { |
| first = state; |
| } |
| } else { |
| if (state.getEventTime() > first.getEventTime()) { |
| first = state; |
| } |
| } |
| } |
| } |
| |
| } |
| |
| return first != null; |
| |
| } catch (EventException se) { |
| final Throwable cause = se.getCause(); |
| if ((cause != null) && (cause instanceof DerivativeException)) { |
| throw (DerivativeException) cause; |
| } |
| throw new IntegratorException(se); |
| } catch (ConvergenceException ce) { |
| throw new IntegratorException(ce); |
| } |
| |
| } |
| |
| /** Get the occurrence time of the first event triggered in the |
| * last evaluated step. |
| * @return occurrence time of the first event triggered in the last |
| * evaluated step, or </code>Double.NaN</code> if no event is |
| * triggered |
| */ |
| public double getEventTime() { |
| return (first == null) ? Double.NaN : first.getEventTime(); |
| } |
| |
| /** Inform the event handlers that the step has been accepted |
| * by the integrator. |
| * @param t value of the independent <i>time</i> variable at the |
| * end of the step |
| * @param y array containing the current value of the state vector |
| * at the end of the step |
| * @exception IntegratorException if the value of one of the |
| * events states cannot be evaluated |
| */ |
| public void stepAccepted(final double t, final double[] y) |
| throws IntegratorException { |
| try { |
| for (EventState state : states) { |
| state.stepAccepted(t, y); |
| } |
| } catch (EventException se) { |
| throw new IntegratorException(se); |
| } |
| } |
| |
| /** Check if the integration should be stopped at the end of the |
| * current step. |
| * @return true if the integration should be stopped |
| */ |
| public boolean stop() { |
| for (EventState state : states) { |
| if (state.stop()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** Let the event handlers reset the state if they want. |
| * @param t value of the independent <i>time</i> variable at the |
| * beginning of the next step |
| * @param y array were to put the desired state vector at the beginning |
| * of the next step |
| * @return true if the integrator should reset the derivatives too |
| * @exception IntegratorException if one of the events states |
| * that should reset the state fails to do it |
| */ |
| public boolean reset(final double t, final double[] y) |
| throws IntegratorException { |
| try { |
| boolean resetDerivatives = false; |
| for (EventState state : states) { |
| if (state.reset(t, y)) { |
| resetDerivatives = true; |
| } |
| } |
| return resetDerivatives; |
| } catch (EventException se) { |
| throw new IntegratorException(se); |
| } |
| } |
| |
| } |