    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    }