DDESystem
Construction of DDESystem
A DDESystem
is represented by the following state equation
where $t$ is the time, $x$ is the value of the state
, $u$ is the value of the input
. $h$ is the history function for which
and by the output equation
where $y$ is the value of the output
.
As an example, consider a system with the state equation
First, we define the history function histfunc
,
julia> const out = zeros(1)
1-element Array{Float64,1}:
0.0
julia> histfunc(out, u, t) = (out .= 1.);
Note that histfunc
mutates a vector out
. This mutation is for performance reasons
. Next the state function can be defined
julia> function statefunc(dx, x, h, u, t)
h(out, u, t - tau) # Update out vector
dx[1] = out[1] + x[1]
end
statefunc (generic function with 1 method)
and let us take all the state variables as outputs. Thus, the output function is
julia> outputfunc(x, u, t) = x
outputfunc (generic function with 1 method)
Next, we need to define the history
for the system. History is defined by specifying a history function, and the type of the lags. There may be two different lag: constant lags which are independent of the state variable $x$ and the dependent lags which are mainly the functions of the state variable $x$. Note that for this example, the have constant lags. Thus,
julia> tau = 1
1
julia> conslags = [tau]
1-element Array{Int64,1}:
1
julia> hist = History(histfunc, conslags, ())
ERROR: UndefVarError: History not defined
At this point, we are ready to construct the system.
julia> ds = DDESystem((statefunc, histfunc), outputfunc, [1.], 0., nothing, Outport())
DDESystem(state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))
Basic Operation of DDESystem
The basis operaiton of DDESystem
is the same as those of other dynamical systems. When triggered from its trigger
link, the DDESystem
reads its time from its trigger
link, reads input, solves its differential equation, computes its output and writes the computed output to its output
bus. To drive DDESystem
, we must first launch it,
julia> iport, trg, hnd = Inport(), 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) @0x00007fa673257340
julia> task2 = @async while true
all(take!(iport) .=== NaN) && break
end
Task (runnable) @0x00007fa670d1f0d0
When launched, ds
is drivable. To drive ds
, we can use the syntax drive(ds, t)
or put!(ds.trigger, t)
where t
is the time until which ds
is to be driven.
julia> put!(trg, 1.)
When driven, ds
reads the time t
from its trigger
link, (since its input is nothing
, ds
does nothing during its input reading stage), solves its differential equation, computes output and writes the value of its output to its output
bus. To signify, the step was taken with success, ds
writes true
to its handshake
which must be read to further drive ds
. For this, we can use the syntax approve(ds)
or take!(ds.handshake)
.
julia> take!(hnd)
true
We can continue to drive ds
.
julia> for t in 2. : 10.
put!(trg, t)
take!(hnd)
end
When launched, we constructed a task
whose state is running
which implies that ds
can be driven.
julia> task
Task (runnable) @0x00007fa673257340
julia> task2
Task (runnable) @0x00007fa670d1f0d0
As long as the state of the task
is running
, ds
can be driven. To terminate task
safely, we need to terminate the ds
.
julia> put!(trg, NaN)
Note that the state of task
is done
which implies that ds
is not drivable any more.
Note that the output values of ds
is written to its output
bus.
julia> iport[1].link.buffer
64-element Buffer{Cyclic,Float64,1}:
436466.8181121704
121540.54530401707
33844.744019167716
9424.577256277034
2624.411352804969
730.8063984951228
203.50408965546976
56.667448342646395
15.778109354779708
4.436563289075523
⋮
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
Full API
Jusdl.DDESystem
— TypeDDESystem(input, output, statefunc, outputfunc, state, t, modelargs=(), solverargs=();
alg=DDEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())
Constructs a DDESystem
with input
and output
. statefunc
is the state function and outputfunc
is the output function of DDESystem
. 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 DDESystem
is represented by
where $t$ is the time t
, $x$ is the value of state
, $u$ is the value of input
, $y$ is the value of output
. $f$ is statefunc
, $g$ is outputfunc
. $h$is the history function of history
. solver
is used to solve the above differential equation.
The syntax of statefunc
must be of the form
function statefunc(dx, x, u, t)
dx .= ... # Update dx
end
and the syntax of outputfunc
must be of the form
function outputfunc(x, u, t)
y = ... # Compute y
return y
end
Example
julia> const out = zeros(1);
julia> histfunc(out, u, t) = (out .= 1.);
julia> function sfuncdde(dx, x, h, u, t)
h(out, u, t - tau) # Update out vector
dx[1] = out[1] + x[1]
end;
julia> ofuncdde(x, u, t) = x;
julia> tau = 1;
julia> conslags = [tau];
julia> DDESystem((sfuncdde, histfunc), ofuncdde, [1.], 0., nothing, Outport())
DDESystem(state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))
See DifferentialEquations for more information about modelargs
, modelkwargs
, solverargs
solverkwargs
and alg
.