Ximeng Sun

Causal Block Diagrams (CBD) Modelling Extension in AToM3



  • Reuse CBD models - design once, use everywhere
    • by Hierarchical Modelling
  • Describe visual CBD models textually
    • by Model Description Class Generation
  • Run simulations independently (outside AToM3)
    • by Standalone Simulator
<<< Top

Hierarchical Modelling

  • Model a group of cooperative blocks as an independent model and use them as a single block (Child block)
  • Reuse a model by adding Child blocks (referring to the model) into another model
Abstract example describing Hierarchical Modelling
Figure 1: Abstract example describing Hierarchical Modelling
<<< Top

How to do it in AToM3

  1. Build a model which is going to be referred to by others, e.g.:
    A model of Double Integrators
    Figure 2: A model of Double Integrators

    "IN" and "IC" are "Inport" blocks. This type of blocks and "Outport" blocks are used to connect inside blocks with outside ones of a model. They are auxiliary visual blocks which will be eliminated during simulation (after flattening process).

    Don't forget to specify the name ("DI" in this example) of your model (Model menu->Edit model attributes->model_name). It's very import because the model is referred to by its name. The name is used as the class name when the model description class is generated. Make sure the name is UNIQUE.

    You can press "genMDC" button to generate Model Description Class file of current model (e.g., Double Integrators) in a desired directory.

  2. Build a model which is going to refer to the above model, e.g.:
    A model referring to Double Integrators as its Child blocks
    Figure 3: A model referring to Double Integrators as its Child blocks

    There are two Child blocks referring to Double Integrators (DI) submodel. You need to specify the name ("DI" defined in the previous example) of the model you want to refer to in the field "block_operator" as shown in the above figure.

    In order to connect the outside blocks with the inside ones through the correct ports, you need to specify the name of the specific Inport block or Outport block inside the Child block you want to connect with in the fields of a connection (or signal). For example, as shown in figure 4, since we want to connect Const block "cb7" with the Inport block "IN" of a "DI" Childe block "cb13" (the block name is not shown in the figure), we need to edit the connection "s9" between "cb7" and "cb13" to fill the field "inport_name" with "IN". We do the same thing to connection "s10" as filling the "inport_name" with "IC" (see figure 2).

    Again, don't forget to specify the name (as "thrown_ball" in this example) of your model.

    Specify Port Name
    Figure 4: Specify Port Name
  3. Again, press "genMDC" button to generate Model Description Class file.

<<< Top

Model Description Class

Now before we run the simulation using the standalonw simulator, let's take a look at Model Description Class.

Model Description Class stores all topological information of the original graphical model, it can be used:

  • regenerate the graphical model;
  • for import by the standalone simulator.

Each type of visual block has a corresponding block class. In order to clearly represent blocks and easily manipulate them during simulation, a block class hierarchy for all kinds of blocks in CBD is created, as shown in the following figure.

Class Hierarchy
Figure 5: Class Hierarchy

As you can see, all other classes inherit from BaseBlock class.

The relation between types of visual blocks and corresponding block classes is as follows:

Class Blocks
BaseBlock Adder/Negetor/Product/Inverter/Inport/Ourport
ConstantBlock Constant
GenericBlock Generic
TestBlock Test
TimeDelayBlock Delay/Integrator/Derivative
ChildBlock Child

The signals attribute contains a list of signals generated by the block. The linksIN attribute contains a list of all other blocks linking into this block. Each element of the list is a tuple of four elements: the link-in block object, the name of the connection between these two blocks, the name of "inport_name" and the name of "outport_name" (only meaningful for the connection with a ChildBlock).

The IC attribute of TimeDelayBlock class contains a tuple of link-in IC block object and name of connection between them.

The TRUE_in attribute of TestBlock class contains a tuple of link-in TRUE_in block object and name of connection between them. FALSE_in attribute is the same.

The model_instance attribute of ChildBlock class contains instance object of the referring model.

Here's the Model Description Class generated from Double Integrator model:


# Casual Block Class

from math import *
from BaseBlock import *

class DI:

  def __init__(self, initParams={}):
    self.__initParams = initParams
    self.__blocks = []

    # build blocks
    self.v_x = TimeDelayBlock("v_x", "Integrator", 0.1)
    self.IC = BaseBlock("IC", "Inport")
    self.IN = BaseBlock("IN", "Inport")
    self.x = TimeDelayBlock("x", "Integrator", 0.1)
    self.x_0 = ConstantBlock("x_0", "Constant", 4.0)

    # build connections
    self.v_x.linksIN.append((self.IN, "s2", "", ""))
    self.v_x.linksIN.append((self.IC, "s3", "", ""))
    self.v_x.IC = (self.IC, "s3", "", "")
    self.x.linksIN.append((self.x_0, "s1", "", ""))
    self.x.linksIN.append((self.v_x, "s4", "", ""))
    self.x.IC = (self.x_0, "s1", "", "")

    # parameters initialization
    for block in self.__blocks:
      if isinstance(block, ConstantBlock):
        if (self.__initParams.has_key(block.getBlockName()) == 1):
          block.init_value = self.__initParams[block.getBlockName()]

  # to access all blocks outside the model
  def getBlocks(self):
    return self.__blocks


As you can see from above, there are three main parts in __init__ method. We'll talk about the third part in "Parameterization" section later.

<<< Top

