.ModelicaDEVS.UsersGuide.PowerDEVS

Information

PowerDEVS - A C++ Implementation of the DEVS Formalism

As mentioned in the introductory section, PowerDEVS served as kind of a template for ModelicaDEVS: although the simulator of ModelicaDEVS is fundamentally different the components of ModelicaDEVS have been built according to the blocks in the PowerDEVS library.

A short but accurate description of the software's main achievements is given in the abstract of "PowerDEVS: A DEVS-Based Environment for Hybrid System Modeling and Simulation" [Kofman03]: "PowerDEVS allows defining atomic DEVS models in C++ language which can be then graphically coupled in hierarchical block diagrams to create more complex systems. Both, atomic an coupled models, can be organized in libraries which facilitate the reusability features. The environment automatically translates the graphically coupled models into a C++ code which executes the simulation."

This section gives a brief introduction into the simulation mechanism of PowerDEVS. For more details you may also download the PowerDEVS code/software from http://www.fceia.unr.edu.ar/lsd/powerdevs/ .


The Modelling Environment

Like many other simulation software systems, PowerDEVS provides a graphical editor where models can be built graphically. Note that it would be possible to declare them directly in C++ code. This however would be rather cumbersome and error-prone, and using the automatic transformation of PowerDEVS is recommended.
Since the handling of the modelling environment is fairly intuitive and anyway not critical to the understanding of the simulator, it is not explained in greater detail here.

An interesting subject to dwell some more on, however, is the way the graphical representation of a model is transformed into C++ code, in order to be utilisable by the simulator framework.


Assume the sample model in the obove figure. When the "run" button in the modelling environment is pressed, PowerDEVS creates a file called "model.h" that holds a C++ description of the model. All information that will be needed for the simulation later on is stored in this file.
The following code corresponds to the model in the figure above, but for simplicity, the output components "ToDisk1", "ToDisk2", "ToDisk3" and "QuickScope1" have been removed:
 1 #include "textonly/simulator.h"
 2 #include "textonly/root_simulator.h"
 3 #include "textonly/connection.h"
 4 #include "textonly/coupling.h"
 5 #include "textonly/root_coupling.h"
 6 #include           //include the Step block
 7 #include   //include the NLfunction block
 8 #include   //include the integrator
 9
10 class model:public root_simulator {
11
12  root_coupling* Coupling0001;
13  simulator* child00010001;   //step
14  simulator* child00010002;   //NLfunction
15  simulator* child00010003;   //integrator
16  connection* EIC0001[1];     //external input connections
17  connection* EOC0001[1];     //external output connections
18  connection* conn00010001;
19  connection* conn00010002;
21  connection* conn00010003;
21  connection* IC0001[3];      //array containing all connections between blocks
22  simulator* D0001[3];        //array containing all blocks
23
24  public:
25
26  model(bool* r):root_simulator(r){}    //the model allocated in main() is a root_simulator
27
28  void configure(){    //this function will be called from the main() function in model.cpp
29
30    Coupling0001=new root_coupling();   //the "global" coupling
31
32    child00010001= new step13();        //allocate a new Step block
33    D0001[0]=child00010001;             //insert the Step block into block array
34    child00010002= new nlfunction();
35    D0001[1]=child00010002;
36    child00010003= new integrador();
37    D0001[2]=child00010003;
38
39    conn00010001= new connection();       //allocate a new connection
40    conn00010001->setup(0 , 0 , 1 , 0);   //connection from step to NLfunction, port 0
41    IC0001[0]=conn00010001;               //insert into array of connections
42    conn00010002= new connection();
43    conn00010002->setup(1 , 0 , 2 , 0);   //connection from NLfunction to integrator
44    IC0001[1]=conn00010002;
45    conn00010003= new connection();
46    conn00010003->setup(2 , 0 , 1 , 1);   //connection from Integrator to NLfunction, port 1
47    IC0001[2]=conn00010003;
48
49    //setup coupling, passing the block and connection arrays (and their sizes)
50    Coupling0001->setup(&D0001[0], 3, &IC0001[0], 3);
51
52    MainCoupling = Coupling0001;       //set MainCoupling
53    Coupling0001->rsim=this;
54    ti = 0;                            //simulation start time
55    tf = 10;                           //simulation final time
56
57    //initialize blocks with the appropriate values for their parameters
58    child00010001->init(0, 0.0,1.76,10.0);
59    child00010002->init(0, "-u1+u0", 2.0);
60    child00010003->init(0, "QSS",1.0,10.0,"integrator.csv");
61    Coupling0001->init(0);
62  }
63 };
As a last point worth mentioning, there is the incorporation of the tie-breaking function by the so called Priority Window (Accessible through the menu Edit, Priorities), which allows the modeller to specify a particular priority order among the components:



