[HomePage] [TitleIndex] [WordIndex


DynSim2, the beginnings of a second version of DynSim, is a simple process control (and dynamic systems) simulator in Python. DynSim, the original, was written in C and designed for speed, but was not scriptable and lacked some of the flexibility of a version written in Python. To some extent, the speed of modern computers can make up for the loss in speed from using an interpreted language. However, any hard number crunching elements (spectral analysis, NNs etc.) will still use the compiled extensions to Python.

Unfortunately, DynSim now appears to be a registered trademark of Invensys, so a name-change for this particular DynSim may be in the winds.


Motivations and Philosophy

Graphical vs Code

Conciseness, readability and power are all obviously in the eyes of the beholder. However, for object oriented systems, where reuseable blocks/classes/objects are glued together with the "custom" elements of your simulation, it is common for these glue elements to be unconventional, complex or special purpose. Often they represent complex equations or algorithms. Such equations and algorithms are almost always easier to program, and more readable, in code form. Obviously a good object oriented language like Python allows even more reuseability through inheritance by being able to take an existing class and specialise it to suit your purpose. Have you ever used a graphical language (with X, +, - blocks etc.) to program a mathematical equation? What might start out as an obviously recognisable equation form in your expertise domain, turns into a rabbit warren of blocks and lines. In Simulink, it seems better to resort to embedding some m-file code into your simulation when you need to put in an equation (even accounting for the performance hit).

Graphical model construction is somewhat misleading to casual users/observers in that it appears that you can construct complex models without programming any code. Of course, this is rubbish! It is just a different form of code; one that still needs to be learnt in great detail (like a normal programming language). However, in order to pack the programming into this (perhaps "unnatural") graphical form, much of the flexibility of a normal programming language is lost. This usually requires the further learning of tricks and techniques to get around the built-in limitations of the graphical construction.

Integration Method

It might be argued that you need "proper" Runge-Kutta etc integrators (which are somewhat problematic for block- or object- oriented modelling) to get good fidelity from simulations. However, more often than not, Process Control models and simulations are often taken overboard with accuracy and detail, with combined controller and process differential equations being solved quite accurately. However, if your objective is to simulate more realistic scenarios, then as an example, the discrete-time implementation of PID controllers (in PLCs and DCSs) needs to be simulated with Euler integration with fixed time-steps of the order of 0.5 seconds or 1.0 second. In this case, differential equation equivalents are inaccurate and the simulation has lost most of its motivation to provide hi-fidelity solutions to the differential equations. This philosophy is exploited in DynSim2 with only manually-set, fixed time-steps being used through Euler or trapezoid integration (built into each simulation class); This helps to "keep it simple if possible, but make it possible to do difficult things" (e.g. through fine timesteps or multi-rate timesteps).

Another advantage of fixed-timestep integration is that the set of calculations done during a simulation is fixed (apart from any sequencing elements). This is advantageous (and almost a pre-requisite) for enclosing the simulation in an optimisation loop, such as would be the case for fitting model parameters to plant data and optimising tuning parameters for controllers. In these cases, variable-step solvers provide an inconsistent result change for a very small change in parameters, due to the number of time-steps for the simulation changing - essentially it generates noise in the objective function of the optimiser. Optimisers relying on smooth objective functions will not work well with this noise.

Getting Started

Go to the Tutorial page for a complete walk-through of constructing, executing and analysing a simulation.


The Documentation page provides the full documentation of DynSim, its usage, the class library, and advanced topics.

A Simple Example

A couple of these classes can be quickly put together into a simulation of a PID control loop with a process represented by a first-order-plus-deadtime (FOPDT) characteristic using the following example script (from the source file):

"""Simple example of dynsim use for a control loop.
Simulates and plots control of a first-order plus deadtime (FOPDT) process
with a PID controller.  100 seconds at stepsize=0.1 second are simulated."""

from pctools.dynsim import control

# create the simulation objects or "blocks"
ctl = control.PID(P=1.8, I=5.0, D=0.0)  # make a PID controller
plant = control.FOPDT(gain=1.0, delay=2.0, tc=5.0) # first-order plus deadtime model
record = control.Log(name='Logged Data', legend=('PV', 'CO', 'SP'))  # set up a logger

PV = 0.0  # provide PV for first time-step (PV not yet generated by plant)
SP = 0.0   # initial value of Setpoint before step test

# simulate
for t,dt in control.timesteps(finish=100.0, timestep=0.1, plot=True):
    if t>10: SP = 40.0  # step change in setpoint
    out = ctl(SP, PV)  # run the PID controller
    PV = plant(out)  # run the process dynamics
    record([PV, out, SP])  # record a log of the main variables

This script runs 1000 time-steps in about 300 milliseconds and produces the following plot window at the end.


If you're thinking "Gee, that seems like a lot of code to do that!". However, if you look carefully, more than half of the code-text is comments. Here is the code again without the comments - its much cleaner and concise, but adding comments still wins for good understanding of the code.

from pctools.dynsim import control

ctl = control.PID(P=1.8, I=5.0, D=0.0)
plant = control.FOPDT(gain=1.0, delay=2.0, tc=5.0)
record = control.Log(name='Logged Data', legend=('PV', 'CO', 'SP'))

PV = 0.0
SP = 0.0
for t,dt in control.timesteps(finish=100.0, timestep=0.1, plot=True):
    if t>10: SP = 40.0
    out = ctl(SP, PV)
    PV = plant(out)
    record([PV, out, SP])

Download it

You can find the latest version of DynSim in the Weblog below. Look for the latest entry with the title "Uploaded new version ...". The zip file will contain all of files you need. Find your installed version of Python and navigate to "...\python\Lib\site-packages". Unzip the dynsim directory there. That's it! You should now be able to start up Python and from dynsim import control etc.

Application Ideas


Not To Do


2015-05-14 10:33