Generators
Basic Operation AbstractSource
An AbstractSource
is a subtype of AbstractComponent
. (See Components for more information.) An AbstractComponent
has input
port and output
port for data flow. The AbstractComponent
reads data from the input
port and writes data to output
port. Since the input-output relation of AbstractSource
depends on just the current time t
, Source
s do not have input
ports since they do not read input values. They just need time t
to compute its output. During their evolution, an AbstractComponent
reads time t
from its trigger
pins, computes its output according to its output function and writes its computed output to its output
ports. An AbstractComponent
also writes true
to their handshake
pin to signal that the evolution is succeeded. To further clarify the operation of AbstractSource
, let us do some examples.
julia> using Causal # hide
julia> f(t) = t * exp(t) + sin(t)
f (generic function with 1 method)
julia> gen = FunctionGenerator(readout=f)
FunctionGenerator(readout:f, output:Outport(numpins:1, eltype:Outpin{Float64}))
We constructed a FunctionGenerator
which is an AbstractSource
.
julia> gen isa AbstractSource
true
To drive gen
, that is to make gen
evolve, we need to launch gen
. To this end, we construct ports and pins for input-output and signaling.
julia> trg, hnd, iport = Outpin(), Inpin{Bool}(), Inport(length(gen.output))
(Outpin(eltype:Float64, isbound:false), Inpin(eltype:Bool, isbound:false), Inport(numpins:1, eltype:Inpin{Float64}))
julia> connect!(gen.output, iport)
1-element Array{Link{Float64},1}:
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect!(trg, gen.trigger)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect!(gen.handshake, hnd)
Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
julia> t = launch(gen)
Task (runnable) @0x00007fe0d87f8280
julia> tout = @async while true
all(take!(iport) .=== NaN) && break
end
Task (runnable) @0x00007fe0d97ef820
At this moment, gen
is ready to be triggered from its trigger
link. Note that the trigger link gen.trigger
and the output gen.output
of gen
are writable.
julia> gen.trigger.link
Link(state:open, eltype:Float64, isreadable:false, iswritable:true)
julia> gen.output[1].links[1]
Link(state:open, eltype:Float64, isreadable:false, iswritable:true)
gen
is triggered by writing time t
to trg
julia> put!(trg, 1.)
When triggered gen
writes true
to its handshake link gen.handshake
which can be read from hnd
.
julia> hnd.link
Link(state:open, eltype:Bool, isreadable:true, iswritable:false)
and to drive gen
for another time hnd
must be read.
julia> take!(hnd)
true
Now continue driving gen
.
julia> for t in 2. : 10.
put!(trg, t)
take!(hnd)
end
When triggered, the output of gen
is written to its output gen.output
.
julia> gen.output[1].links[1].buffer
64-element Buffer{Cyclic,Float64,1}:
220264.11392695628
72928.1674666637
23848.65325458045
7677.0890955979285
2420.2933454582117
741.1068712382199
217.635797637269
60.39773077762287
15.687409624686982
3.5597528132669414
⋮
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
Causal
provides some other function generators which are documented in the following section.
Full API
Causal.@def_source
— Macro@def_source ex
where ex
is the expression to define to define a new AbstractSource component type. The usage is as follows:
@def_source struct MySource{T1,T2,T3,...,TN,OP, RO} <: AbstractSource
param1::T1 = param1_default # optional field
param2::T2 = param2_default # optional field
param3::T3 = param3_default # optional field
⋮
paramN::TN = paramN_default # optional field
output::OP = output_default # mandatory field
readout::RO = readout_function # mandatory field
end
Here, MySource
has N
parameters, an output
port and a readout
function.
output
and readout
are mandatory fields to define a new source. The rest of the fields are the parameters of the source.
readout
must be a single-argument function, i.e. a fucntion of time t
.
New source must be a subtype of AbstractSource
to function properly.
Example
julia> @def_source struct MySource{OP, RO} <: AbstractSource
a::Int = 1
b::Float64 = 2.
output::OP = Outport()
readout::RO = t -> (a + b) * sin(t)
end
julia> gen = MySource();
julia> gen.a
1
julia> gen.output
1-element Outport{Outpin{Float64}}:
Outpin(eltype:Float64, isbound:false)
Causal.FunctionGenerator
— TypeFunctionGenerator(; readout, output=Outport())
Constructs a generic function generator with readout
function and output
port.
Example
julia> gen = FunctionGenerator(readout = t -> [t, 2t], output = Outport(2));
julia> gen.readout(1.)
2-element Array{Float64,1}:
1.0
2.0
Causal.SinewaveGenerator
— TypeSinewaveGenerator(;amplitude=1., frequency=1., phase=0., delay=0., offset=0.)
Constructs a SinewaveGenerator
with output of the form
where $A$ is amplitude
, $f$ is frequency
, $\tau$ is delay
and $\phi$ is phase
and $B$ is offset
.
Causal.DampedSinewaveGenerator
— TypeDampedSinewaveGenerator(;amplitude=1., decay=-0.5, frequency=1., phase=0., delay=0., offset=0.)
Constructs a DampedSinewaveGenerator
which generates outputs of the form
where $A$ is amplitude
, $\alpha$ is decay
, $f$ is frequency
, $\phi$ is phase
, $\tau$ is delay
and $B$ is offset
.
Causal.SquarewaveGenerator
— TypeSquarewaveGenerator(;level1=1., level2=0., period=1., duty=0.5, delay=0.)
Constructs a SquarewaveGenerator
with output of the form
where $A_1$, $A_2$ is level1
and level2
, $T$ is period
, $\tau$ is delay
$\alpha$ is duty
.
Causal.TriangularwaveGenerator
— TypeTriangularwaveGenerator(;amplitude=1, period=1, duty=0.5, delay=0, offset=0)
Constructs a TriangularwaveGenerator
with output of the form
where $A$ is amplitude
, $T$ is period
, $\tau$ is delay
$\alpha$ is duty
.
Causal.ConstantGenerator
— TypeConstantGenerator(;amplitude=1.)
Constructs a ConstantGenerator
with output of the form
where $A$ is `amplitude.
Causal.RampGenerator
— TypeRampGenerator(;scale=1, delay=0.)
Constructs a RampGenerator
with output of the form
where $\alpha$ is the scale
and $\tau$ is delay
.
Causal.StepGenerator
— TypeStepGenerator(;amplitude=1, delay=0, offset=0)
Constructs a StepGenerator
with output of the form
where $A$ is amplitude
, $B$ is the offset
and $\tau$ is the delay
.
Causal.ExponentialGenerator
— TypeExponentialGenerator(;scale=1, decay=-1, delay=0.)
Constructs an ExponentialGenerator
with output of the form
where $A$ is scale
, $\alpha$ is decay
and $\tau$ is delay
.
Causal.DampedExponentialGenerator
— TypeDampedExponentialGenerator(;scale=1, decay=-1, delay=0.)
Constructs an DampedExponentialGenerator
with outpsuts of the form
where $A$ is scale
, $\alpha$ is decay
, $\tau$ is delay
.