Construction and Simulation of a Simple Model

In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below.

model

Model Simulation

We construct an empty model and then add nodes and branches to model. See Construction of Models for more detailed information about model construction.

using Jusdl

# Construction of an empty model
t0 = 0.     # Start time
dt = 0.01   # Sampling interval
tf = 10.    # Final time
model = Model(clock=Clock(t0, dt, tf))

# Adding nodes to model
addnode!(model, SinewaveGenerator(), label=:gen)
addnode!(model, Writer(), label=:writer)

# Adding branches to model
addbranch!(model, :gen => :writer)

In this simple model, we have a single output sinusoidal wave generator gen and a writer. In the script above, we constructed the components, connected them together and constructed the model.

In addition to simulation time settings(which have set through model clock during the model construction above), we can specify simulation settings such as whether a simulation log file is be to constructed, model components are to be saved in a file, etc.

simdir = "/tmp"
logtofile = true
reportsim = true

At this point, the model is ready for simulation.

sim = simulate!(model, simdir=simdir, logtofile=logtofile, reportsim=reportsim)
Simulation(state:done, retcode:success, path:/tmp/Simulation-0c71b52b-e23f-4fd2-9ab4-31fde3eb8b8b)

Investigation of Simulation

First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved.

foreach(println, readlines(`ls -al $(sim.path)`))
total 10568
drwxr-xr-x 2 sari sari     4096 May 12 00:24 .
drwxrwxrwt 1 root root 10764288 May 12 00:24 ..
-rw-r--r-- 1 sari sari    15236 May 12 00:24 cb865e26-2d3e-4b71-bf74-271e6c3ecb1b.jld2
-rw-r--r-- 1 sari sari    21831 May 12 00:24 report.jld2
-rw-r--r-- 1 sari sari     1043 May 12 00:24 simlog.log

The simulation directory includes a log file simlog.log which helps the user monitor simulation steps.

# Print the contents of log file
open(joinpath(sim.path, "simlog.log"), "r") do file
    for line in readlines(file)
        println(line)
    end
end
┌ Info: 2020-05-12T00:24:15.217 Started simulation...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.297 Inspecting model...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.297 Done.
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.297 Initializing the model...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.352 Done...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.352 Running the simulation...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.491 Done...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.491 Terminating the simulation...
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
┌ Info: 2020-05-12T00:24:15.521 Done.
└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5

report.jld2 file, which includes the information about the simulation and model components, can be read back after the simulation.

julia> using FileIO, JLD2

julia> filecontent = load(joinpath(sim.path, "report.jld2"))
Dict{String,Any} with 9 entries:
  "retcode"         => :success
  "name"            => "Simulation-0c71b52b-e23f-4fd2-9ab4-31fde3eb8b8b"
  "model/callbacks" => nothing
  "model/name"      => ""
  "model/clock"     => Clock(t:10.0, dt:0.01, tf:10.0, paused:false, isrunning:…
  "model/id"        => "b3eacea9-7253-4f85-8726-54cc54b0030f"
  "components/"     => SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0…
  "path"            => "/tmp/Simulation-0c71b52b-e23f-4fd2-9ab4-31fde3eb8b8b"
  "state"           => :done

julia> clock = filecontent["model/clock"]
Clock(t:10.0, dt:0.01, tf:10.0, paused:false, isrunning:false)

Analysis of Simulation Data

After the simulation, the data saved in simulation data files, i.e. in the files of writers, can be read back any offline data analysis can be performed.

# Read the simulation data
t, x = read(getnode(model, :writer).component)

# Plot the data
using Plots
plot(t, x, xlabel="t", ylabel="x", label="")

A Larger Model Simulation

Consider a larger model whose block diagram is given below

model

The script below illustrates the construction and simulation of this model

using Jusdl
using Plots

# Construction of the model
model = Model()
addnode!(model, SinewaveGenerator(frequency=2), label=:gen1)
addnode!(model, Gain(gain=1), label=:gain1)
addnode!(model, Adder((+,+)), label=:adder1)
addnode!(model, SinewaveGenerator(frequency=3), label=:gen2)
addnode!(model, Adder((+, +, -)), label=:adder2)
addnode!(model, Gain(gain=1), label=:gain2)
addnode!(model, Writer(), label=:writer)
addnode!(model, Gain(gain=1), label=:gain3)
addbranch!(model, :gen1 => :gain1, 1 => 1)
addbranch!(model, :gain1 => :adder1, 1 => 1)
addbranch!(model, :adder1 => :adder2, 1 => 1)
addbranch!(model, :gen2 => :adder1, 1 => 2)
addbranch!(model, :gen2 => :adder2, 1 => 2)
addbranch!(model, :adder2 => :gain2, 1 => 1)
addbranch!(model, :gain2 => :writer, 1 => 1)
addbranch!(model, :gain2 => :gain3, 1 => 1)
addbranch!(model, :gain3 => :adder2, 1 => 3)

# Simulation of the model
simulate!(model, withbar=false)

# Reading and plotting the simulation data
t, x = read(getnode(model, :writer).component)
plot(t, x)
[ Info: 2020-05-12T00:24:27.058 Started simulation...
[ Info: 2020-05-12T00:24:27.058 Inspecting model...
┌ Info: 	The model has algrebraic loops:[[5, 6, 8]]
└ 		Trying to break these loops...
[ Info: 	Loop [5, 6, 8] is broken
[ Info: 2020-05-12T00:24:27.188 Done.
[ Info: 2020-05-12T00:24:27.188 Initializing the model...
[ Info: 2020-05-12T00:24:27.345 Done...
[ Info: 2020-05-12T00:24:27.345 Running the simulation...
[ Info: 2020-05-12T00:24:27.562 Done...
[ Info: 2020-05-12T00:24:27.562 Terminating the simulation...
[ Info: 2020-05-12T00:24:27.563 Done.