DiscreteSystem

Construction of DiscreteSystem

DiscreteSystems evolve by the following discrete time difference equation.

\[ x_{k + 1} = f(x_k, u_k, k) \\ y_k = g(x_k, u_k, k)\]

where $x_k$ is the state, $y_k$ is the value of output and $u_k$ is the value of input at discrete time t. $f$ is the state function and $g$ is the output function of the system. See the main constructor.

Basic Construction of DiscreteSystem

When a DiscreteSystem is triggered from its trigger link, it reads current time from its trigger link, reads its input, solves its difference equation, computes its output and writes its output value to its output bus. Let us continue with an example.

We first define state function sfunc and output function ofunc of the system,

julia> using Jusdl # hide

julia> sfunc(dx, x, u, t) = (dx .= -0.5x)
sfunc (generic function with 1 method)

julia> ofunc(x, u, t) = x
ofunc (generic function with 1 method)

From sfunc, it is seen that the system does not have any input, and from ofunc the system has one output. Thus, the input and output of the system is

julia> input = nothing

julia> output = Bus(1)
1-element Bus{Link{Float64}}:
 Link(state:open, eltype:Float64, hasmaster:false, numslaves:0, isreadable:false, iswritable:false)

We also need to specify the initial condition and time of the system

julia> x0  = [1.]
1-element Array{Float64,1}:
 1.0

julia> t = 0.
0.0

We are now ready to construct the system ds.

julia> ds = DiscreteSystem(input, output, sfunc, ofunc, x0, t)
DiscreteSystem(state:[1.0], t:0.0, input:nothing, output:Bus(nlinks:1, eltype:Link{Float64}, isreadable:false, iswritable:false))

To drive ds, we need to launch it.

julia> task = launch(ds)
(Task (runnable) @0x00007f70295a24a0, Task (runnable) @0x00007f70295a2230)

At this point, ds is ready to be driven. To drive ds, we can either use drive(ds, t) or put!(ds.trigger, t).

julia> drive(ds, 1.)
1.0

When the above code is executed, ds evolves until its time is ds.t is 1., During this evolution, ds reads time t from its trigger link, reads its input (in this example, ds has no input, so it does nothing when reading its input), solves its difference equation, computes its output and writes its output value to its output. To signal that the evolution is succeeded, ds writes true its handshake link which needs to be taken to further drive ds.

julia> ds.handshake  # `handshake` link is readable
ERROR: UndefVarError: ds not defined

julia> take!(ds.handshake)
ERROR: UndefVarError: ds not defined

We continue to drive ds,

julia> for i in 2. : 10.
           drive(ds, i)
           take!(ds.handshake)
       end
ERROR: UndefVarError: drive not defined

Note that all the output values of ds is written to its output bus.

julia> ds.output[1].buffer.data
64-element Array{Float64,1}:
 -0.5
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  ⋮
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0
  0.0

When we launched ds, we constructed a task which is still running.

julia> task
(Task (runnable) @0x00007f70295a24a0, Task (runnable) @0x00007f70295a2230)

As long nothing goes wrong, i.e. no exception is thrown, during the evolution of ds, it is possible to drive ds. To safely terminate the task, we need to terminate the ds.

julia> terminate(ds)

We can confirm that the task is not running and its state is done.

julia> task
(Task (runnable) @0x00007f70295a24a0, Task (done) @0x00007f70295a2230)

Since the task is not running any more, ds cannot be drivable any more. However to drive ds again, we need launch ds again.

Full API

Jusdl.Components.Systems.DynamicSystems.DiscreteSystemType
DiscreteSystem(input, output, statefunc, outputfunc, state, t, modelargs=(), solverargs=(); 
    alg=DiscreteAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())

Construct a DiscreteSystem with input and output. statefunc is the state function and outputfunc is the output function of DiscreteSystem. state is the initial state and t is the time. modelargs and modelkwargs are passed into ODEProblem and solverargs and solverkwargs are passed into solve method of DifferentialEquations. alg is the algorithm to solve the diffence equation of the system.

The system is represented by

\[ \begin{array}{l} x_{k + 1} = f(x_k, u_k, k) \\ y_k = g(x_k, u_k, k) \end{array}\]

where $x_k$ is the state, $y_k$ is the value of output, $u_k$ is the value of input at dicrete time $k$. $f` is `statefunc` and$g`isoutputfunc`.

The signature of statefunc must be of the form

function statefunc(dx, x, u, t)
    dx = ...   # Update dx
end

and the signature of outputfunc must be of the form

function outputfunc(x, u, t)
    y = ...   # Compute y
    return y
end

Example

julia> sfunc(dx,x,u,t) = (dx .= 0.5x)
sfunc (generic function with 1 method)

julia> ofunc(x, u, t) = x
ofunc (generic function with 1 method)

julia> ds = DiscreteSystem(Bus(1), Bus(1), sfunc, ofunc, [1.], 0.)
DiscreteSystem(state:[1.0], t:0.0, input:Bus(nlinks:1, eltype:Link{Float64}, isreadable:false, iswritable:false), output:Bus(nlinks:1, eltype:Link{Float64}, isreadable:false, iswritable:false))
Info

See DifferentialEquations for more information about modelargs, modelkwargs, solverargs, solverkwargs and alg.

source