예제 #1
0
  /**
   * Initialize the integrator. Check for the existence of a director and an ODE solver. Set the
   * state to the value given by <i>initialState</i>.
   *
   * @exception IllegalActionException If there is no director, or the director has no ODE solver,
   *     or the initialState parameter does not contain a valid token, or the superclass throws it.
   */
  public void initialize() throws IllegalActionException {
    ContinuousDirector dir = (ContinuousDirector) getDirector();

    if (dir == null) {
      throw new IllegalActionException(this, " no director available");
    }

    ContinuousODESolver solver = dir._getODESolver();

    if (solver == null) {
      throw new IllegalActionException(this, " no ODE solver available");
    }

    super.initialize();
    _lastRound = -1;
    _tentativeState = ((DoubleToken) initialState.getToken()).doubleValue();
    _state = _tentativeState;

    if (_debugging) {
      _debug("Initialize: initial state = " + _tentativeState);
    }

    // The number of auxiliary variables that are used depends on
    // the solver.
    int n = solver.getIntegratorAuxVariableCount();
    if ((_auxVariables == null) || (_auxVariables.length != n)) {
      _auxVariables = new double[n];
    }
  }
예제 #2
0
  /**
   * If the value at the <i>derivative</i> port is known, and the current step size is bigger than
   * 0, perform an integration. If the <i>impulse</i> port is known and has data, then add the value
   * provided to the state; if the <i>initialState</i> port is known and has data, then reset the
   * state to the provided value. If both <i>impulse</i> and <i>initialState</i> have data, then
   * <i>initialState</i> dominates. If either is unknown, then simply return, leaving the output
   * unknown. Note that the signals provided at these two ports are required to be purely discrete.
   * This is enforced by throwing an exception if the current microstep is zero when they have input
   * data.
   *
   * @exception IllegalActionException If the input is infinite or not a number, or if thrown by the
   *     solver, or if data is present at either <i>impulse</i> or <i>initialState</i> and the step
   *     size is greater than zero.
   */
  public void fire() throws IllegalActionException {
    ContinuousDirector dir = (ContinuousDirector) getDirector();
    double stepSize = dir.getCurrentStepSize();
    int microstep = dir.getIndex();

    if (_debugging) {
      Time currentTime = dir.getModelTime();
      _debug(
          "Fire at time "
              + currentTime
              + " and microstep "
              + microstep
              + " with step size "
              + stepSize);
    }
    // First handle the impulse input.
    if (impulse.getWidth() > 0 && impulse.hasToken(0)) {
      double impulseValue = ((DoubleToken) impulse.get(0)).doubleValue();
      if (_debugging) {
        _debug("-- impulse input received with value " + impulseValue);
      }
      if (impulseValue != 0.0) {
        if (microstep == 0) {
          throw new IllegalActionException(
              this, "Signal at the impulse port is not purely discrete.");
        }
        double currentState = getState() + impulseValue;
        setTentativeState(currentState);
        if (_debugging) {
          _debug("-- Due to impulse input, set state to " + currentState);
        }
      }
    }
    // Next handle the initialState port.
    ParameterPort initialStatePort = initialState.getPort();
    if (initialStatePort.getWidth() > 0 && initialStatePort.hasToken(0)) {
      double initialValue = ((DoubleToken) initialStatePort.get(0)).doubleValue();
      if (_debugging) {
        _debug("-- initialState input received with value " + initialValue);
      }
      if (microstep == 0.0) {
        throw new IllegalActionException(
            this, "Signal at the initialState port is not purely discrete.");
      }
      setTentativeState(initialValue);
      if (_debugging) {
        _debug("-- Due to initialState input, set state to " + initialValue);
      }
    }

    // Produce the current _tentativeState as output, if it
    // has not already been produced.
    if (!state.isKnown()) {
      double tentativeOutput = getTentativeState();
      // If the round has not updated since the last output, then
      // just produce the same output as last time.
      int currentRound = dir._getODESolver()._getRound();
      if (_lastRound == currentRound) {
        tentativeOutput = _lastOutput;
      }

      if (_debugging) {
        _debug("** Sending output " + tentativeOutput);
      }
      _lastOutput = tentativeOutput;
      state.broadcast(new DoubleToken(tentativeOutput));
    }

    // The _tentativeSate is committed only in postfire(),
    // but multiple rounds will occur before postfire() is called.
    // At each round, this fire() method may be called multiple
    // times, and we want to make sure that the integration step
    // only runs once in the step.
    if (derivative.isKnown() && derivative.hasToken(0)) {
      int currentRound = dir._getODESolver()._getRound();
      if (_lastRound < currentRound) {
        // This is the first fire() in a new round
        // where the derivative input is known and present.
        // Update the tentative state. Note that we will
        // have already produced an output, and so we
        // will not read the updated _tentativeState
        // again in subsequent invocations of fire()
        // in this round. So it is safe to update
        // _tentativeState.
        _lastRound = currentRound;
        double currentDerivative = getDerivative();
        if (Double.isNaN(currentDerivative) || Double.isInfinite(currentDerivative)) {
          throw new IllegalActionException(
              this, "The provided derivative input is invalid: " + currentDerivative);
        }
        if (stepSize > 0.0) {
          // The following method changes the tentative state.
          dir._getODESolver().integratorIntegrate(this);
        }
      }
    }
  }