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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
18
package org.apache.commons.math.ode;
20
import org.apache.commons.math.ConvergenceException;
21
import org.apache.commons.math.FunctionEvaluationException;
23
import java.util.ArrayList;
24
import java.util.Iterator;
26
/** This class handles several {@link SwitchingFunction switching
27
* functions} during integration.
29
* @see SwitchingFunction
30
* @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
34
public class SwitchingFunctionsHandler {
36
/** Simple constructor.
37
* Create an empty handler
39
public SwitchingFunctionsHandler() {
40
functions = new ArrayList();
45
/** Add a switching function.
46
* @param function switching function
47
* @param maxCheckInterval maximal time interval between switching
48
* function checks (this interval prevents missing sign changes in
49
* case the integration steps becomes very large)
50
* @param convergence convergence threshold in the event time search
51
* @param maxIterationCount upper limit of the iteration count in
52
* the event time search
54
public void add(SwitchingFunction function, double maxCheckInterval,
55
double convergence, int maxIterationCount) {
56
functions.add(new SwitchState(function, maxCheckInterval,
57
convergence, maxIterationCount));
60
/** Check if the handler does not have any condition.
61
* @return true if handler is empty
63
public boolean isEmpty() {
64
return functions.isEmpty();
67
/** Evaluate the impact of the proposed step on all handled
68
* switching functions.
69
* @param interpolator step interpolator for the proposed step
70
* @return true if at least one switching function triggers an event
71
* before the end of the proposed step (this implies the step should
73
* @exception DerivativeException if the interpolator fails to
74
* compute the function somewhere within the step
75
* @exception IntegratorException if an event cannot be located
77
public boolean evaluateStep(StepInterpolator interpolator)
78
throws DerivativeException, IntegratorException {
83
if (functions.isEmpty()) {
84
// there is nothing to do, return now to avoid setting the
85
// interpolator time (and hence avoid unneeded calls to the
86
// user function due to interpolator finalization)
92
// initialize the switching functions
93
double t0 = interpolator.getPreviousTime();
94
interpolator.setInterpolatedTime(t0);
95
double [] y = interpolator.getInterpolatedState();
96
for (Iterator iter = functions.iterator(); iter.hasNext();) {
97
((SwitchState) iter.next()).reinitializeBegin(t0, y);
104
// check events occurrence
105
for (Iterator iter = functions.iterator(); iter.hasNext();) {
107
SwitchState state = (SwitchState) iter.next();
108
if (state.evaluateStep(interpolator)) {
112
if (interpolator.isForward()) {
113
if (state.getEventTime() < first.getEventTime()) {
117
if (state.getEventTime() > first.getEventTime()) {
126
return first != null;
128
} catch (FunctionEvaluationException fee) {
129
throw new IntegratorException(fee);
130
} catch (ConvergenceException ce) {
131
throw new IntegratorException(ce);
136
/** Get the occurrence time of the first event triggered in the
137
* last evaluated step.
138
* @return occurrence time of the first event triggered in the last
139
* evaluated step, or </code>Double.NaN</code> if no event is
142
public double getEventTime() {
143
return (first == null) ? Double.NaN : first.getEventTime();
146
/** Inform the switching functions that the step has been accepted
148
* @param t value of the independent <i>time</i> variable at the
150
* @param y array containing the current value of the state vector
151
* at the end of the step
152
* @exception IntegratorException if the value of one of the
153
* switching functions cannot be evaluated
155
public void stepAccepted(double t, double[] y)
156
throws IntegratorException {
158
for (Iterator iter = functions.iterator(); iter.hasNext();) {
159
((SwitchState) iter.next()).stepAccepted(t, y);
161
} catch (FunctionEvaluationException fee) {
162
throw new IntegratorException(fee);
166
/** Check if the integration should be stopped at the end of the
168
* @return true if the integration should be stopped
170
public boolean stop() {
171
for (Iterator iter = functions.iterator(); iter.hasNext();) {
172
if (((SwitchState) iter.next()).stop()) {
179
/** Let the switching functions reset the state if they want.
180
* @param t value of the independent <i>time</i> variable at the
181
* beginning of the next step
182
* @param y array were to put the desired state vector at the beginning
184
* @return true if the integrator should reset the derivatives too
186
public boolean reset(double t, double[] y) {
187
boolean resetDerivatives = false;
188
for (Iterator iter = functions.iterator(); iter.hasNext();) {
189
if (((SwitchState) iter.next()).reset(t, y)) {
190
resetDerivatives = true;
193
return resetDerivatives;
196
/** Switching functions. */
197
private ArrayList functions;
199
/** First active switching function. */
200
private SwitchState first;
202
/** Initialization indicator. */
203
private boolean initialized;