in commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/ode/AbstractFieldIntegrator.java [292:393]
protected FieldODEStateAndDerivative<T> acceptStep(final AbstractFieldStepInterpolator<T> interpolator,
final T tEnd)
throws MaxCountExceededException, DimensionMismatchException, NoBracketingException {
FieldODEStateAndDerivative<T> previousState = interpolator.getGlobalPreviousState();
final FieldODEStateAndDerivative<T> currentState = interpolator.getGlobalCurrentState();
// initialize the events states if needed
if (! statesInitialized) {
for (FieldEventState<T> state : eventsStates) {
state.reinitializeBegin(interpolator);
}
statesInitialized = true;
}
// search for next events that may occur during the step
final int orderingSign = interpolator.isForward() ? +1 : -1;
SortedSet<FieldEventState<T>> occurringEvents = new TreeSet<>(new Comparator<FieldEventState<T>>() {
/** {@inheritDoc} */
@Override
public int compare(FieldEventState<T> es0, FieldEventState<T> es1) {
return orderingSign * Double.compare(es0.getEventTime().getReal(), es1.getEventTime().getReal());
}
});
for (final FieldEventState<T> state : eventsStates) {
if (state.evaluateStep(interpolator)) {
// the event occurs during the current step
occurringEvents.add(state);
}
}
AbstractFieldStepInterpolator<T> restricted = interpolator;
while (!occurringEvents.isEmpty()) {
// handle the chronologically first event
final Iterator<FieldEventState<T>> iterator = occurringEvents.iterator();
final FieldEventState<T> currentEvent = iterator.next();
iterator.remove();
// get state at event time
final FieldODEStateAndDerivative<T> eventState = restricted.getInterpolatedState(currentEvent.getEventTime());
// restrict the interpolator to the first part of the step, up to the event
restricted = restricted.restrictStep(previousState, eventState);
// advance all event states to current time
for (final FieldEventState<T> state : eventsStates) {
state.stepAccepted(eventState);
isLastStep = isLastStep || state.stop();
}
// handle the first part of the step, up to the event
for (final FieldStepHandler<T> handler : stepHandlers) {
handler.handleStep(restricted, isLastStep);
}
if (isLastStep) {
// the event asked to stop integration
return eventState;
}
FieldODEState<T> newState = null;
resetOccurred = false;
for (final FieldEventState<T> state : eventsStates) {
newState = state.reset(eventState);
if (newState != null) {
// some event handler has triggered changes that
// invalidate the derivatives, we need to recompute them
final T[] y = equations.getMapper().mapState(newState);
final T[] yDot = computeDerivatives(newState.getTime(), y);
resetOccurred = true;
return equations.getMapper().mapStateAndDerivative(newState.getTime(), y, yDot);
}
}
// prepare handling of the remaining part of the step
previousState = eventState;
restricted = restricted.restrictStep(eventState, currentState);
// check if the same event occurs again in the remaining part of the step
if (currentEvent.evaluateStep(restricted)) {
// the event occurs during the current step
occurringEvents.add(currentEvent);
}
}
// last part of the step, after the last event
for (final FieldEventState<T> state : eventsStates) {
state.stepAccepted(currentState);
isLastStep = isLastStep || state.stop();
}
isLastStep = isLastStep || currentState.getTime().subtract(tEnd).abs().getReal() <= JdkMath.ulp(tEnd.getReal());
// handle the remaining part of the step, after all events if any
for (FieldStepHandler<T> handler : stepHandlers) {
handler.handleStep(restricted, isLastStep);
}
return currentState;
}