1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math.ode;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23
24 import org.apache.commons.math.MaxEvaluationsExceededException;
25 import org.apache.commons.math.ode.events.CombinedEventsManager;
26 import org.apache.commons.math.ode.events.EventHandler;
27 import org.apache.commons.math.ode.events.EventState;
28 import org.apache.commons.math.ode.sampling.StepHandler;
29
30
31
32
33
34
35 public abstract class AbstractIntegrator implements FirstOrderIntegrator {
36
37
38
39 private final String name;
40
41
42 private int maxEvaluations;
43
44
45 private int evaluations;
46
47
48 private transient FirstOrderDifferentialEquations equations;
49
50
51 protected Collection<StepHandler> stepHandlers;
52
53
54 protected double stepStart;
55
56
57 protected double stepSize;
58
59
60 protected CombinedEventsManager eventsHandlersManager;
61
62
63
64
65 public AbstractIntegrator(final String name) {
66 this.name = name;
67 stepHandlers = new ArrayList<StepHandler>();
68 stepStart = Double.NaN;
69 stepSize = Double.NaN;
70 eventsHandlersManager = new CombinedEventsManager();
71 setMaxEvaluations(-1);
72 resetEvaluations();
73 }
74
75
76
77 protected AbstractIntegrator() {
78 this(null);
79 }
80
81
82 public String getName() {
83 return name;
84 }
85
86
87 public void addStepHandler(final StepHandler handler) {
88 stepHandlers.add(handler);
89 }
90
91
92 public Collection<StepHandler> getStepHandlers() {
93 return Collections.unmodifiableCollection(stepHandlers);
94 }
95
96
97 public void clearStepHandlers() {
98 stepHandlers.clear();
99 }
100
101
102 public void addEventHandler(final EventHandler function,
103 final double maxCheckInterval,
104 final double convergence,
105 final int maxIterationCount) {
106 eventsHandlersManager.addEventHandler(function, maxCheckInterval,
107 convergence, maxIterationCount);
108 }
109
110
111 public Collection<EventHandler> getEventHandlers() {
112 return eventsHandlersManager.getEventsHandlers();
113 }
114
115
116 public void clearEventHandlers() {
117 eventsHandlersManager.clearEventsHandlers();
118 }
119
120
121
122
123 protected boolean requiresDenseOutput() {
124 for (StepHandler handler : stepHandlers) {
125 if (handler.requiresDenseOutput()) {
126 return true;
127 }
128 }
129 return false;
130 }
131
132
133 public double getCurrentStepStart() {
134 return stepStart;
135 }
136
137
138 public double getCurrentSignedStepsize() {
139 return stepSize;
140 }
141
142
143 public void setMaxEvaluations(int maxEvaluations) {
144 this.maxEvaluations = (maxEvaluations < 0) ? Integer.MAX_VALUE : maxEvaluations;
145 }
146
147
148 public int getMaxEvaluations() {
149 return maxEvaluations;
150 }
151
152
153 public int getEvaluations() {
154 return evaluations;
155 }
156
157
158
159 protected void resetEvaluations() {
160 evaluations = 0;
161 }
162
163
164
165
166
167 protected void setEquations(final FirstOrderDifferentialEquations equations) {
168 this.equations = equations;
169 }
170
171
172
173
174
175
176
177
178 public void computeDerivatives(final double t, final double[] y, final double[] yDot)
179 throws DerivativeException {
180 if (++evaluations > maxEvaluations) {
181 throw new DerivativeException(new MaxEvaluationsExceededException(maxEvaluations));
182 }
183 equations.computeDerivatives(t, y, yDot);
184 }
185
186
187
188
189
190
191
192
193
194 protected void sanityChecks(final FirstOrderDifferentialEquations equations,
195 final double t0, final double[] y0,
196 final double t, final double[] y)
197 throws IntegratorException {
198
199 if (equations.getDimension() != y0.length) {
200 throw new IntegratorException(
201 "dimensions mismatch: ODE problem has dimension {0}," +
202 " initial state vector has dimension {1}",
203 equations.getDimension(), y0.length);
204 }
205
206 if (equations.getDimension() != y.length) {
207 throw new IntegratorException(
208 "dimensions mismatch: ODE problem has dimension {0}," +
209 " final state vector has dimension {1}",
210 equations.getDimension(), y.length);
211 }
212
213 if (Math.abs(t - t0) <= 1.0e-12 * Math.max(Math.abs(t0), Math.abs(t))) {
214 throw new IntegratorException(
215 "too small integration interval: length = {0}",
216 Math.abs(t - t0));
217 }
218
219 }
220
221
222
223
224
225
226
227
228
229
230
231 protected CombinedEventsManager addEndTimeChecker(final double startTime,
232 final double endTime,
233 final CombinedEventsManager manager) {
234 CombinedEventsManager newManager = new CombinedEventsManager();
235 for (final EventState state : manager.getEventsStates()) {
236 newManager.addEventHandler(state.getEventHandler(),
237 state.getMaxCheckInterval(),
238 state.getConvergence(),
239 state.getMaxIterationCount());
240 }
241 newManager.addEventHandler(new EndTimeChecker(endTime),
242 Double.POSITIVE_INFINITY,
243 Math.ulp(Math.max(Math.abs(startTime), Math.abs(endTime))),
244 100);
245 return newManager;
246 }
247
248
249 private static class EndTimeChecker implements EventHandler {
250
251
252 private final double endTime;
253
254
255
256
257 public EndTimeChecker(final double endTime) {
258 this.endTime = endTime;
259 }
260
261
262 public int eventOccurred(double t, double[] y, boolean increasing) {
263 return STOP;
264 }
265
266
267 public double g(double t, double[] y) {
268 return t - endTime;
269 }
270
271
272 public void resetState(double t, double[] y) {
273 }
274
275 }
276
277 }