DiscreteSystem
Construction of DiscreteSystem
DiscreteSystem
s 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 Causal # 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 = Outport(1)
1-element Outport{Outpin{Float64}}:
Outpin(eltype:Float64, isbound: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(righthandside=sfunc, readout=ofunc, state=x0, input=input, output=output)
DiscreteSystem(righthandside:sfunc, readout:ofunc, state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))
To drive ds
, we need to launch
it.
julia> iport, trg, hnd = Inport(1), Outpin(), Inpin{Bool}()
(Inport(numpins:1, eltype:Inpin{Float64}), Outpin(eltype:Float64, isbound:false), Inpin(eltype:Bool, isbound:false))
julia> connect!(ds.output, iport)
1-element Array{Link{Float64},1}:
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect!(trg, ds.trigger)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect!(ds.handshake, hnd)
Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
julia> task = launch(ds)
Task (runnable) @0x00007f1fca591870
julia> task2 = @async while true
all(take!(iport) .=== NaN) && break
end
Task (runnable) @0x00007f1fca8b1d50
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> put!(trg, 1.)
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> hnd.link # `handshake` link is readable
Link(state:open, eltype:Bool, isreadable:true, iswritable:false)
julia> take!(hnd)
true
We continue to drive ds
,
julia> for i in 2. : 10.
put!(trg, i)
take!(hnd)
end
Note that all the output values of ds
is written to its output
bus.
julia> iport[1].link.buffer
64-element Buffer{Cyclic,Float64,1}:
0.0009765625
-0.001953125
0.00390625
-0.0078125
0.015625
-0.03125
0.0625
-0.125
0.25
-0.5
⋮
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) @0x00007f1fca591870
julia> task2
Task (runnable) @0x00007f1fca8b1d50
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> put!(trg, NaN)
julia> put!(ds.output, [NaN])
1-element Array{Float64,1}:
NaN
We can confirm that the task
is not running and its state is done
.
julia> task
Task (done) @0x00007f1fca591870
julia> task2
Task (done) @0x00007f1fca8b1d50
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
Causal.@def_discrete_system
— Macro@def_discrete_system ex
where ex
is the expression to define to define a new AbstractDiscreteSystem component type. The usage is as follows:
@def_discrete_system mutable struct MyDiscreteSystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDiscreteSystem
param1::T1 = param1_default # optional field
param2::T2 = param2_default # optional field
param3::T3 = param3_default # optional field
⋮
paramN::TN = paramN_default # optional field
righthandside::RH = righthandside_function # mandatory field
readout::RO = readout_function # mandatory field
state::ST = state_default # mandatory field
input::IP = input_default # mandatory field
output::OP = output_default # mandatory field
end
Here, MyDiscreteSystem
has N
parameters. MyDiscreteSystem
is represented by the righthandside
and readout
function. state
, input
and output
is the state, input port and output port of MyDiscreteSystem
.
righthandside
must have the signature
function righthandside(dx, x, u, t, args...; kwargs...)
dx .= .... # update dx
end
and readout
must have the signature
function readout(x, u, t)
y = ...
return y
end
New discrete system must be a subtype of AbstractDiscreteSystem
to function properly.
Example
julia> @def_discrete_system mutable struct MyDiscreteSystem{RH, RO, IP, OP} <: AbstractDiscreteSystem
α::Float64 = 1.
β::Float64 = 2.
righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))
state::Vector{Float64} = [1.]
readout::RO = (x, u, t) -> x
input::IP = Inport(1)
output::OP = Outport(1)
end
julia> ds = MyDiscreteSystem();
julia> ds.input
1-element Inport{Inpin{Float64}}:
Inpin(eltype:Float64, isbound:false)
Causal.DiscreteSystem
— Typemutable struct DiscreteSystem{RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
A generic discrete system
Fields
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be an
Inport
orNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Example
julia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);
julia> ofuncdiscrete(x, u, t) = x;
julia> DiscreteSystem(righthandside=sfuncdiscrete, readout=ofuncdiscrete, state=[1.], input=nothing, output=Outport())
DiscreteSystem(righthandside:sfuncdiscrete, readout:ofuncdiscrete, state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))
Causal.DiscreteLinearSystem
— Typemutable struct DiscreteLinearSystem{T1<:(AbstractArray{var"#s301",2} where var"#s301"<:Real), T2<:(AbstractArray{var"#s300",2} where var"#s300"<:Real), T3<:(AbstractArray{var"#s299",2} where var"#s299"<:Real), T4<:(AbstractArray{var"#s298",2} where var"#s298"<:Real), IP<:(Union{var"#s297", var"#s296"} where var"#s296"<:Nothing where var"#s297"<:Inport), OP<:(Union{var"#s295", var"#s294"} where var"#s294"<:Nothing where var"#s295"<:Outport), ST<:(AbstractArray{var"#s293",1} where var"#s293"<:Real), RH, RO, var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a DiscreteLinearSystem
with input
and output
. 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 differential equation of the system.
The DiscreteLinearSystem
is represented by the following state and output equations.
\[\begin{array}{l} \dot{x} = A x + B u \\[0.25cm] y = C x + D u \end{array}\]
where $x$ is state
. solver
is used to solve the above differential equation.
Fields
A::AbstractArray{var"#s301",2} where var"#s301"<:Real
A
B::AbstractArray{var"#s300",2} where var"#s300"<:Real
B
C::AbstractArray{var"#s299",2} where var"#s299"<:Real
C
D::AbstractArray{var"#s298",2} where var"#s298"<:Real
D
input::Union{var"#s297", var"#s296"} where var"#s296"<:Nothing where var"#s297"<:Inport
Input. Expected to an
Inport
orNothing
output::Union{var"#s295", var"#s294"} where var"#s294"<:Nothing where var"#s295"<:Outport
Output port
state::AbstractArray{var"#s293",1} where var"#s293"<:Real
State
righthandside::Any
Right-hand-side function
readout::Any
Readout function
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Causal.HenonSystem
— Typemutable struct HenonSystem{T1<:Real, T2<:Real, T3<:Real, RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a Henon
system evolving with the dynamics
\[\begin{array}{l} \dot{x}_1 = 1 - \alpha (x_1^2) + x_2 \\[0.25cm] \dot{x}_2 = \beta x_1 \end{array}\]
Fields
α::Real
α
β::Real
β
γ::Real
γ
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be an
Inport
ofNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Causal.LoziSystem
— Typemutable struct LoziSystem{T1<:Real, T2<:Real, T3<:Real, RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a Lozi
system evolving with the dynamics
\[\begin{array}{l} \dot{x}_1 = 1 - \alpha |x_1| + x_2 \\[0.25cm] \dot{x}_2 = \beta x_1 \end{array}\]
Fields
α::Real
α
β::Real
β
γ::Real
γ
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be an
Inport
orNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Causal.BogdanovSystem
— Typemutable struct BogdanovSystem{T1<:Real, T2<:Real, T3<:Real, T4<:Real, RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a Bogdanov system with equations
\[\begin{array}{l} \dot{x}_1 = x_1 + \dot{x}_2 \\[0.25cm] \dot{x}_2 = x_2 + \epsilon + x_2 + k x_1 (x_1 - 1) + \mu x_1 x_2 \end{array}\]
Fields
ε::Real
ε
μ::Real
μ
k::Real
k
γ::Real
γ
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be an
Inport
orNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Causal.GingerbreadmanSystem
— Typemutable struct GingerbreadmanSystem{T1<:Real, RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a GingerbreadmanSystem with the dynamics
\[\begin{array}{l} \dot{x}_1 = 1 - x_2 + |x_1|\\[0.25cm] \dot{x}_2 = x_1 \end{array}\]
Fields
γ::Real
γ
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be
Inport
orNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any
Causal.LogisticSystem
— Typemutable struct LogisticSystem{T1<:Real, T2<:Real, RH, RO, ST<:(AbstractArray{var"#s301",1} where var"#s301"<:Real), IP<:(Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport), OP<:(Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport), var"253", var"254", var"255", Symbol, var"256", Float64, var"257", var"258", var"259", var"260", var"261", var"262"} <: AbstractDiscreteSystem
Constructs a LogisticSystem with the dynamics
\[\begin{array}{l} \dot{x} = r x (1 - x) \end{array}\]
Fields
r::Real
r
γ::Real
γ
righthandside::Any
Right-hand-side function
readout::Any
Readout function
state::AbstractArray{var"#s301",1} where var"#s301"<:Real
State
input::Union{var"#s300", var"#s299"} where var"#s299"<:Nothing where var"#s300"<:Inport
Input. Expected to be an
Inport
orNothing
output::Union{var"#s298", var"#s297"} where var"#s297"<:Nothing where var"#s298"<:Outport
Output port
trigger::Any
handshake::Any
callbacks::Any
name::Any
id::Any
t::Any
modelargs::Any
modelkwargs::Any
solverargs::Any
solverkwargs::Any
alg::Any
integrator::Any