Standalone Simulator

  • Run simulation independently (outside AToM3) by using generated Model Description Class of a hierarchical CBD model
  • Detect algebraic loop of a hierarchical model
    • Flattening the model before simulation
  • Linear algebraic loop can be solved
    • Linear equation solver implementing Gauss-Jordan Elimination

First, let's see how to build a simulation using the standalone simulator.


# import simulator class
from ST_Simulator import *

# import the generated Model Description Class of a CBD model
from thrown_ball import *
def example():
    # provide an instance of a model (the top-level model of hierarchical models) 
    # to instantiate a simulator instance and use default parameters for the model
    s = ST_Simulator(thrown_ball())
    # specify the duration of the simulation, let's try 32 iterations here
    for i in range(32):
        # run the simulation once
    # print out signals of all blocks


The output is really hard to read. Later we'll show how to use PyPlotter to make it pretty readable.

<<< Top

Loop Detection

In order to detect algebraic loops of a hierarchical model, besides the usual way of loop detection, we need to flatten the hierarchical model first. Why? See the following example:

A two-level hierarchical model with Linear Algebraic Loop
Figure 6: A two-level hierarchical model WITH Linear Algebraic Loop

It's a two-level hierarchical model. For sure, the top level model has an algebraic loop and so does the whole hierarchical model.

How about the following model:

A two-level hierarchical model without Linear Algebraic Loop
Figure 7: A two-level hierarchical model WITHOUT Linear Algebraic Loop

Since there is a Delay block inside M1_L2 model, although the top level model has an algebraic loop, the whole model is loop-free.

The idea behind Flattening is very simple: if all blocks are in the same level, then the loop detection becomes easy to accomplish. The flattening is a recursive process. After the process, all Inport, Outport and Child blocks are eliminated.

Obviously, flattening is a simple but not the best solution for loop detection of hierarchical model. One disadvantage is the structures of all models of each level will be known or exposed by this process.

<<< Top


Most of time, when you build a hierarchical model, although you have several instances of the same child model, you want each of these instances to behave differently during simulation. Parameterization can help you to achieve this goal. See the following examples:

The Ballistic Problem without Hierarchical Modelling
Figure 8: The Ballistic Problem without Hierarchical Modelling

You soon realize there is a need to abstract some part of the above model and model that part as a seperate model to get a hierarchical model. But you should also notice that the constant blocks "x_0" and "y_0" have different initial values. So after building the whole hierarchical model with a child model called "DI" (Double Integrators) in which the constant block's default value is 4.0, you need to specify the desired initial values of the constant blocks in different model instances, by giving a list of initial values (a map of map) to the construction method of the top-level model. This is illustrated in figure 9.

The Ballistic Problem with Hierarchical Modelling
Figure 9: The Ballistic Problem with Hierarchical Modelling
<<< Top

Plot Outputs

PyPlotter is a easy-to-use tool for simple plotting. It will be installed as a Python library. There is an example showing how to use to display results from our simulations:


from ST_Simulator import *
from thrown_ball import *

from PyPlotter import tkGfx as GfxDriver # 'awtGfx' for jython
from PyPlotter import Graph, Gfx
def example():
  s = ST_Simulator(thrown_ball({"cb13":{"x_0":0.0}, "cb15":{"x_0":2.0}}))
  for i in range(30):

def plot(s):  
  blocks = s.getModel().getBlocks() 
  xaxis = []
  yaxis = []
  for block in blocks: 
    if (block.getBlockName() == "cb13.x"):
      for signal in block.signals:
    elif (block.getBlockName() == "cb15.x"):
      for signal in block.signals:

  gfx = GfxDriver.Window(title="Ballistic Problem")   
  gr = Graph.Cartesian(gfx, 0, 0, 40, 14)    
  gr.addPen("X vs Y (theta = 45 degree)", Gfx.RED_PEN)
  i = 0
  for x in xaxis:
    gr.addValue("X vs Y (theta = 45 degree)", x, yaxis[i])
    i += 1

if __name__=="__main__":


When you run the above simulation program, you'll get the following figure:

Display of simulation results of Ballistic Problem
Figure 10: Display of simulation results of Ballistic Problem
<<< Top


AToM3 (it should be already installed in any teaching machines at the third floor of Trottier as: /usr/local/pkgs/atom3/atom.sh)
Causal Block Diagrams formalism (unpack it into the AToM3 workspace folder under your home directory; some functions of the standalone simulator are removed temporarily for teaching purpose.)

Tips: In any teaching machine at Trottier, the AToM3 is under: /usr/local/pkgs/atom3/

  1. Before you start AToM3, create a workspace for AToM3 under your home directory (e.g., atom3-user)
  2. To start AToM3:
    $ ./atom3.sh
    $ python atom3.py
    If this is the first time you run AToM3, then you'll be ask to set User Area directory (e.g., atom3-user).
  3. Download CBD formalism package here and unpack the CBD formalism package into User Formalisms folder of your workspace (e.g., atom3-user).
  4. (In case the CBD meta-model hasn't been loaded) Open CBD meta-model by press F3 and select CausalBlockDiagram_META.py in CausalBlockDiagram under User Formalisms directory (NOT the one in central AToM3 directory).
If you want to run AToM3 in your own machines elsewhere, make sure you've already installed Python
Maintained by Ximeng Sun. Last Modified: 2008/09/10 00:03:05.