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, Sources 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_sourceMacro
@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.

Warning

output and readout are mandatory fields to define a new source. The rest of the fields are the parameters of the source.

Warning

readout must be a single-argument function, i.e. a fucntion of time t.

Warning

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)
source
Causal.FunctionGeneratorType
FunctionGenerator(; 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
source
Causal.SinewaveGeneratorType
SinewaveGenerator(;amplitude=1., frequency=1., phase=0., delay=0., offset=0.)

Constructs a SinewaveGenerator with output of the form

\[ x(t) = A sin(2 \pi f (t - \tau) + \phi) + B\]

where $A$ is amplitude, $f$ is frequency, $\tau$ is delay and $\phi$ is phase and $B$ is offset.

source
Causal.DampedSinewaveGeneratorType
DampedSinewaveGenerator(;amplitude=1., decay=-0.5, frequency=1., phase=0., delay=0., offset=0.)

Constructs a DampedSinewaveGenerator which generates outputs of the form

\[ x(t) = A e^{\alpha t} sin(2 \pi f (t - \tau) + \phi) + B\]

where $A$ is amplitude, $\alpha$ is decay, $f$ is frequency, $\phi$ is phase, $\tau$ is delay and $B$ is offset.

source
Causal.SquarewaveGeneratorType
SquarewaveGenerator(;level1=1., level2=0., period=1., duty=0.5, delay=0.)

Constructs a SquarewaveGenerator with output of the form

\[ x(t) = \left\{\begin{array}{lr} A_1 + B, & kT + \tau \leq t \leq (k + \alpha) T + \tau \\ A_2 + B, & (k + \alpha) T + \tau \leq t \leq (k + 1) T + \tau \end{array} \right. \quad k \in Z\]

where $A_1$, $A_2$ is level1 and level2, $T$ is period, $\tau$ is delay $\alpha$ is duty.

source
Causal.TriangularwaveGeneratorType
TriangularwaveGenerator(;amplitude=1, period=1, duty=0.5, delay=0, offset=0)

Constructs a TriangularwaveGenerator with output of the form

\[ x(t) = \left\{\begin{array}{lr} \dfrac{A t}{\alpha T} + B, & kT + \tau \leq t \leq (k + \alpha) T + \tau \\[0.25cm] \dfrac{A (T - t)}{T (1 - \alpha)} + B, & (k + \alpha) T + \tau \leq t \leq (k + 1) T + \tau \end{array} \right. \quad k \in Z\]

where $A$ is amplitude, $T$ is period, $\tau$ is delay $\alpha$ is duty.

source
Causal.ConstantGeneratorType
ConstantGenerator(;amplitude=1.)

Constructs a ConstantGenerator with output of the form

\[ x(t) = A\]

where $A$ is `amplitude.

source
Causal.RampGeneratorType
RampGenerator(;scale=1, delay=0.)

Constructs a RampGenerator with output of the form

\[ x(t) = \alpha (t - \tau)\]

where $\alpha$ is the scale and $\tau$ is delay.

source
Causal.StepGeneratorType
StepGenerator(;amplitude=1, delay=0, offset=0)

Constructs a StepGenerator with output of the form

\[ x(t) = \left\{\begin{array}{lr} B, & t \leq \tau \\ A + B, & t > \tau \end{array} \right.\]

where $A$ is amplitude, $B$ is the offset and $\tau$ is the delay.

source
Causal.ExponentialGeneratorType
ExponentialGenerator(;scale=1, decay=-1, delay=0.)

Constructs an ExponentialGenerator with output of the form

\[ x(t) = A e^{\alpha (t - \tau)}\]

where $A$ is scale, $\alpha$ is decay and $\tau$ is delay.

source
Causal.DampedExponentialGeneratorType
DampedExponentialGenerator(;scale=1, decay=-1, delay=0.)

Constructs an DampedExponentialGenerator with outpsuts of the form

\[ x(t) = A (t - \tau) e^{\alpha (t - \tau)}\]

where $A$ is scale, $\alpha$ is decay, $\tau$ is delay.

source