The Simulator

The PowerDEVS simulator framework enables the user to simulate a system that is available in the C++ format shown before. Normally, this is the result of modelling it graphically in the PowerDEVS graphical editor followed by an automatic transformation into the aforementioned C++ data structures.
The subsequent sections will give insight into the simulator architecture both on a more theoretical level as well as on the level of its actual implementation in C++.

Simulator Theory
The PowerDEVS simulator is based on the abstract simulator concept developed by Zeigler [Zeigler84]. To make allowance for the possibility of coupled/hierarchical DEVS systems, PowerDEVS models embody the structure shown in the following figure, whereas simulators represent atomic models and coordinators represent coupled models.

As soon as there are two or more components constituting the model, it is necessary to make them able to communicate with each other (send and receive output/input signals). The most intuitive approach would probably be the following: each block keeps a list of the blocks that are connected to its output port, and whenever the block produces an output event, it sends a message to the connected blocks in order to make them undergo their external transition. It is however not the approach chosen in Zeigler's abstract simulator/PowerDEVS. PowerDEVS rather leaves the control of the interaction within a set of blocks to the coordinator that is declared to be responsible for these particular blocks. If for example block A has to generate an output event that has to be sent to block B, it is the coordinator that a) sends a message (called "lambdamessage" in PowerDEVS) to block A in order to trigger the λ-function and b) passes the generated output event to the block B. Of course, both approaches (the intuitive one as well as the one applied in PowerDEVS) lead to the same result. Thus, a modeller does not have to think of the complicated coordinator-simulator concept but may consider the blocks to act autonomously ("block A decides to produce an event and sends it to block B").

Let us study the PowerDEVS solution to the component interaction issue in more detail. The figure above depicts the possible hierarchical structure and the corresponding simulation scheme of a DEVS model. The messages between coordinators and simulators up and down the tree consist of the following two types: We can see that simulators do not interact directly with other simulators on the same layer, but only pass their outputs to the parent coordinator which then is responsible for the propagation of the signal to the appropriate simulators (i.e. those which are connected to the "firing" simulator). The communication between simulators can thus be said to be monitored by the associated coordinator.

Since both coordinators and simulators have to be valid DEVS models, they have to feature the typical DEVS functions: δint, δext, the time-advance and the λ-function. In simulators, these functions simply define the inherent behaviour of the block in question. In the case of a coordinator however, they have a slightly different meaning/effect: Let us investigate now, how a signal moves through the tree of coordinators and simulators. Consider a hierarchy like the one in the subsequent figure, which has the same topology as the example above, but with directed connections).
Suppose that coupled2 has just noticed that atomic3 is ready to undergo its internal transition (apparently, it has the smallest tn value). For this reason, coupled2 sends a message to atomic3, which then executes its internal transition. Instead of sending the output directly to coupled1 (which looks like another simulator to atomic3), it returns it to its father coordinator, coupled2. coupled2 checks now what components are attached to the output port of atomic3 and finds coupled1, to which it propagates the output of atomic3. coupled1 has now just received an external event that makes it execute an external transition. Since coupled1 is a coordinator, this transition just consists of forwarding the signal to the simulators connected to its input ports. In our example, this is only atomic1, which now executes its external transition and thereby sets its local variable tn to a new value. As mentioned before, when a coordinator (coupled1 in this case) forwards an external event, it scans the tn values of its children in order to update dast and its own tn value. Note that this update already involves the new tn value of atomic1. The next step depends now on whether atomic1 or atomic2 has the smaller tn value and therefore is the imminent component to execute its internal transition.

So much for the theoretical background of the PowerDEVS model simulator. When comparing this simulation scheme to the way ModelicaDEVS works, it can be easily seen that there are several fundamental differences between the two simulator concepts.


Generated at 2024-04-25T18:15:59Z by OpenModelicaOpenModelica 1.22.3 using GenerateDoc.mos