1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.ode;
24
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.Comparator;
28 import java.util.List;
29 import java.util.PriorityQueue;
30 import java.util.Queue;
31 import java.util.stream.Collectors;
32 import java.util.stream.Stream;
33
34 import org.hipparchus.exception.MathIllegalArgumentException;
35 import org.hipparchus.exception.MathIllegalStateException;
36 import org.hipparchus.ode.events.Action;
37 import org.hipparchus.ode.events.DetectorBasedEventState;
38 import org.hipparchus.ode.events.EventOccurrence;
39 import org.hipparchus.ode.events.EventState;
40 import org.hipparchus.ode.events.ODEEventDetector;
41 import org.hipparchus.ode.events.ODEStepEndHandler;
42 import org.hipparchus.ode.events.StepEndEventState;
43 import org.hipparchus.ode.sampling.AbstractODEStateInterpolator;
44 import org.hipparchus.ode.sampling.ODEStepHandler;
45 import org.hipparchus.util.FastMath;
46 import org.hipparchus.util.Incrementor;
47
48
49
50
51 public abstract class AbstractIntegrator implements ODEIntegrator {
52
53
54 private List<ODEStepHandler> stepHandlers;
55
56
57 private ODEStateAndDerivative stepStart;
58
59
60 private double stepSize;
61
62
63 private boolean isLastStep;
64
65
66 private boolean resetOccurred;
67
68
69 private List<DetectorBasedEventState> detectorBasedEventsStates;
70
71
72 private List<StepEndEventState> stepEndEventsStates;
73
74
75 private boolean statesInitialized;
76
77
78 private final String name;
79
80
81 private Incrementor evaluations;
82
83
84 private transient ExpandableODE equations;
85
86
87
88
89 protected AbstractIntegrator(final String name) {
90 this.name = name;
91 stepHandlers = new ArrayList<>();
92 stepStart = null;
93 stepSize = Double.NaN;
94 detectorBasedEventsStates = new ArrayList<>();
95 stepEndEventsStates = new ArrayList<>();
96 statesInitialized = false;
97 evaluations = new Incrementor();
98 }
99
100
101 @Override
102 public String getName() {
103 return name;
104 }
105
106
107 @Override
108 public void addStepHandler(final ODEStepHandler handler) {
109 stepHandlers.add(handler);
110 }
111
112
113 @Override
114 public List<ODEStepHandler> getStepHandlers() {
115 return Collections.unmodifiableList(stepHandlers);
116 }
117
118
119 @Override
120 public void clearStepHandlers() {
121 stepHandlers.clear();
122 }
123
124
125 @Override
126 public void addEventDetector(final ODEEventDetector detector) {
127 detectorBasedEventsStates.add(new DetectorBasedEventState(detector));
128 }
129
130
131 @Override
132 public List<ODEEventDetector> getEventDetectors() {
133 return detectorBasedEventsStates.stream().map(es -> es.getEventDetector()).collect(Collectors.toList());
134 }
135
136
137 @Override
138 public void clearEventDetectors() {
139 detectorBasedEventsStates.clear();
140 }
141
142
143 @Override
144 public void addStepEndHandler(ODEStepEndHandler handler) {
145 stepEndEventsStates.add(new StepEndEventState(handler));
146 }
147
148
149 @Override
150 public List<ODEStepEndHandler> getStepEndHandlers() {
151 return stepEndEventsStates.stream().map(es -> es.getHandler()).collect(Collectors.toList());
152 }
153
154
155 @Override
156 public void clearStepEndHandlers() {
157 stepEndEventsStates.clear();
158 }
159
160
161 @Override
162 public double getCurrentSignedStepsize() {
163 return stepSize;
164 }
165
166
167 @Override
168 public void setMaxEvaluations(int maxEvaluations) {
169 evaluations = evaluations.withMaximalCount((maxEvaluations < 0) ? Integer.MAX_VALUE : maxEvaluations);
170 }
171
172
173 @Override
174 public int getMaxEvaluations() {
175 return evaluations.getMaximalCount();
176 }
177
178
179 @Override
180 public int getEvaluations() {
181 return evaluations.getCount();
182 }
183
184
185
186
187
188
189
190
191
192 protected ODEStateAndDerivative initIntegration(final ExpandableODE eqn,
193 final ODEState s0, final double t) {
194
195 this.equations = eqn;
196 evaluations = evaluations.withCount(0);
197
198
199 eqn.init(s0, t);
200
201
202 final double t0 = s0.getTime();
203 final double[] y0 = s0.getCompleteState();
204 final double[] y0Dot = computeDerivatives(t0, y0);
205
206
207 final ODEStateAndDerivative s0WithDerivatives =
208 eqn.getMapper().mapStateAndDerivative(t0, y0, y0Dot);
209
210
211 detectorBasedEventsStates.stream().forEach(s -> {
212 s.init(s0WithDerivatives, t);
213 s.getEventDetector().getHandler().init(s0WithDerivatives, t, s.getEventDetector());
214 });
215
216
217 stepEndEventsStates.stream().forEach(s -> {
218 s.init(s0WithDerivatives, t);
219 s.getHandler().init(s0WithDerivatives, t);
220 });
221
222
223 for (ODEStepHandler handler : stepHandlers) {
224 handler.init(s0WithDerivatives, t);
225 }
226
227 setStateInitialized(false);
228
229 return s0WithDerivatives;
230
231 }
232
233
234
235
236 protected ExpandableODE getEquations() {
237 return equations;
238 }
239
240
241
242
243 protected Incrementor getEvaluationsCounter() {
244 return evaluations;
245 }
246
247
248
249
250
251
252
253
254
255
256 public double[] computeDerivatives(final double t, final double[] y)
257 throws MathIllegalArgumentException, MathIllegalStateException, NullPointerException {
258 evaluations.increment();
259 return equations.computeDerivatives(t, y);
260 }
261
262
263
264
265
266 protected void incrementEvaluations(final int nTimes) {
267 evaluations.increment(nTimes);
268 }
269
270
271
272
273
274
275
276 protected void setStateInitialized(final boolean stateInitialized) {
277 this.statesInitialized = stateInitialized;
278 }
279
280
281
282
283
284
285
286
287
288
289 protected ODEStateAndDerivative acceptStep(final AbstractODEStateInterpolator interpolator,
290 final double tEnd)
291 throws MathIllegalArgumentException, MathIllegalStateException {
292
293 ODEStateAndDerivative previousState = interpolator.getGlobalPreviousState();
294 final ODEStateAndDerivative currentState = interpolator.getGlobalCurrentState();
295 AbstractODEStateInterpolator restricted = interpolator;
296
297
298
299 if (!statesInitialized) {
300
301 detectorBasedEventsStates.stream().forEach(s -> s.reinitializeBegin(interpolator));
302 statesInitialized = true;
303 }
304
305
306 stepEndEventsStates.stream().forEach(s -> s.setStepEnd(currentState.getTime()));
307
308
309 final int orderingSign = interpolator.isForward() ? +1 : -1;
310 final Queue<EventState> occurringEvents = new PriorityQueue<>(new Comparator<EventState>() {
311
312 @Override
313 public int compare(final EventState es0, final EventState es1) {
314 return orderingSign * Double.compare(es0.getEventTime(), es1.getEventTime());
315 }
316 });
317
318 resetOccurred = false;
319 boolean doneWithStep = false;
320 resetEvents:
321 do {
322
323
324 occurringEvents.clear();
325 final AbstractODEStateInterpolator finalRestricted = restricted;
326 Stream.concat(detectorBasedEventsStates.stream(), stepEndEventsStates.stream()).
327 forEach(s -> { if (s.evaluateStep(finalRestricted)) {
328
329 occurringEvents.add(s);
330 }
331 });
332
333 do {
334
335 eventLoop:
336 while (!occurringEvents.isEmpty()) {
337
338
339 final EventState currentEvent = occurringEvents.poll();
340
341
342 ODEStateAndDerivative eventState = restricted.getInterpolatedState(currentEvent.getEventTime());
343
344
345 restricted = restricted.restrictStep(previousState, eventState);
346
347
348 for (final DetectorBasedEventState state : detectorBasedEventsStates) {
349 if (state != currentEvent && state.tryAdvance(eventState, interpolator)) {
350
351
352 occurringEvents.remove(state);
353
354 occurringEvents.add(state);
355
356 occurringEvents.add(currentEvent);
357 continue eventLoop;
358 }
359 }
360
361
362
363 for (final ODEStepHandler handler : stepHandlers) {
364 handler.handleStep(restricted);
365 }
366
367
368 final EventOccurrence occurrence = currentEvent.doEvent(eventState);
369 final Action action = occurrence.getAction();
370 isLastStep = action == Action.STOP;
371
372 if (isLastStep) {
373
374
375
376
377 final ODEStateAndDerivative savedState = eventState;
378 eventState = interpolator.getInterpolatedState(occurrence.getStopTime());
379 restricted = interpolator.restrictStep(savedState, eventState);
380
381
382 for (final ODEStepHandler handler : stepHandlers) {
383 handler.handleStep(restricted);
384 handler.finish(restricted.getCurrentState());
385 }
386
387 }
388
389 if (isLastStep) {
390
391 return eventState;
392 }
393
394 if (action == Action.RESET_DERIVATIVES || action == Action.RESET_STATE) {
395
396
397 final ODEState newState = occurrence.getNewState();
398 final double[] y = newState.getCompleteState();
399 final double[] yDot = computeDerivatives(newState.getTime(), y);
400 resetOccurred = true;
401 return equations.getMapper().mapStateAndDerivative(newState.getTime(), y, yDot);
402 }
403
404
405
406 previousState = eventState;
407 restricted = restricted.restrictStep(eventState, currentState);
408
409 if (action == Action.RESET_EVENTS) {
410 continue resetEvents;
411 }
412
413
414
415 if (currentEvent.evaluateStep(restricted)) {
416
417 occurringEvents.add(currentEvent);
418 }
419
420 }
421
422
423
424
425
426
427
428
429 for (final DetectorBasedEventState state : detectorBasedEventsStates) {
430 if (state.tryAdvance(currentState, interpolator)) {
431 occurringEvents.add(state);
432 }
433 }
434
435 } while (!occurringEvents.isEmpty());
436
437 doneWithStep = true;
438 } while (!doneWithStep);
439
440 isLastStep = isLastStep || FastMath.abs(currentState.getTime() - tEnd) < FastMath.ulp(tEnd);
441
442
443 for (ODEStepHandler handler : stepHandlers) {
444 handler.handleStep(restricted);
445 if (isLastStep) {
446 handler.finish(restricted.getCurrentState());
447 }
448 }
449
450 return currentState;
451
452 }
453
454
455
456
457
458
459
460
461 protected void sanityChecks(final ODEState initialState, final double t)
462 throws MathIllegalArgumentException {
463
464 final double threshold = 1000 * FastMath.ulp(FastMath.max(FastMath.abs(initialState.getTime()),
465 FastMath.abs(t)));
466 final double dt = FastMath.abs(initialState.getTime() - t);
467 if (dt < threshold) {
468 throw new MathIllegalArgumentException(LocalizedODEFormats.TOO_SMALL_INTEGRATION_INTERVAL,
469 dt, threshold, false);
470 }
471
472 }
473
474
475
476
477 protected boolean resetOccurred() {
478 return resetOccurred;
479 }
480
481
482
483
484 protected void setStepSize(final double stepSize) {
485 this.stepSize = stepSize;
486 }
487
488
489
490
491 protected double getStepSize() {
492 return stepSize;
493 }
494
495
496
497 protected void setStepStart(final ODEStateAndDerivative stepStart) {
498 this.stepStart = stepStart;
499 }
500
501
502 @Override
503 public ODEStateAndDerivative getStepStart() {
504 return stepStart;
505 }
506
507
508
509
510 protected void setIsLastStep(final boolean isLastStep) {
511 this.isLastStep = isLastStep;
512 }
513
514
515
516
517 protected boolean isLastStep() {
518 return isLastStep;
519 }
520
521 }