Ejemplo n.º 1
0
        })

    window.doStep(time, step, 0, START_STEP_SIZE)

    wOut = window.getValues(step, 0, [window.tau, window.x])

    # Coupling equation
    power_tau = wOut[window.tau]

    power.setValues(step, 0, {
        power.tau: power_tau,
        power.up: env_up(time),
        power.down: env_down(time)
    })

    power.doStep(time, step, 0, START_STEP_SIZE)

    pOut = power.getValues(step, 0, [power.omega, power.theta, power.i])

    trace_omega.append(pOut[power.omega])
    trace_i.append(pOut[power.i])
    trace_x.append(wOut[window.x])
    time += START_STEP_SIZE
    times.append(time)

color_pallete = [
    "#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33",
    "#a65628", "#f781bf"
]

output_file("./results.html", title="Results")
step_size = START_STEP_SIZE
step = 1  # Step 0 has already been done by the initialization.
last_rollback_step = 0

while time < STOP_TIME:
    step_completed = False
    while not step_completed:
        l.debug("Start step: %d at time %f", step, time)
        """
        This scenario will fail to execute because the adapt armature current is using the last two values to check the crossing.
        When it checks the crossing, it is already too late and more steps need to be rolled back.
        Not just one.
        """
        environment.doStep(time, step, iteration, step_size)
        power.doStep(time, step, iteration, step_size)
        (step_info,
         proposed_step_size) = adapt_armature.doStep(time, step, iteration,
                                                     step_size)

        if step_info == STEP_DISCARD:
            l.debug("Rolling back step: %d at time %f", step, time)
            """
            In this abstraction, we don't need to do much.
            But in real FMI, we would have to restore the state of the FMUs.
            """
            step_completed = False
            last_rollback_step = step
            l.debug("Decreasing step size from %f to %f...", step_size,
                    proposed_step_size)
            step_size = proposed_step_size
    environment
    power
    obstacle
    window
    armature adaptation
    controller
    
    """

    # This is the jacobi type iteration
    """
    Notice that the units have the state and inputs defined at time t,
    and we assume that they can compute their internal state up to time t+H.
    """
    environment.doStep(time, step, iteration, START_STEP_SIZE)
    power.doStep(time, step, iteration, START_STEP_SIZE)
    obstacle.doStep(time, step, iteration, START_STEP_SIZE)
    window.doStep(time, step, iteration, START_STEP_SIZE)
    adapt_armature.doStep(time, step, iteration, START_STEP_SIZE)
    controller.doStep(time, step, iteration, START_STEP_SIZE)

    # Set environment inputs
    # Nothing to do

    # Get environment outputs
    envOut = environment.getValues(step, iteration,
                                   [environment.out_up, environment.out_down])

    # get obstacle delayed inputs
    #cOut = controller.getValues(step-1, iteration, [controller.out_up, controller.out_down])
    wOut = window.getValues(step - 1, iteration, [window.x])
class AlgebraicAdaptation_Power_Window_Obstacle(AbstractSimulationUnit):
    """
    This is the adaptation that realizes the strong coupling between the power,
    window, and obstacle units.
    """
    def __init__(self, name, num_rtol, num_atol, START_STEP_SIZE,
                 FMU_START_RATE):

        self._num_rtol = num_rtol
        self._num_atol = num_atol

        self._max_iterations = 100

        self._power = PowerFMU("power",
                               num_rtol,
                               num_atol,
                               START_STEP_SIZE / FMU_START_RATE,
                               J=0.085,
                               b=5,
                               K=7.45,
                               R=0.15,
                               L=0.036,
                               V_a=12)

        self.omega = self._power.omega
        self.theta = self._power.theta

        self._window = WindowFMU("window",
                                 num_rtol,
                                 num_atol,
                                 START_STEP_SIZE / FMU_START_RATE,
                                 r=0.11,
                                 b=10)

        self._obstacle = ObstacleFMU("obstacle",
                                     num_rtol,
                                     num_atol,
                                     START_STEP_SIZE / FMU_START_RATE,
                                     c=1e5,
                                     fixed_x=0.45)

        self.up = self._power.up
        self.down = self._power.down

        input_vars = [self.down, self.up]

        self.i = self._power.i
        self.omega = self._power.omega
        self.theta = self._power.theta
        self.x = self._window.x
        self.F = self._obstacle.F

        state_vars = [self.i, self.omega, self.theta, self.x, self.F]

        algebraic_functions = {}

        AbstractSimulationUnit.__init__(self, name, algebraic_functions,
                                        state_vars, input_vars)

    def _isClose(self, a, b):
        return numpy.isclose(a, b, self._num_rtol, self._num_atol)

    def _biggerThan(self, a, b):
        return not numpy.isclose(a, b, self._num_rtol,
                                 self._num_atol) and a > b

    def _doInternalSteps(self, time, step, iteration, step_size):
        l.debug(">%s._doInternalSteps(%f, %d, %d, %f)", self._name, time, step,
                iteration, step_size)

        assert step_size > 0.0, "step_size too small: {0}".format(step_size)
        #assert self._biggerThan(step_size, 0), "step_size too small: {0}".format(step_size)
        assert iteration == 0, "Fixed point iterations not supported outside of this component."

        converged = False
        internal_iteration = 0

        cOut = self.getValues(step, iteration, [self.up, self.down])
        wOut = self._window.getValues(step - 1, iteration,
                                      [self._window.x, self._window.tau])
        pOut = None

        while not converged and internal_iteration < self._max_iterations:
            self._power.setValues(
                step,
                iteration,
                {
                    self._power.tau: wOut[self._window.tau],  # Delayed input
                    self._power.up: cOut[self.up],
                    self._power.down: cOut[self.down]
                })
            self._power.doStep(time, step, iteration, step_size)
            pOut = self._power.getValues(
                step, iteration,
                [self._power.omega, self._power.theta, self._power.i])

            self._obstacle.setValues(
                step, iteration,
                {self._obstacle.x: wOut[self._window.x]})  # Delayed input
            self._obstacle.doStep(time, step, iteration, step_size)
            oOut = self._obstacle.getValues(step, iteration,
                                            [self._obstacle.F])

            self._window.setValues(
                step, iteration, {
                    self._window.omega_input: pOut[self._power.omega],
                    self._window.theta_input: pOut[self._power.theta],
                    self._window.F_obj: oOut[self._obstacle.F]
                })
            self._window.doStep(time, step, iteration, step_size)
            wOut_corrected = self._window.getValues(
                step, iteration, [self._window.x, self._window.tau])

            l.debug("Iteration step completed:")
            l.debug("wOut=%s;", wOut)
            l.debug("wOut_corrected=%s.", wOut_corrected)


            if self._isClose(wOut[self._window.x], wOut_corrected[self._window.x]) \
                and self._isClose(wOut[self._window.tau], wOut_corrected[self._window.tau]):
                converged = True

            internal_iteration = internal_iteration + 1
            wOut = wOut_corrected

        if converged:
            l.debug("Fixed point found after %d iterations",
                    internal_iteration)
        else:
            l.debug("Fixed point not found after %d iterations",
                    internal_iteration)
            raise RuntimeError("Fixed point not found")

        AbstractSimulationUnit.setValues(
            self, step, iteration, {
                self.i: pOut[self._power.i],
                self.theta: pOut[self._power.theta],
                self.omega: pOut[self._power.omega],
                self.x: wOut[self._window.x],
                self.F: oOut[self._obstacle.F]
            })

        l.debug("<%s._doInternalSteps() = (%s, %d)", self._name, STEP_ACCEPT,
                step_size)
        return (STEP_ACCEPT, step_size)

    def setValues(self, step, iteration, values):
        l.debug(
            ">%s.AlgebraicAdaptation_Power_Window_Obstacle.setValues(%d, %d, %s)",
            self._name, step, iteration, values)

        # Filter just the inputs.
        inputs = {self.up: values[self.up], self.down: values[self.down]}

        AbstractSimulationUnit.setValues(self, step, iteration, inputs)

        if self._mode == INIT_MODE:
            # Initialize the internal FMUs and compute the value of the armature.

            l.debug("Initializing strong component...")

            step = iteration = 0

            wOut_tau_delayed = 0.0
            wOut_x_delayed = 0.0

            # Set power inputs (or initial state, given by values)
            self._power.setValues(step, iteration, values)
            self._power.setValues(step, iteration,
                                  {self._power.tau: wOut_tau_delayed})

            # Get power initial outputs
            pOut = self._power.getValues(
                step, iteration,
                [self._power.omega, self._power.theta, self._power.i])

            # Set obstacle initial inputs
            # Assume they are zero because the outputs of the window are delayed.
            self._obstacle.setValues(step, iteration,
                                     {self._obstacle.x: wOut_x_delayed})
            # Get obstacle outputs
            oOut = self._obstacle.getValues(step, iteration,
                                            [self._obstacle.F])

            # Set window inputs
            self._window.setValues(
                step, iteration, {
                    self._window.omega_input: pOut[self._power.omega],
                    self._window.theta_input: pOut[self._power.theta],
                    self._window.F_obj: oOut[self._obstacle.F]
                })
            # Get window outputs
            wOut = self._window.getValues(step, iteration,
                                          [self._window.x, self._window.tau])

            # Set corrected power windows
            self._power.setValues(
                step,
                iteration,
                {
                    self._power.tau:
                    wOut[self._window.tau]  # Delayed input from window
                })

            # We know that convergence is easily achieved for this initialisation
            assert self._isClose(wOut[self._window.tau], wOut_tau_delayed)
            assert self._isClose(wOut[self._window.x], wOut_x_delayed)

            # Record the outputs
            AbstractSimulationUnit.setValues(
                self, step, iteration, {
                    self.i: pOut[self._power.i],
                    self.theta: pOut[self._power.theta],
                    self.omega: pOut[self._power.omega],
                    self.x: wOut[self._window.x],
                    self.F: oOut[self._obstacle.F]
                })

            l.debug("Strong component initialized.")

        l.debug("<%s.AlgebraicAdaptation_Power_Window_Obstacle.setValues()",
                self._name)

    def enterInitMode(self):
        l.debug(
            ">%s.AlgebraicAdaptation_Power_Window_Obstacle.enterInitMode()",
            self._name)

        AbstractSimulationUnit.enterInitMode(self)

        self._power.enterInitMode()
        self._window.enterInitMode()
        self._obstacle.enterInitMode()

        l.debug(
            "<%s.AlgebraicAdaptation_Power_Window_Obstacle.enterInitMode()",
            self._name)

    def exitInitMode(self):
        l.debug(">%s.AlgebraicAdaptation_Power_Window_Obstacle.exitInitMode()",
                self._name)

        AbstractSimulationUnit.exitInitMode(self)

        self._power.exitInitMode()
        self._window.exitInitMode()
        self._obstacle.exitInitMode()

        l.debug("<%s.AlgebraicAdaptation_Power_Window_Obstacle.exitInitMode()",
                self._name)