Integrating adevs into other simulation environments

Adevs is designed to be integrated into component based simulation environments such as the High Level Architecture and some high performance simulation systems. The xdevssim class provides a wrapper around the Parallel DEVS simulators that can be driven by other simulation tools. The xdevssim class provides a few fundamental methods. These are initialize(), finalize(), inject(), computeInputOutput(), and deltaFunc(). The xdevssim constructor accepts a devs model as its only argument, just as with the devssim simulator.

The initialize(TIME_TYPE) function must be called prior to calling any other methods. The initialize() method will call the init() method of the model attached to the simulator. The TIME_TYPE argument is used as the simulation start time. The initialize() method is a virtual method that can be overridden by a derived class as needed.

The finalize() method should be called when the simulation is complete. The only methods that should be activated after calling finalize() are the initialize() method (to get ready for another run) and the destructor. The finalize() method is a virtual method that can be overridden as needed.

The inject(const adevs_bag<PortValue>&) and inject(const PortValue&) are used to inject data into the simulator. The input objects will applied to the model when the deltFunc(TIME_TYPE) method is called. Note that no garbage collection is performed for the injected values. If explicit memory management is needed for the inject values (i.e. delete), this should be done after the deltFunc(TIME_TYPE) method has been called. That is, after the inputs have been applied to the models.

The computeInputOutput() method returns a read only bag of PortValue objects that are the output of the model at time nextTN(). The output values will be garbage collected via the model's gc_output() method when the deltFunc(TIME_TYPE) method is called.

The deltFunc(TIME_TYPE) method causes the simulation clock to be advanced and the model state at the supplied time to be computed. Calling this method has the following effects. The model I/O is computed if it has not been already via a computeInputOutput() call. The values supplied to the model via the inject() method are applied and the model state is computed at the indicated time. After the state has been computed, the model's garbage collection methods are activated. This may cause values obtained by computeInputOutput() to be deleted, and so the simulation developer must be careful when explicit memory management is being used.

The following code snippet shows how the Parallel DEVS simulation cycle could be implemented using an instance of the xdevssim class.

myModel* model = new myModel;
xdevssim sim(myModel);
sim.initialize();
while (sim.nextTN() < INFINITY)
{
     sim.computeInputOutput();
     sim.deltFunc(sim.nextTN());
}
sim.finalize();

The following code snippet will give exactly the same results.


myModel* model = new myModel;
xdevssim sim(myModel);
sim.initialize();
while (sim.nextTN() < INFINITY)
{
     sim.deltFunc(sim.nextTN());
}
sim.finalize();

In the more general case, the clock of the adevs simulation would be driven by some other time source (either a real or simulated clock) and data would be both received from the outside world and sent to the outside world. Imagine that we have a function send(y,t) that sends a time stamped message bag of PortValue objects and a function recv(x,t,tmax) that fills out the bag x with PortValue pairs and sets t to the input time stamp if input is available before time tmax. Otherwise, recv(x,t,tmax) set t = tmax and sets y to an empty bag. The adevs simulation could be driven with the following code. Such functions could be implemented using the standard High Level Architecture runtime infrastructure API (browsing the www.sisostds.org conference proceedings will turn up several papers on integrating DEVS simulations with the HLA).

myModel* model = new myModel;
xdevssim sim(myModel);
sim.initialize();
while(!done)
{
     // wait for input or our next event time
     recv(x,t,sim.nextTN());
     // if t is the next event time, send our output
     if (t == sim.nextTN())
     {
          send(sim.computeInputOutput(),sim.nextTN());
     }
     // inject available input
     sim.inject(x);
     // compute next state
     sim.deltFunc(t);
}
sim.finalize();