* @return True if it is OK to fire.
*/
private boolean _prefireWithEnclosingNonContinuousDirector()
throws IllegalActionException {
CompositeActor container = (CompositeActor) getContainer();
Director executiveDirector = ((Actor) container).getExecutiveDirector();
// Check the enclosing model time against the local model time.
Time outTime = executiveDirector.getModelTime();
int comparison = _currentTime.compareTo(outTime);
if (comparison > 0) {
// Local current time exceeds that of the environment.
// We need to roll back. Make sure this is allowable.
if (!_commitIsPending) {
throw new IllegalActionException(this, "The model time of "
+ container.getFullName()
+ " is greater than the environment time. "
+ "Environment: " + outTime
+ ", the model time (iteration begin time): "
+ _currentTime);
}
// If we get here, local time exceeds the environment time
// and we have speculatively executed up to that local time.
// But now, we cannot commit that execution because an unexpected
// event has occurred. Instead, we have to re-do the integration
// with a smaller step size that brings us up to the current
// environment time.
// NOTE: This depends on the property that if an integration
// step with a larger step size was successful and produced
// no events, then an integration step with this now smaller
// step size will also be successful and produce no events.
_currentStepSize = outTime.subtract(_iterationBeginTime)
.getDoubleValue();
// If the step size is now negative, then we are trying
// to roll back too far.
if (_currentStepSize < 0.0) {
throw new IllegalActionException(this,
"Attempting to roll back time from "
+ _iterationBeginTime + " to " + outTime
+ ", but state has been committed.");
}
rollBackToCommittedState();
fire();
// It is safe to commit if we assume that the environment
// will not roll back time, and that it is not iterating to
// a fixed point. FIXME: Is this assumption right?
// If the enclosing director is a FixedPointDirector,
// there may inputs that are unknown! Perhaps the composite
// actor prefire() returns false if there unknown inputs?
_commit();
_commitIsPending = false;
} else if (comparison == 0 && _commitIsPending) {
// If we have a pending commit and current time matches the environment
// time, then perform the commit now.
_commitIsPending = false;
boolean result = _commit();
if (result == false) {
// The commit returned false, which means that either all
// actors return false in postfire or if we have reached the
// stop time. In this case, we should not execute further,
// so prefire() should return false.
// FIXME: Actually, postfire() should return false.
// Also, why do the other branches of the if ignore
// the return value of _commit()?
return false;
}
} else if (comparison < 0
&& executiveDirector != _enclosingContinuousDirector()) {
// Local current time is behind environment time, so
// We must be inside a modal model and have been
// disabled at the time that the commit
// would be effective. Cancel any pending commit.
if (_commitIsPending) {
_commitIsPending = false;
rollBackToCommittedState();
}
// Force current time to match the environment time, and treat
// this as if were were starting again in initialize().
// This ensures that actors like plotters will be postfired at
// the current time.
// FIXME: How do we know that that time matches the
// time at which the commit occurred?
// Shouldn't this be checked?
_currentTime = outTime;
if (_debugging) {
_debug("----- Setting current time to match enclosing non-ContinuousDirector: "
+ _currentTime);
}
_currentStepSize = 0.0;
}
// Adjust the step size to
// make sure the time does not exceed the next iteration
// time of the environment during this next integration step.
Time environmentNextIterationTime = executiveDirector
.getModelNextIterationTime();
Time localTargetTime = _iterationBeginTime.add(_currentStepSize);
if (environmentNextIterationTime.compareTo(localTargetTime) < 0) {
_currentStepSize = environmentNextIterationTime.subtract(
_currentTime).getDoubleValue();