Reactors


Reactor Behaviour: Structure and Definition

The following example shows the structure and definition of a reactor behaviour, exemplified through two reactor behaviours called Add and WindPower. The Main actor, when run, will visualize the DAG of the Add reactor behaviour. The Add reactor behaviour has 2 sources called a and b, and it has one sink (denoted by out) which is bound to the result of (+ a b). A more complex example is given by the WindPower reactor behaviour, which implements a mathematical formula for computing the theoretical wind power of a wind turbine (i.e. the theoretical upper limit for the power generated from wind).

Try it out! Replace the expression (to-graphviz Add) with (to-graphviz WindPower) and re-run the program to visualize the DAG that corresponds with the WindPower reactor behaviour.

Example

Graphical DAG Representation

DAG viewing area. Run program to view Directed Acyclic Graph, which is inserted here by the Stella program.

Reactor Behaviour Composition: Deploy

Reactor behaviours can be used within other behaviours. A prime example of this is given by the following code, where the WindPower reactor behaviour of the previous example is used from within a newly added PowerOutput reactor behaviour. PowerOutput behaviour extends WindPower by taking into account that the real power output of wind turbines depends on their efficiency (e.g. 30%). In the body of PowerOutput, the deploy statement can be seen as a function call but for reactor behaviours: it deploys a new instance of WindPower within the current reactor. When the example program is run, the DAG of PowerOutput is visualized. You can see that a copy of WindPower is embedded within this DAG.

Example

Graphical DAG Representation

DAG viewing area. Run program to view Directed Acyclic Graph, which is inserted here by the Stella program.

Running Reactors: Simple Wind Turbine Simulator

Wind Turbine Simulator

In this example we define a simple wind turbine simulator, as discussed more elaborately in this paper. It combines elements that we previously discussed: The Wind actor behaviour is discussed here, and the WindPower and PowerOutput reactor behaviours are discussed on this page. New to this example are the Turbine and TurbinePowerOutput reactor behaviours, and the Main actor behaviour which kicks the wind turbine simulator into action.

Pointfree Composition: ror

Stella enables pointfree reactor behaviour composition via operators such as ror. For example, the Turbine and PowerOutput behaviours are composed to create a new reactor behaviour called TurbinePowerOutput. Concretely, the sinks of Turbine are connected to the sources of PowerOutput. See this paper for more information on this topic.

Linking Actors to Reactors

The Main actor behaviour is responsible for kicking the simulator into action: it spawns a Wind actor (stored in mistral) representing the wind, and it spawns a TurbinePowerOutput reactor (stored in turbine that represents a wind turbine and its power output calculation. The crucial statement that is responsible for kicking the turbine reactor into action is the react-to! statement, which will send an instruction to turbine to change the value of its source nodes to 80 (meters blade-length), 0.3 (30% efficiency), and mistral as the wind.

Implicit Stream Dependencies

Note that reactors can create dependencies to data streams. In the body of Turbine, note that the expression the-wind.speed creates a dependency to the speed stream that is exported by the actor referenced by the-wind. More information about this mechanism can be found in this paper.