diff --git a/Project.toml b/Project.toml index fcca3c20..ff8bea32 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Causal" uuid = "c45f814d-238a-4fdc-b3d7-673e55950ac7" authors = ["Zekeriya Sarı ", "Serkan Günel "] -version = "1.0.0" +version = "0.3.0" [deps] DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" diff --git a/docs/build/index.html b/docs/build/index.html index 3e842476..5800fc05 100644 --- a/docs/build/index.html +++ b/docs/build/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Home · Causal

Causal

Causal enables fast and effective systems simulations together with online and offline data analysis. In Causal, it is possible to simulate discrete-time and continuous-time, static or dynamical systems. In particular, it is possible to simulate dynamical systems modeled by different types of differential equations such as ODE (Ordinary Differential Equation), Random Ordinary Differential Equation (RODE), SDE (Stochastic Differential Equation), DDE (Delay Differential Equation) and DAE (Differential Algebraic Equation), and discrete difference equations. During the simulation, the data flowing through the links of the model can be processed online and offline and specialized analyzes can be performed. These analyses can also be enriched with plugins that can easily be defined using the standard Julia library or various Julia packages. The simulation is performed by evolving the components individually and in parallel during sampling time intervals. The individual evolution of the components allows the simulation of the models that include components represented by different kinds of mathematical equations.

Installation

Installation of Causal is the similar to any other registered Julia package. Start a Julia session and type

] add Causal
-======= -Home · Jusdl

Jusdl

Jusdl enables fast and effective systems simulations together with online and offline data analysis. In Jusdl, it is possible to simulate discrete-time and continuous-time, static or dynamical systems. In particular, it is possible to simulate dynamical systems modeled by different types of differential equations such as ODE (Ordinary Differential Equation), Random Ordinary Differential Equation (RODE), SDE (Stochastic Differential Equation), DDE (Delay Differential Equation) and DAE (Differential Algebraic Equation), and discrete difference equations. During the simulation, the data flowing through the links of the model can be processed online and offline and specialized analyzes can be performed. These analyses can also be enriched with plugins that can easily be defined using the standard Julia library or various Julia packages. The simulation is performed by evolving the components individually and in parallel during sampling time intervals. The individual evolution of the components allows the simulation of the models that include components represented by different kinds of mathematical equations.

Installation

Installation of Jusdl is the similar to any other registered Julia package. Start a Julia session and type

] add Jusdl
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Home · Causal

Causal

Causal enables fast and effective systems simulations together with online and offline data analysis. In Causal, it is possible to simulate discrete-time and continuous-time, static or dynamical systems. In particular, it is possible to simulate dynamical systems modeled by different types of differential equations such as ODE (Ordinary Differential Equation), Random Ordinary Differential Equation (RODE), SDE (Stochastic Differential Equation), DDE (Delay Differential Equation) and DAE (Differential Algebraic Equation), and discrete difference equations. During the simulation, the data flowing through the links of the model can be processed online and offline and specialized analyzes can be performed. These analyses can also be enriched with plugins that can easily be defined using the standard Julia library or various Julia packages. The simulation is performed by evolving the components individually and in parallel during sampling time intervals. The individual evolution of the components allows the simulation of the models that include components represented by different kinds of mathematical equations.

Installation

Installation of Causal is the similar to any other registered Julia package. Start a Julia session and type

] add Causal
diff --git a/docs/build/manual/components/componentsbase/evolution/index.html b/docs/build/manual/components/componentsbase/evolution/index.html index 9d3ccaff..de3986e2 100644 --- a/docs/build/manual/components/componentsbase/evolution/index.html +++ b/docs/build/manual/components/componentsbase/evolution/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Evolution of Components · Causal

Evolution of Components

In Causal, the simulation of a model is performed by individual evolution of components (see Modeling and Simulation for more information of modeling and simulation adopted in Causal). Basically, when triggered through its trigger pin, based on its type, a component takes a forward step as follows,

  1. The next clock time t is read from its trigger pin.
  2. The next input value u(t) is read from from its input port,
  3. The component evolves from its current time t - dt to the current clock time t
  4. Using the state variable x(t) at time t, current clock time t and u(t), the next output value y(t) is computed.
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

or a backward step as follows.

  1. The next clock time t is read from its trigger pin.
  2. Using the state variable x(t - dt) at time t - dt, current component time t - dt and u(t - dt), the next output value y(t) is computed.
  3. The next input value u(t) is read from from its input port,
  4. The component evolves from its current time t - dt to the current clock time t
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

Here dt is the simulation step size.

Reading Time

Reading State

Causal.readstateFunction
readstate(comp::AbstractComponent)

Returns the state of comp if comp is AbstractDynamicSystem. Otherwise, returns nothing.

source

Reading Input

Writing Output

Causal.writeoutput!Function
writeoutput!(comp::AbstractComponent, out)

Writes out to the output of comp if the output of comp is Outport. Otherwise, does nothing.

source

Computing Output

Causal.computeoutputFunction
computeoutput(comp, x, u, t)

Computes the output of comp according to its readout if readout is not nothing. Otherwise, nothing is done. x is the state, u is the value of input, t is the time.

source

Evolve

Causal.evolve!Function
evolve!(comp::AbstractSource, u, t)

Does nothing. u is the value of input and t is time.

evolve!(comp::AbstractSink, u, t)

Writes t to time buffer timebuf and u to databuf of comp. u is the value of input and t is time.

evolve!(comp::AbstractStaticSystem, u, t)

Writes u to buffer of comp if comp is an AbstractMemory. Otherwise, nothing is done. u is the value of input and t is time.

evolve!(comp::AbstractDynamicSystem, u, t)

Solves the differential equation of the system of comp for the time interval (comp.t, t) for the inital condition x where x is the current state of comp . u is the input function defined for (comp.t, t). The comp is updated with the computed state and time t.

source

Taking Steps

Causal.forwardstepFunction
forwardstep(comp, t)

Makes comp takes a forward step. The input value u and state x of comp are read. Using x, u and time t, comp is evolved. The output y of comp is computed and written into the output bus of comp.

source
Causal.backwardstepFunction
backwardstep(comp, t)

Reads the state x. Using the time t and x, computes and writes the ouput value y of comp. Then, the input value u is read and comp is evolved.

source
Causal.approve!Function
approve!(comp::AbstractComponent)

Read handshake link of comp. When not approved or false is read from the handshake link, the task launched for the trigger link of comp gets stuck during comp is taking step.

source
approve!(comp::AbstractSubSystem)

Approves comp by approving each subcomponent of comp. See also: approve!(comp::AbstractComponent)

source
Causal.terminate!Function
terminate!(comp::AbstractComponent)

Closes the trigger link and output bus of comp.

source
terminate!(comp::AbstractSubSystem)

Terminates comp by terminating each subcomponent of comp. See also: terminate!(comp::AbstractComponent)

source
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
-======= -Evolution of Components · Jusdl

Evolution of Components

In Jusdl, the simulation of a model is performed by individual evolution of components (see Modeling and Simulation for more information of modeling and simulation adopted in Jusdl). Basically, when triggered through its trigger pin, based on its type, a component takes a forward step as follows,

  1. The next clock time t is read from its trigger pin.
  2. The next input value u(t) is read from from its input port,
  3. The component evolves from its current time t - dt to the current clock time t
  4. Using the state variable x(t) at time t, current clock time t and u(t), the next output value y(t) is computed.
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

or a backward step as follows.

  1. The next clock time t is read from its trigger pin.
  2. Using the state variable x(t - dt) at time t - dt, current component time t - dt and u(t - dt), the next output value y(t) is computed.
  3. The next input value u(t) is read from from its input port,
  4. The component evolves from its current time t - dt to the current clock time t
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

Here dt is the simulation step size.

Reading Time

Reading State

Jusdl.readstateFunction
readstate(comp::AbstractComponent)

Returns the state of comp if comp is AbstractDynamicSystem. Otherwise, returns nothing.

source

Reading Input

Writing Output

Jusdl.writeoutput!Function
writeoutput!(comp::AbstractComponent, out)

Writes out to the output of comp if the output of comp is Outport. Otherwise, does nothing.

source

Computing Output

Jusdl.computeoutputFunction
computeoutput(comp, x, u, t)

Computes the output of comp according to its readout if readout is not nothing. Otherwise, nothing is done. x is the state, u is the value of input, t is the time.

source

Evolve

Jusdl.evolve!Function
evolve!(comp::AbstractSource, u, t)

Does nothing. u is the value of input and t is time.

evolve!(comp::AbstractSink, u, t)

Writes t to time buffer timebuf and u to databuf of comp. u is the value of input and t is time.

evolve!(comp::AbstractStaticSystem, u, t)

Writes u to buffer of comp if comp is an AbstractMemory. Otherwise, nothing is done. u is the value of input and t is time.

evolve!(comp::AbstractDynamicSystem, u, t)

Solves the differential equation of the system of comp for the time interval (comp.t, t) for the inital condition x where x is the current state of comp . u is the input function defined for (comp.t, t). The comp is updated with the computed state and time t.

source

Taking Steps

Jusdl.forwardstepFunction
forwardstep(comp, t)

Makes comp takes a forward step. The input value u and state x of comp are read. Using x, u and time t, comp is evolved. The output y of comp is computed and written into the output bus of comp.

source
Jusdl.backwardstepFunction
backwardstep(comp, t)

Reads the state x. Using the time t and x, computes and writes the ouput value y of comp. Then, the input value u is read and comp is evolved.

source
Jusdl.approve!Function
approve!(comp::AbstractComponent)

Read handshake link of comp. When not approved or false is read from the handshake link, the task launched for the trigger link of comp gets stuck during comp is taking step.

source
approve!(comp::AbstractSubSystem)

Approves comp by approving each subcomponent of comp. See also: approve!(comp::AbstractComponent)

source
Jusdl.terminate!Function
terminate!(comp::AbstractComponent)

Closes the trigger link and output bus of comp.

source
terminate!(comp::AbstractSubSystem)

Terminates comp by terminating each subcomponent of comp. See also: terminate!(comp::AbstractComponent)

source
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Evolution of Components · Causal

Evolution of Components

In Causal, the simulation of a model is performed by individual evolution of components (see Modeling and Simulation for more information of modeling and simulation adopted in Causal). Basically, when triggered through its trigger pin, based on its type, a component takes a forward step as follows,

  1. The next clock time t is read from its trigger pin.
  2. The next input value u(t) is read from from its input port,
  3. The component evolves from its current time t - dt to the current clock time t
  4. Using the state variable x(t) at time t, current clock time t and u(t), the next output value y(t) is computed.
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

or a backward step as follows.

  1. The next clock time t is read from its trigger pin.
  2. Using the state variable x(t - dt) at time t - dt, current component time t - dt and u(t - dt), the next output value y(t) is computed.
  3. The next input value u(t) is read from from its input port,
  4. The component evolves from its current time t - dt to the current clock time t
  5. The component writes true to its handshake pin to signal that taking step is performed with success.

Here dt is the simulation step size.

Reading Time

Reading State

Causal.readstateFunction
readstate(comp::AbstractComponent)

Returns the state of comp if comp is AbstractDynamicSystem. Otherwise, returns nothing.

source

Reading Input

Writing Output

Causal.writeoutput!Function
writeoutput!(comp::AbstractComponent, out)

Writes out to the output of comp if the output of comp is Outport. Otherwise, does nothing.

source

Computing Output

Causal.computeoutputFunction
computeoutput(comp, x, u, t)

Computes the output of comp according to its readout if readout is not nothing. Otherwise, nothing is done. x is the state, u is the value of input, t is the time.

source

Evolve

Causal.evolve!Function
evolve!(comp::AbstractSource, u, t)

Does nothing. u is the value of input and t is time.

evolve!(comp::AbstractSink, u, t)

Writes t to time buffer timebuf and u to databuf of comp. u is the value of input and t is time.

evolve!(comp::AbstractStaticSystem, u, t)

Writes u to buffer of comp if comp is an AbstractMemory. Otherwise, nothing is done. u is the value of input and t is time.

evolve!(comp::AbstractDynamicSystem, u, t)

Solves the differential equation of the system of comp for the time interval (comp.t, t) for the inital condition x where x is the current state of comp . u is the input function defined for (comp.t, t). The comp is updated with the computed state and time t.

source

Taking Steps

Causal.forwardstepFunction
forwardstep(comp, t)

Makes comp takes a forward step. The input value u and state x of comp are read. Using x, u and time t, comp is evolved. The output y of comp is computed and written into the output bus of comp.

source
Causal.backwardstepFunction
backwardstep(comp, t)

Reads the state x. Using the time t and x, computes and writes the ouput value y of comp. Then, the input value u is read and comp is evolved.

source
Causal.approve!Function
approve!(comp::AbstractComponent)

Read handshake link of comp. When not approved or false is read from the handshake link, the task launched for the trigger link of comp gets stuck during comp is taking step.

source
approve!(comp::AbstractSubSystem)

Approves comp by approving each subcomponent of comp. See also: approve!(comp::AbstractComponent)

source
Causal.terminate!Function
terminate!(comp::AbstractComponent)

Closes the trigger link and output bus of comp.

source
terminate!(comp::AbstractSubSystem)

Terminates comp by terminating each subcomponent of comp. See also: terminate!(comp::AbstractComponent)

source
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
diff --git a/docs/build/manual/components/componentsbase/hierarchy/index.html b/docs/build/manual/components/componentsbase/hierarchy/index.html index e8dfe934..2a6a6a8c 100644 --- a/docs/build/manual/components/componentsbase/hierarchy/index.html +++ b/docs/build/manual/components/componentsbase/hierarchy/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Component Type Hierarchy · Causal

Component Type Hierarchy

Causal.AbstractDiscreteSystemType
abstract type AbstractDiscreteSystem <: AbstractDynamicSystem

Abstract type of all dynamic systems modelled by dicrete difference equations.

source
Causal.AbstractODESystemType
abstract type AbstractODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by ordinary differential equations.

source
Causal.AbstractRODESystemType
abstract type AbstractRODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by random ordinary differential equations.

source
Causal.AbstractDAESystemType
abstract type AbstractDAESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by differential algebraic equations

source
Causal.AbstractSDESystemType
abstract type AbstractSDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by stochastic differential equations.

source
Causal.AbstractDDESystemType
abstract type AbstractDDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modlled by delay dynamical systems.

source
-======= -Component Type Hierarchy · Jusdl

Component Type Hierarchy

Jusdl.AbstractDiscreteSystemType
abstract type AbstractDiscreteSystem <: AbstractDynamicSystem

Abstract type of all dynamic systems modelled by dicrete difference equations.

source
Jusdl.AbstractODESystemType
abstract type AbstractODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by ordinary differential equations.

source
Jusdl.AbstractRODESystemType
abstract type AbstractRODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by random ordinary differential equations.

source
Jusdl.AbstractDAESystemType
abstract type AbstractDAESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by differential algebraic equations

source
Jusdl.AbstractSDESystemType
abstract type AbstractSDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by stochastic differential equations.

source
Jusdl.AbstractDDESystemType
abstract type AbstractDDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modlled by delay dynamical systems.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Component Type Hierarchy · Causal

Component Type Hierarchy

Causal.AbstractDiscreteSystemType
abstract type AbstractDiscreteSystem <: AbstractDynamicSystem

Abstract type of all dynamic systems modelled by dicrete difference equations.

source
Causal.AbstractODESystemType
abstract type AbstractODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by ordinary differential equations.

source
Causal.AbstractRODESystemType
abstract type AbstractRODESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by random ordinary differential equations.

source
Causal.AbstractDAESystemType
abstract type AbstractDAESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by differential algebraic equations

source
Causal.AbstractSDESystemType
abstract type AbstractSDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modelled by stochastic differential equations.

source
Causal.AbstractDDESystemType
abstract type AbstractDDESystem <: AbstractDynamicSystem

Abstract type of all dynamical systems modlled by delay dynamical systems.

source
diff --git a/docs/build/manual/components/componentsbase/interpolation/index.html b/docs/build/manual/components/componentsbase/interpolation/index.html index 179cc1e4..9885089c 100644 --- a/docs/build/manual/components/componentsbase/interpolation/index.html +++ b/docs/build/manual/components/componentsbase/interpolation/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Interpolation · Causal

Interpolation

Full API

Causal.InterpolantType
Interpolant(tinit, tfinal, coefinit, coeffinal)

Constructs a linnear interpolant that interpolates between the poinsts (tinit, coefinit) and (tfinal, coeffinal).

source
Causal.update!Method
update!(intepolant)

Updates interpolant using the data in timebuf and databuf of interpolant.

source
-======= -Interpolation · Jusdl

Interpolation

Full API

Jusdl.InterpolantType
Interpolant(tinit, tfinal, coefinit, coeffinal)

Constructs a linnear interpolant that interpolates between the poinsts (tinit, coefinit) and (tfinal, coeffinal).

source
Jusdl.update!Method
update!(intepolant)

Updates interpolant using the data in timebuf and databuf of interpolant.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Interpolation · Causal

Interpolation

Full API

Causal.InterpolantType
Interpolant(tinit, tfinal, coefinit, coeffinal)

Constructs a linnear interpolant that interpolates between the poinsts (tinit, coefinit) and (tfinal, coeffinal).

source
Causal.update!Method
update!(intepolant)

Updates interpolant using the data in timebuf and databuf of interpolant.

source
diff --git a/docs/build/manual/components/sinks/printer/index.html b/docs/build/manual/components/sinks/printer/index.html index e8397c5c..15e8ca9d 100644 --- a/docs/build/manual/components/sinks/printer/index.html +++ b/docs/build/manual/components/sinks/printer/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Printer · Causal

Printer

Basic Operation of Printers

See Basic Operation of Writers since the operation of Writer and that of Printer is very similar.

Full API

Causal.PrinterType

Printer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol()) where T Constructs a Printer with input bus input. buflen is the length of its internal buflen. plugin is data proccessing tool.

source
Base.printMethod
print(printer::Printer, td, xd)

Prints xd corresponding to xd to the console.

source
Base.openMethod
open(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
Base.closeMethod
close(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
-======= -Printer · Jusdl

Printer

Basic Operation of Printers

See Basic Operation of Writers since the operation of Writer and that of Printer is very similar.

Full API

Jusdl.PrinterType

Printer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol()) where T Constructs a Printer with input bus input. buflen is the length of its internal buflen. plugin is data proccessing tool.

source
Base.printMethod
print(printer::Printer, td, xd)

Prints xd corresponding to xd to the console.

source
Base.openMethod
open(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
Base.closeMethod
close(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Printer · Causal

Printer

Basic Operation of Printers

See Basic Operation of Writers since the operation of Writer and that of Printer is very similar.

Full API

Causal.PrinterType

Printer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol()) where T Constructs a Printer with input bus input. buflen is the length of its internal buflen. plugin is data proccessing tool.

source
Base.printMethod
print(printer::Printer, td, xd)

Prints xd corresponding to xd to the console.

source
Base.openMethod
open(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
Base.closeMethod
close(printer::Printer)

Does nothing. Just a common interface function ot AbstractSink interface.

source
diff --git a/docs/build/manual/components/sinks/scope/index.html b/docs/build/manual/components/sinks/scope/index.html index b04d650a..e52dc56e 100644 --- a/docs/build/manual/components/sinks/scope/index.html +++ b/docs/build/manual/components/sinks/scope/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Scope · Causal

Scope

Basic Operation of Scopes

See Basic Operation of Writers since the operation of Writer and that of Scope is very similar.

Full API

Causal.ScopeType
Scope(input=Inport(), args...; buflen::Int=64, plugin=nothing, callbacks=nothing, name=Symbol(), kwargs...)

Constructs a Scope with input bus input. buflen is the length of the internal buffer of Scope. plugin is the additional data processing tool. args,kwargs are passed into plots(args...; kwargs...)). See (https://github.com/JuliaPlots/Plots.jl) for more information.

Warning

When initialized, the plot of Scope is closed. See open(sink::Scope) and close(sink::Scope).

source
Causal.update!Method
update!(s::Scope, x, yi)

Updates the series of the plot windows of s with x and yi.

source
Base.closeMethod
close(sink::Scope)

Closes the plot window of the plot of sink.

source
Base.openMethod
open(sink::Scope)

Opens the plot window for the plots of sink.

source
-======= -Scope · Jusdl

Scope

Basic Operation of Scopes

See Basic Operation of Writers since the operation of Writer and that of Scope is very similar.

Full API

Jusdl.ScopeType
Scope(input=Inport(), args...; buflen::Int=64, plugin=nothing, callbacks=nothing, name=Symbol(), kwargs...)

Constructs a Scope with input bus input. buflen is the length of the internal buffer of Scope. plugin is the additional data processing tool. args,kwargs are passed into plots(args...; kwargs...)). See (https://github.com/JuliaPlots/Plots.jl) for more information.

Warning

When initialized, the plot of Scope is closed. See open(sink::Scope) and close(sink::Scope).

source
Jusdl.update!Method
update!(s::Scope, x, yi)

Updates the series of the plot windows of s with x and yi.

source
Base.closeMethod
close(sink::Scope)

Closes the plot window of the plot of sink.

source
Base.openMethod
open(sink::Scope)

Opens the plot window for the plots of sink.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Scope · Causal

Scope

Basic Operation of Scopes

See Basic Operation of Writers since the operation of Writer and that of Scope is very similar.

Full API

Causal.ScopeType
Scope(input=Inport(), args...; buflen::Int=64, plugin=nothing, callbacks=nothing, name=Symbol(), kwargs...)

Constructs a Scope with input bus input. buflen is the length of the internal buffer of Scope. plugin is the additional data processing tool. args,kwargs are passed into plots(args...; kwargs...)). See (https://github.com/JuliaPlots/Plots.jl) for more information.

Warning

When initialized, the plot of Scope is closed. See open(sink::Scope) and close(sink::Scope).

source
Causal.update!Method
update!(s::Scope, x, yi)

Updates the series of the plot windows of s with x and yi.

source
Base.closeMethod
close(sink::Scope)

Closes the plot window of the plot of sink.

source
Base.openMethod
open(sink::Scope)

Opens the plot window for the plots of sink.

source
diff --git a/docs/build/manual/components/sinks/sinks/index.html b/docs/build/manual/components/sinks/sinks/index.html index 27a8e2de..537d930e 100644 --- a/docs/build/manual/components/sinks/sinks/index.html +++ b/docs/build/manual/components/sinks/sinks/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Sinks · Causal

Sinks

Sinks are used to simulation data flowing through the connections of the model. The data processing is done online during the simulation. Sink type is a subtype of AbstractSink. An AbstractSink is also a subtype of AbstractComponent (see Components), so an AbstractSink instance has a trigger link to be triggered and a handshake link to signal that evolution is succeeded. In addition, an AbstractSink has an input buffer inbuf whose mode is Cyclic. When an AbstractSink instance is triggered through its trigger link, it basically reads its incoming data and writes to its input buffer inbuf. When its input buffer inbuf is full, the data in inbuf is processed according to the type of AbstractSink. Causal provides three concrete subtypes of AbstractSink which are Writer, Printer and Scope. As the operation of an AbstractSink just depends on incoming data, an AbstractSink does not have an output.

Full API

Causal.@def_sinkMacro
@def_sink ex

where ex is the expression to define to define a new AbstractSink component type. The usage is as follows:

@def_sink struct MySink{T1,T2,T3,...,TN, A} <: AbstractSink
-=======
-Sinks · Jusdl

Sinks

Sinks are used to simulation data flowing through the connections of the model. The data processing is done online during the simulation. Sink type is a subtype of AbstractSink. An AbstractSink is also a subtype of AbstractComponent (see Components), so an AbstractSink instance has a trigger link to be triggered and a handshake link to signal that evolution is succeeded. In addition, an AbstractSink has an input buffer inbuf whose mode is Cyclic. When an AbstractSink instance is triggered through its trigger link, it basically reads its incoming data and writes to its input buffer inbuf. When its input buffer inbuf is full, the data in inbuf is processed according to the type of AbstractSink. Jusdl provides three concrete subtypes of AbstractSink which are Writer, Printer and Scope. As the operation of an AbstractSink just depends on incoming data, an AbstractSink does not have an output.

Full API

Jusdl.@def_sinkMacro
@def_sink ex

where ex is the expression to define to define a new AbstractSink component type. The usage is as follows:

@def_sink struct MySink{T1,T2,T3,...,TN, A} <: AbstractSink
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Sinks · Causal

Sinks

Sinks are used to simulation data flowing through the connections of the model. The data processing is done online during the simulation. Sink type is a subtype of AbstractSink. An AbstractSink is also a subtype of AbstractComponent (see Components), so an AbstractSink instance has a trigger link to be triggered and a handshake link to signal that evolution is succeeded. In addition, an AbstractSink has an input buffer inbuf whose mode is Cyclic. When an AbstractSink instance is triggered through its trigger link, it basically reads its incoming data and writes to its input buffer inbuf. When its input buffer inbuf is full, the data in inbuf is processed according to the type of AbstractSink. Causal provides three concrete subtypes of AbstractSink which are Writer, Printer and Scope. As the operation of an AbstractSink just depends on incoming data, an AbstractSink does not have an output.

Full API

Causal.@def_sinkMacro
@def_sink ex

where ex is the expression to define to define a new AbstractSink component type. The usage is as follows:

@def_sink struct MySink{T1,T2,T3,...,TN, A} <: AbstractSink
     param1::T1 = param1_default     # optional field 
     param2::T2 = param2_default     # optional field 
     param3::T3 = param3_default     # optional field
@@ -20,8 +16,4 @@
 julia> sink = MySink();
 
 julia> sink.action(sink, ones(2), ones(2) * 2)
-<<<<<<< HEAD
-[1.0, 1.0][2.0, 2.0]
source
-======= -[1.0, 1.0][2.0, 2.0]
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +[1.0, 1.0][2.0, 2.0]
source
diff --git a/docs/build/manual/components/sinks/writer/index.html b/docs/build/manual/components/sinks/writer/index.html index ec387b3d..0baec144 100644 --- a/docs/build/manual/components/sinks/writer/index.html +++ b/docs/build/manual/components/sinks/writer/index.html @@ -1,17 +1,9 @@ -<<<<<<< HEAD -Writer · Causal

Writer

Basic Operation of Writers

Having launched, a Writer is triggered through its trigger pin. When triggered, a Writer reads its input and then writes it to its internal buffer databuf. When databuf is full, the data in databuf is processed. Thus, the length of the data that is to be processed by the Writer is determined by the length of their internal buffer databuf.

Let us construct a Writer.

julia> using Causal # hide
+Writer · Causal

Writer

Basic Operation of Writers

Having launched, a Writer is triggered through its trigger pin. When triggered, a Writer reads its input and then writes it to its internal buffer databuf. When databuf is full, the data in databuf is processed. Thus, the length of the data that is to be processed by the Writer is determined by the length of their internal buffer databuf.

Let us construct a Writer.

julia> using Causal # hide
 
 julia> w = Writer(input=Inport(), buflen=5)
-Writer(path:/tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f, nin:1)

The file of w is closed and the trigger pin of w is not writable. That is, it is not possible to trigger w from its trigger pin.

julia> w.file
-JLDFile /tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f (read/write)
-=======
-Writer · Jusdl

Writer

Basic Operation of Writers

Having launched, a Writer is triggered through its trigger pin. When triggered, a Writer reads its input and then writes it to its internal buffer databuf. When databuf is full, the data in databuf is processed. Thus, the length of the data that is to be processed by the Writer is determined by the length of their internal buffer databuf.

Let us construct a Writer.

julia> using Jusdl # hide
-
-julia> w = Writer(input=Inport(), buflen=5)
-Writer(path:/tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d, nin:1)

The file of w is closed and the trigger pin of w is not writable. That is, it is not possible to trigger w from its trigger pin.

julia> w.file
-JLDFile /tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d (read/write)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Writer(path:/tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b, nin:1)

The file of w is closed and the trigger pin of w is not writable. That is, it is not possible to trigger w from its trigger pin.

julia> w.file
+JLDFile /tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b (read/write)
   (closed)
 
 julia> w.trigger
@@ -29,19 +21,11 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> open(w)
-<<<<<<< HEAD
-Writer(path:/tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f, nin:1)
+Writer(path:/tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b, nin:1)
 
 julia> t = launch(w)
-Task (runnable) @0x00007f513170d870

Now, the internal file of w is opened in read/write mode and its trigger pin is writable.

julia> w.file
-JLDFile /tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f (read/write)
-=======
-Writer(path:/tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d, nin:1)
-
-julia> t = launch(w)
-Task (runnable) @0x00007f163dbf8760

Now, the internal file of w is opened in read/write mode and its trigger pin is writable.

julia> w.file
-JLDFile /tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d (read/write)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad7a14010

Now, the internal file of w is opened in read/write mode and its trigger pin is writable.

julia> w.file
+JLDFile /tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b (read/write)
   (no datasets)
 
 julia> w.trigger.link
@@ -60,29 +44,17 @@
   0.0
   0.0
   0.0

Since the databuf is not full nothing is written to the file of w.

julia> w.file
-<<<<<<< HEAD
-JLDFile /tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f (read/write)
-=======
-JLDFile /tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d (read/write)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+JLDFile /tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b (read/write)
   (no datasets)

Let us continue triggering w until the databuf of w is full.

julia> for t in 2. : 5.
            put!(trg, t)
            put!(oport, [t * 10])
            take!(hnd)
        end

Now check that the content of the file of w.

julia> w.file
-<<<<<<< HEAD
-JLDFile /tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f (read/write)
+JLDFile /tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b (read/write)
  └─🔢 [5.0, 4.0, 3.0, 2.0, 1.0]

Note that the content of databuf is written to the file of w. The operation of w can be terminated.

julia> put!(trg, NaN)

When terminated, the file of w is closed.

julia> w.file
-JLDFile /tmp/be91a0c8-75bf-4237-ac17-d0978ac6d20f (read/write)
+JLDFile /tmp/70e9b09e-68ba-4dc2-bb31-1fa1a191e91b (read/write)
   (closed)
Note

In this example, w does not have a plugin so nothing has been derived or computed from the data in databuf. The data in databuf is just written to file of w. To further data processing, see Plugins

Full API

Causal.WriterType
Writer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol(uuid4()), 
     path=joinpath(tempdir(), string(name)))

Constructs a Writer whose input bus is input. buflen is the length of the internal buffer of Writer. If not nothing, plugin is used to processes the incomming data. path determines the path of the file of Writer.

Note

The type of file of Writer is JLD2.

Warning

When initialized, the file of Writer is closed. See open(writer::Writer) and close(writer::Writer).

source
Causal.write!Method
write!(writer, td, xd)

Writes xd corresponding to xd to the file of writer.

Example

julia> w = Writer(Inport(1))
-=======
-JLDFile /tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d (read/write)
- └─🔢 [5.0, 4.0, 3.0, 2.0, 1.0]

Note that the content of databuf is written to the file of w. The operation of w can be terminated.

julia> put!(trg, NaN)

When terminated, the file of w is closed.

julia> w.file
-JLDFile /tmp/71bd8c50-3d96-42e4-b462-59dda4a22e9d (read/write)
-  (closed)
Note

In this example, w does not have a plugin so nothing has been derived or computed from the data in databuf. The data in databuf is just written to file of w. To further data processing, see Plugins

Full API

Jusdl.WriterType
Writer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol(uuid4()), 
-    path=joinpath(tempdir(), string(name)))

Constructs a Writer whose input bus is input. buflen is the length of the internal buffer of Writer. If not nothing, plugin is used to processes the incomming data. path determines the path of the file of Writer.

Note

The type of file of Writer is JLD2.

Warning

When initialized, the file of Writer is closed. See open(writer::Writer) and close(writer::Writer).

source
Jusdl.write!Method
write!(writer, td, xd)

Writes xd corresponding to xd to the file of writer.

Example

julia> w = Writer(Inport(1))
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 Writer(path:/tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2, nin:1)
 
 julia> open(w)
@@ -100,11 +72,7 @@
  └─🔢 1.0
 
 julia> w.file[string(0.)]
-<<<<<<< HEAD
-10.0
source
Base.readMethod
read(writer::Writer, flatten=false)

Read the contents of the file of writer and returns the sorted content of the file. If flatten is true, the content is also flattened.

source
Causal.freadFunction
fread(path::String)

Reads the content of jld2 file and returns the sorted file content.

source
Base.Filesystem.mvMethod
mv(writer::Writer, dst; force::Bool=false)

Moves the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed.

Example

julia> mkdir(joinpath(tempdir(), "testdir1"))
-=======
-10.0
source
Base.readMethod
read(writer::Writer, flatten=false)

Read the contents of the file of writer and returns the sorted content of the file. If flatten is true, the content is also flattened.

source
Jusdl.freadFunction
fread(path::String)

Reads the content of jld2 file and returns the sorted file content.

source
Base.Filesystem.mvMethod
mv(writer::Writer, dst; force::Bool=false)

Moves the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed.

Example

julia> mkdir(joinpath(tempdir(), "testdir1"))
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+10.0
source
Base.readMethod
read(writer::Writer, flatten=false)

Read the contents of the file of writer and returns the sorted content of the file. If flatten is true, the content is also flattened.

source
Causal.freadFunction
fread(path::String)

Reads the content of jld2 file and returns the sorted file content.

source
Base.Filesystem.mvMethod
mv(writer::Writer, dst; force::Bool=false)

Moves the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed.

Example

julia> mkdir(joinpath(tempdir(), "testdir1"))
 "/tmp/testdir1"
 
 julia> mkdir(joinpath(tempdir(), "testdir2"))
@@ -114,7 +82,7 @@
 Writer(path:/tmp/testdir1/myfile.jld2, nin:1)
 
 julia> mv(w, "/tmp/testdir2")
-Writer(path:/tmp/testdir2/myfile.jld2, nin:1)
source
Base.Filesystem.cpMethod
cp(writer::Writer, dst; force=false, follow_symlinks=false)

Copies the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed. If follow_symlinks is true, symbolinks are followed.

Example

julia> mkdir(joinpath(tempdir(), "testdir1"))
+Writer(path:/tmp/testdir2/myfile.jld2, nin:1)
source
Base.Filesystem.cpMethod
cp(writer::Writer, dst; force=false, follow_symlinks=false)

Copies the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed. If follow_symlinks is true, symbolinks are followed.

Example

julia> mkdir(joinpath(tempdir(), "testdir1"))
 "/tmp/testdir1"
 
 julia> mkdir(joinpath(tempdir(), "testdir2"))
@@ -124,8 +92,4 @@
 Writer(path:/tmp/testdir1.jld2, nin:1)
 
 julia> cp(w, "/tmp/testdir2")
-<<<<<<< HEAD
-Writer(path:/tmp/testdir2/1e72bad1-9800-4ca0-bccd-702afe75e555, nin:1)
source
Base.openMethod
open(writer::Writer)

Opens writer by opening the its file in read/write mode. When writer is not openned, it is not possible to write data in writer. See also close(writer::Writer)

source
-======= -Writer(path:/tmp/testdir2/1e72bad1-9800-4ca0-bccd-702afe75e555, nin:1)
source
Base.openMethod
open(writer::Writer)

Opens writer by opening the its file in read/write mode. When writer is not openned, it is not possible to write data in writer. See also close(writer::Writer)

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Writer(path:/tmp/testdir2/1e72bad1-9800-4ca0-bccd-702afe75e555, nin:1)source
Base.openMethod
open(writer::Writer)

Opens writer by opening the its file in read/write mode. When writer is not openned, it is not possible to write data in writer. See also close(writer::Writer)

source
diff --git a/docs/build/manual/components/sources/clock/index.html b/docs/build/manual/components/sources/clock/index.html index 8cf65a43..ded79965 100644 --- a/docs/build/manual/components/sources/clock/index.html +++ b/docs/build/manual/components/sources/clock/index.html @@ -1,19 +1,11 @@ -<<<<<<< HEAD -Clock · Causal

Clock

Causal is a clocked simulation environment. That is, model components are evolved in different time intervals, called the sampling interval. During the simulation, model components are triggered by these generated time pulses. A Clock instance is used to to generate those time pulses. The simulation time settings–the simulation start time, stop time, sampling interval–are configured through the Clock.

Construction of Clock

Construction of Clock is done by specifying its start time and final time and the simulation sampling period.

julia> using Causal # hide
-=======
-Clock · Jusdl

Clock

Jusdl is a clocked simulation environment. That is, model components are evolved in different time intervals, called the sampling interval. During the simulation, model components are triggered by these generated time pulses. A Clock instance is used to to generate those time pulses. The simulation time settings–the simulation start time, stop time, sampling interval–are configured through the Clock.

Construction of Clock

Construction of Clock is done by specifying its start time and final time and the simulation sampling period.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Clock · Causal

Clock

Causal is a clocked simulation environment. That is, model components are evolved in different time intervals, called the sampling interval. During the simulation, model components are triggered by these generated time pulses. A Clock instance is used to to generate those time pulses. The simulation time settings–the simulation start time, stop time, sampling interval–are configured through the Clock.

Construction of Clock

Construction of Clock is done by specifying its start time and final time and the simulation sampling period.

julia> using Causal # hide
 
 julia> Clock(0., 1, 10.)
 Clock(t:0.0, dt:1.0, tf:10.0, paused:false, isrunning:false)
 
 julia> Clock{Int}(1, 1, 10)
-<<<<<<< HEAD
 Clock(t:1, dt:1, tf:10, paused:false, isrunning:false)

Basic Usage of Clocks

A Clock has a Callback list so that a Callback can be constructed to trigger specific events configured with the time settings. See the following case study.

Let us consider a Clock with initial time of 0, sampling interval of 1 and final time of 10.

julia> using Causal # hide
-=======
-Clock(t:1, dt:1, tf:10, paused:false, isrunning:false)

Basic Usage of Clocks

A Clock has a Callback list so that a Callback can be constructed to trigger specific events configured with the time settings. See the following case study.

Let us consider a Clock with initial time of 0, sampling interval of 1 and final time of 10.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 
 julia> clk = Clock(0., 1., 10.)
 Clock(t:0.0, dt:1.0, tf:10.0, paused:false, isrunning:false)

Notice that clk is not running, since it is not set. Now, let us set it

julia> set!(clk)
@@ -63,20 +55,12 @@
 Clock time = 9.0
 t = 10.0
 
-<<<<<<< HEAD
 Clock time = 10.0

Note that we, constructed a simple callback. It is of course possible to construct more complex callbacks.

Usage of Clocks with ProgressMeter

It also possible to iterate the Clocks by using a progress meter. See ProgressMeter for further information for progress meter.

using Causal
-=======
-Clock time = 10.0

Note that we, constructed a simple callback. It is of course possible to construct more complex callbacks.

Usage of Clocks with ProgressMeter

It also possible to iterate the Clocks by using a progress meter. See ProgressMeter for further information for progress meter.

using Jusdl
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 using ProgressMeter
 clk = Clock(0., 0.01, 1.)
 set!(clk)
 @showprogress for t in clk 
-<<<<<<< HEAD
-end 

Note that clk is just iterated.

Full API

Causal.ClockType
Clock(t::Real, dt::Real, tf::Real)

Constructs a Clock with starting time t, final time tf and sampling inteval dt. When iterated, the Clock returns its current time.

Warning

When constructed, Clock is not running. To take clock ticks from Clock, the Clock must be setted. See take!(clk::Clock) and set!

source
Base.iterateFunction
iterate(clk::Clock[, t=clk.t)

Iterationk interface for clk. clk can be iterated in a loop.

Example

julia> clk = Clock(0., 0.1, 0.3);
-=======
-end 

Note that clk is just iterated.

Full API

Jusdl.ClockType
Clock(t::Real, dt::Real, tf::Real)

Constructs a Clock with starting time t, final time tf and sampling inteval dt. When iterated, the Clock returns its current time.

Warning

When constructed, Clock is not running. To take clock ticks from Clock, the Clock must be setted. See take!(clk::Clock) and set!

source
Base.iterateFunction
iterate(clk::Clock[, t=clk.t)

Iterationk interface for clk. clk can be iterated in a loop.

Example

julia> clk = Clock(0., 0.1, 0.3);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+end 

Note that clk is just iterated.

Full API

Causal.ClockType
Clock(t::Real, dt::Real, tf::Real)

Constructs a Clock with starting time t, final time tf and sampling inteval dt. When iterated, the Clock returns its current time.

Warning

When constructed, Clock is not running. To take clock ticks from Clock, the Clock must be setted. See take!(clk::Clock) and set!

source
Base.iterateFunction
iterate(clk::Clock[, t=clk.t)

Iterationk interface for clk. clk can be iterated in a loop.

Example

julia> clk = Clock(0., 0.1, 0.3);
 
 julia> set!(clk)
 Clock(t:0.0, dt:0.1, tf:0.3, paused:false, isrunning:true)
@@ -87,7 +71,7 @@
 t = 0.0
 t = 0.1
 t = 0.2
-t = 0.3
source
Base.take!Method
take!(clk::Clock)

Takes a values from clk.

Example

julia> clk = Clock(0., 0.1, 0.5)
+t = 0.3
source
Base.take!Method
take!(clk::Clock)

Takes a values from clk.

Example

julia> clk = Clock(0., 0.1, 0.5)
 Clock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)
 
 julia> set!(clk)
@@ -101,11 +85,7 @@
 take!(clk) = 0.2
 take!(clk) = 0.3
 take!(clk) = 0.4
-<<<<<<< HEAD
-take!(clk) = 0.5
source
Causal.isoutoftimeMethod
isoutoftime(clk::Clock)

Returns true if clk is out of time, i.e., the current time of clk exceeds its final time.

source
Causal.pause!Method
pause!(clk::Clock)

Pauses clk. When paused, the current time of clk does not advance.

Example

julia> clk = Clock(0., 0.1, 0.5);
-=======
-take!(clk) = 0.5
source
Jusdl.isoutoftimeMethod
isoutoftime(clk::Clock)

Returns true if clk is out of time, i.e., the current time of clk exceeds its final time.

source
Jusdl.pause!Method
pause!(clk::Clock)

Pauses clk. When paused, the current time of clk does not advance.

Example

julia> clk = Clock(0., 0.1, 0.5);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+take!(clk) = 0.5
source
Causal.isoutoftimeMethod
isoutoftime(clk::Clock)

Returns true if clk is out of time, i.e., the current time of clk exceeds its final time.

source
Causal.pause!Method
pause!(clk::Clock)

Pauses clk. When paused, the current time of clk does not advance.

Example

julia> clk = Clock(0., 0.1, 0.5);
 
 julia> set!(clk);
 
@@ -117,27 +97,15 @@
 take!(clk) = 0.1
 take!(clk) = 0.2
 ┌ Warning: Clock is paused.
-<<<<<<< HEAD
 └ @ Causal ~/.julia/dev/Causal/src/components/sources/clock.jl:61
 take!(clk) = 0.2
 ┌ Warning: Clock is paused.
 └ @ Causal ~/.julia/dev/Causal/src/components/sources/clock.jl:61
-take!(clk) = 0.2
source
Causal.set!Function
set(clk::Clock, t::Real, dt::Real, tf::Real)

Sets clk for current clock time t, sampling time dt and final time tf. After the set, it is possible to take clock tick from clk. See also take!(clk::Clock)

Example

julia> clk = Clock(0., 0.1, 0.5)
-=======
-└ @ Jusdl ~/.julia/dev/Jusdl/src/components/sources/clock.jl:61
-take!(clk) = 0.2
-┌ Warning: Clock is paused.
-└ @ Jusdl ~/.julia/dev/Jusdl/src/components/sources/clock.jl:61
-take!(clk) = 0.2
source
Jusdl.set!Function
set(clk::Clock, t::Real, dt::Real, tf::Real)

Sets clk for current clock time t, sampling time dt and final time tf. After the set, it is possible to take clock tick from clk. See also take!(clk::Clock)

Example

julia> clk = Clock(0., 0.1, 0.5)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+take!(clk) = 0.2
source
Causal.set!Function
set(clk::Clock, t::Real, dt::Real, tf::Real)

Sets clk for current clock time t, sampling time dt and final time tf. After the set, it is possible to take clock tick from clk. See also take!(clk::Clock)

Example

julia> clk = Clock(0., 0.1, 0.5)
 Clock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)
 
 julia> set!(clk)
 Clock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:true)
 
 julia> take!(clk)
-<<<<<<< HEAD
-0.0
source
-======= -0.0
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +0.0source diff --git a/docs/build/manual/components/sources/generators/index.html b/docs/build/manual/components/sources/generators/index.html index d06b40c8..4d1f11fe 100644 --- a/docs/build/manual/components/sources/generators/index.html +++ b/docs/build/manual/components/sources/generators/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Generators · Causal

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
-=======
-Generators · Jusdl

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 Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Generators · Causal

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)
@@ -24,20 +20,12 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> t = launch(gen)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ed649d0
-=======
-Task (runnable) @0x00007f163fd8b820
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad832b820
 
 julia> tout = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ee584f0

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
-=======
-Task (runnable) @0x00007f1645c25600

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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1a5ae60

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]
@@ -67,11 +55,7 @@
       0.0
       0.0
       0.0
-<<<<<<< HEAD
       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
-=======
-      0.0

Jusdl provides some other function generators which are documented in the following section.

Full API

Jusdl.@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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
     param1::T1 = param1_default     # optional field 
     param2::T2 = param2_default     # optional field 
     param3::T3 = param3_default     # optional field
@@ -93,11 +77,7 @@
 
 julia> gen.output
 1-element Outport{Outpin{Float64}}:
-<<<<<<< HEAD
- 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));
-=======
- Outpin(eltype:Float64, isbound:false)
source
Jusdl.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));
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ 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}:
@@ -111,8 +91,4 @@
 	\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 -<<<<<<< HEAD - \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
-======= - \end{array} \right.\]

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

source
Jusdl.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
Jusdl.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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + \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
diff --git a/docs/build/manual/components/systems/dynamicsystems/daesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/daesystem/index.html index 1e24f5c4..0dd14bde 100644 --- a/docs/build/manual/components/systems/dynamicsystems/daesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/daesystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -DAESystem · Causal

DAESystem

Full API

Causal.@def_dae_systemMacro
@def_dae_system ex

where ex is the expression to define to define a new AbstractDAESystem component type. The usage is as follows:

@def_dae_system mutable struct MyDAESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDAESystem
-=======
-DAESystem · Jusdl

DAESystem

Full API

Jusdl.@def_dae_systemMacro
@def_dae_system ex

where ex is the expression to define to define a new AbstractDAESystem component type. The usage is as follows:

@def_dae_system mutable struct MyDAESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDAESystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+DAESystem · Causal

DAESystem

Full API

Causal.@def_dae_systemMacro
@def_dae_system ex

where ex is the expression to define to define a new AbstractDAESystem component type. The usage is as follows:

@def_dae_system mutable struct MyDAESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDAESystem
     param1::T1 = param1_default                 # optional field 
     param2::T2 = param2_default                 # optional field 
     param3::T3 = param3_default                 # optional field
@@ -34,11 +30,7 @@
         output::OP = Outport(1)
         end
 
-<<<<<<< HEAD
-julia> ds = MyDAESystem();
source
Causal.DAESystemType
DAESystem(; righthandside, readout, state, stateder, diffvars, input, output)

Constructs a generic DAE system.

Example

julia> function sfuncdae(out, dx, x, u, t)
-=======
-julia> ds = MyDAESystem();
source
Jusdl.DAESystemType
DAESystem(; righthandside, readout, state, stateder, diffvars, input, output)

Constructs a generic DAE system.

Example

julia> function sfuncdae(out, dx, x, u, t)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+julia> ds = MyDAESystem();
source
Causal.DAESystemType
DAESystem(; righthandside, readout, state, stateder, diffvars, input, output)

Constructs a generic DAE system.

Example

julia> function sfuncdae(out, dx, x, u, t)
            out[1] = x[1] + 1 - dx[1]
            out[2] = (x[1] + 1) * x[2] + 2
        end;
@@ -66,8 +58,4 @@
     \dot{x}_3 = -\dfrac{F}{m l} x_1 \\[0.25cm]
     \dot{x}_4 = g \dfrac{F}{l} x_2 \\[0.25cm]
     0 = x_1^2 + x_2^2 - l^2 
-<<<<<<< HEAD
-\end{array}\]

where $F$ is the external force, $l$ is the length, $m$ is the mass and $g$ is the accelaration of gravity.

source
-======= -\end{array}\]

where $F$ is the external force, $l$ is the length, $m$ is the mass and $g$ is the accelaration of gravity.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +\end{array}\]

where $F$ is the external force, $l$ is the length, $m$ is the mass and $g$ is the accelaration of gravity.

source diff --git a/docs/build/manual/components/systems/dynamicsystems/ddesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/ddesystem/index.html index 14065f22..ef902fe4 100644 --- a/docs/build/manual/components/systems/dynamicsystems/ddesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/ddesystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -DDESystem · Causal

DDESystem

Construction of DDESystem

A DDESystem is represented by the following state equation

\[ \dot{x} = f(x, h, u, t) \quad t \geq t_0\]

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

\[ x(t) = h(t) \quad t \leq t_0\]

and by the output equation

\[ y = g(x, u, t) \]

where $y$ is the value of the output.

As an example, consider a system with the state equation

\[ \begin{array}{l} -======= -DDESystem · Jusdl

DDESystem

Construction of DDESystem

A DDESystem is represented by the following state equation

\[ \dot{x} = f(x, h, u, t) \quad t \geq t_0\]

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

\[ x(t) = h(t) \quad t \leq t_0\]

and by the output equation

\[ y = g(x, u, t) \]

where $y$ is the value of the output.

As an example, consider a system with the state equation

\[ \begin{array}{l} ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +DDESystem · Causal

DDESystem

Construction of DDESystem

A DDESystem is represented by the following state equation

\[ \dot{x} = f(x, h, u, t) \quad t \geq t_0\]

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

\[ x(t) = h(t) \quad t \leq t_0\]

and by the output equation

\[ y = g(x, u, t) \]

where $y$ is the value of the output.

As an example, consider a system with the state equation

\[ \begin{array}{l} \dot{x} = -x(t - \tau) \quad t \geq 0 \\ x(t) = 1. -\tau \leq t \leq 0 \\ \end{array}\]

First, we define the history function histfunc,


@@ -36,35 +32,20 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> task = launch(ds)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ee5bd00
-=======
-Task (runnable) @0x00007f163e5d64a0
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad9004eb0
 
 julia> task2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ed95d50

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)
-=======
-Task (runnable) @0x00007f163e74e230

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)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdadc079390

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
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ee5bd00
+Task (runnable) @0x00007fdad9004eb0
 
 julia> task2
-Task (runnable) @0x00007f512ed95d50

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
-=======
-Task (runnable) @0x00007f163e5d64a0
-
-julia> task2
-Task (runnable) @0x00007f163e74e230

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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdadc079390

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
@@ -85,11 +66,7 @@
       0.0
       0.0
       0.0
-<<<<<<< HEAD
       0.0

Full API

Causal.@def_dde_systemMacro
@def_dde_system ex

where ex is the expression to define to define a new AbstractDDESystem component type. The usage is as follows:

@def_dde_system mutable struct MyDDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDDESystem
-=======
-      0.0

Full API

Jusdl.@def_dde_systemMacro
@def_dde_system ex

where ex is the expression to define to define a new AbstractDDESystem component type. The usage is as follows:

@def_dde_system mutable struct MyDDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDDESystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
     param1::T1 = param1_default                 # optional field 
     param2::T2 = param2_default                 # optional field 
     param3::T3 = param3_default                 # optional field
@@ -140,8 +117,4 @@
            output::OP = Outport(1)
        end
 
-<<<<<<< HEAD
-julia> ds = MyDDESystem();
source
Causal.DDESystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Construct a generic DDE system

source
Causal.DelayFeedbackSystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Constructs DelayFeedbackSystem

source
-======= -julia> ds = MyDDESystem();
source
Jusdl.DDESystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Construct a generic DDE system

source
Jusdl.DelayFeedbackSystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Constructs DelayFeedbackSystem

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +julia> ds = MyDDESystem();source
Causal.DDESystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Construct a generic DDE system

source
Causal.DelayFeedbackSystemType
DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)

Constructs DelayFeedbackSystem

source
diff --git a/docs/build/manual/components/systems/dynamicsystems/discretesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/discretesystem/index.html index dcaa36ea..aaa76361 100644 --- a/docs/build/manual/components/systems/dynamicsystems/discretesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/discretesystem/index.html @@ -1,11 +1,6 @@ -<<<<<<< HEAD -DiscreteSystem · Causal

DiscreteSystem

Construction of DiscreteSystem

DiscreteSystems evolve by the following discrete time difference equation.

\[ x_{k + 1} = f(x_k, u_k, k) \\ +DiscreteSystem · Causal

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 Causal # hide
-=======
-DiscreteSystem · Jusdl

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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 
 julia> sfunc(dx, x, u, t) = (dx .= -0.5x)
 sfunc (generic function with 1 method)
@@ -35,20 +30,12 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> task = launch(ds)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512fda7d00
-=======
-Task (runnable) @0x00007f163e74cc40
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad9413820
 
 julia> task2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (runnable) @0x00007f513170ee60

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
-=======
-Task (runnable) @0x00007f163770dd50

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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad7a144f0

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)
@@ -77,32 +64,18 @@
   0.0
   0.0
   0.0

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

julia> task
-<<<<<<< HEAD
-Task (runnable) @0x00007f512fda7d00
+Task (runnable) @0x00007fdad9413820
 
 julia> task2
-Task (runnable) @0x00007f513170ee60

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)
-=======
-Task (runnable) @0x00007f163e74cc40
-
-julia> task2
-Task (runnable) @0x00007f163770dd50

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)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad7a144f0

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
-<<<<<<< HEAD
-Task (done) @0x00007f512fda7d00
-
-julia> task2
-Task (done) @0x00007f513170ee60

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_systemMacro
@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
-=======
-Task (done) @0x00007f163e74cc40
+Task (done) @0x00007fdad9413820
 
 julia> task2
-Task (done) @0x00007f163770dd50

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.@def_discrete_systemMacro
@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
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (done) @0x00007fdad7a144f0

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_systemMacro
@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
@@ -132,11 +105,7 @@
 
 julia> ds.input 
 1-element Inport{Inpin{Float64}}:
-<<<<<<< HEAD
- Inpin(eltype:Float64, isbound:false)
source
Causal.DiscreteSystemType
DiscreteSystem(; righthandside, readout, state, input, output)

Constructs a generic discrete system

Example

julia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);
-=======
- Inpin(eltype:Float64, isbound:false)
source
Jusdl.DiscreteSystemType
DiscreteSystem(; righthandside, readout, state, input, output)

Constructs a generic discrete system

Example

julia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ Inpin(eltype:Float64, isbound:false)
source
Causal.DiscreteSystemType
DiscreteSystem(; righthandside, readout, state, input, output)

Constructs a generic discrete system

Example

julia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);
 
 julia> ofuncdiscrete(x, u, t) = x;
 
@@ -161,8 +130,4 @@
     \dot{x}_2 = x_1
 \end{array}\]
source
Causal.LogisticSystemType
LogisticSystem()

Constructs a LogisticSystem with the dynamics

\[\begin{array}{l} \dot{x} = r x (1 - x) -<<<<<<< HEAD -\end{array}\]
source
-======= -\end{array}\]
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +\end{array}\]source diff --git a/docs/build/manual/components/systems/dynamicsystems/odesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/odesystem/index.html index 68d04f05..7cc0a2a8 100644 --- a/docs/build/manual/components/systems/dynamicsystems/odesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/odesystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -ODESystem · Causal

ODESystem

Basic Operation of ODESystem

When an ODESystem is triggered, it reads its current time from its trigger link, reads its input, solves its differential equation and computes its output. Let us observe the basic operation of ODESystems with a simple example.

We first construct an ODESystem. Since an ODESystem is represented by its state equation and output equation, we need to define those equations.

julia> using Causal # hide
-=======
-ODESystem · Jusdl

ODESystem

Basic Operation of ODESystem

When an ODESystem is triggered, it reads its current time from its trigger link, reads its input, solves its differential equation and computes its output. Let us observe the basic operation of ODESystems with a simple example.

We first construct an ODESystem. Since an ODESystem is represented by its state equation and output equation, we need to define those equations.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ODESystem · Causal

ODESystem

Basic Operation of ODESystem

When an ODESystem is triggered, it reads its current time from its trigger link, reads its input, solves its differential equation and computes its output. Let us observe the basic operation of ODESystems with a simple example.

We first construct an ODESystem. Since an ODESystem is represented by its state equation and output equation, we need to define those equations.

julia> using Causal # hide
 
 julia> sfunc(dx,x,u,t) = (dx .= -0.5x)
 sfunc (generic function with 1 method)
@@ -28,20 +24,12 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> task = launch(ds)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ef52e60
-=======
-Task (runnable) @0x00007f163dbe4280
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1ce9870
 
 julia> task2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (runnable) @0x00007f5130119600

When launched, ds is ready to driven. ds is driven from its trigger link. Note that the trigger link of ds is writable.

julia> ds.trigger.link
-=======
-Task (runnable) @0x00007f163e5d5120

When launched, ds is ready to driven. ds is driven from its trigger link. Note that the trigger link of ds is writable.

julia> ds.trigger.link
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad8755d50

When launched, ds is ready to driven. ds is driven from its trigger link. Note that the trigger link of ds is writable.

julia> ds.trigger.link
 Link(state:open, eltype:Float64, isreadable:false, iswritable:true)

Let us drive ds to the time of t of 1 second.

julia> put!(trg, 1.)

When driven, ds reads current time of t from its trigger link, reads its input value from its input, solves its differential equation and computes its output values and writes its output. So, for the step to be continued, an input values must be written. Note that the input of ds is writable,

julia> ds.input[1].link
 Link(state:open, eltype:Float64, isreadable:false, iswritable:true)

Let us write some value.

julia> put!(oport, [5.])
 1-element Array{Float64,1}:
@@ -73,32 +61,18 @@
  0.0
  0.0
  0.0

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

julia> task
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ef52e60
+Task (runnable) @0x00007fdad1ce9870
 
 julia> task2
-Task (runnable) @0x00007f5130119600

To terminate the task safely, we need to terminate ds safely.

julia> put!(trg, NaN)
-=======
-Task (runnable) @0x00007f163dbe4280
-
-julia> task2
-Task (runnable) @0x00007f163e5d5120

To terminate the task safely, we need to terminate ds safely.

julia> put!(trg, NaN)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad8755d50

To terminate the task safely, we need to terminate ds safely.

julia> put!(trg, NaN)
 
 julia> put!(ds.output, [NaN])
 1-element Array{Float64,1}:
  NaN

Now, the state of the task is done.

julia> task
-<<<<<<< HEAD
-Task (done) @0x00007f512ef52e60
-
-julia> task2
-Task (done) @0x00007f5130119600

So, it is not possible to drive ds.

Mutation in State Function in ODESystem

Consider a system with the following ODE

\[\begin{array}{l} -======= -Task (done) @0x00007f163dbe4280 +Task (done) @0x00007fdad1ce9870 julia> task2 -Task (done) @0x00007f163e5d5120

So, it is not possible to drive ds.

Mutation in State Function in ODESystem

Consider a system with the following ODE

\[\begin{array}{l} ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Task (done) @0x00007fdad8755d50

So, it is not possible to drive ds.

Mutation in State Function in ODESystem

Consider a system with the following ODE

\[\begin{array}{l} \dot{x} = f(x, u, t) \\ y = g(x, u, t) \\ \end{array}\]

where $x \in R^d, y \in R^m, u \in R^p$. To construct and ODESystem, The signature of the state function statefunc must be of the form

function statefunc(dx, x, u, t)
@@ -106,11 +80,7 @@
 end

Note that statefunc does not construct dx but updates dx and does not return anything. This is for performance reasons. On the contrary, the signature of the output function outputfunc must be of the form,

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

Note the output value y is computed and returned from outputfunc. y is not updated but generated in the outputfunc.

Full API

Causal.@def_ode_systemMacro
@def_ode_system ex

where ex is the expression to define to define a new AbstractODESystem component type. The usage is as follows:

@def_ode_system mutable struct MyODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractODESystem
-=======
-end

Note the output value y is computed and returned from outputfunc. y is not updated but generated in the outputfunc.

Full API

Jusdl.@def_ode_systemMacro
@def_ode_system ex

where ex is the expression to define to define a new AbstractODESystem component type. The usage is as follows:

@def_ode_system mutable struct MyODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractODESystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
     param1::T1 = param1_default                     # optional field 
     param2::T2 = param2_default                     # optional field 
     param3::T3 = param3_default                     # optional field
@@ -140,11 +110,7 @@
 
 julia> ds.input 
 1-element Inport{Inpin{Float64}}:
-<<<<<<< HEAD
- Inpin(eltype:Float64, isbound:false)
source
Causal.ODESystemType
ODESystem(;righthandside, readout, state, input, output)

Constructs a generic ODE system.

Example

julia> ds = ODESystem(righthandside=(dx,x,u,t)->(dx.=-x), readout=(x,u,t)->x, state=[1.],input=nothing, output=Outport(1));
-=======
- Inpin(eltype:Float64, isbound:false)
source
Jusdl.ODESystemType
ODESystem(;righthandside, readout, state, input, output)

Constructs a generic ODE system.

Example

julia> ds = ODESystem(righthandside=(dx,x,u,t)->(dx.=-x), readout=(x,u,t)->x, state=[1.],input=nothing, output=Outport(1));
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ Inpin(eltype:Float64, isbound:false)
source
Causal.ODESystemType
ODESystem(;righthandside, readout, state, input, output)

Constructs a generic ODE system.

Example

julia> ds = ODESystem(righthandside=(dx,x,u,t)->(dx.=-x), readout=(x,u,t)->x, state=[1.],input=nothing, output=Outport(1));
 
 julia> ds.state
 1-element Array{Float64,1}:
@@ -203,8 +169,4 @@
     \dot{x}_2 = \gamma (\mu (x_1^2 - 1) x_2 - x_1) + \sum_{j = 1}^3 \theta_{2j} u_j 
 \end{array}\]

where $\Theta = [\theta_{ij}]$ is cplmat and $u = [u_{j}]$ is the value of the input. The output function is

\[ y = g(x, u, t)\]

where $t$ is time t, $y$ is the value of the output and $g$ is outputfunc.

source
Causal.IntegratorType
Integrator(state=zeros(0), t=0., modelargs=(), solverargs=(); 
     alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple(), numtaps=numtaps, callbacks=nothing, 
-<<<<<<< HEAD
-    name=Symbol())

Constructs an integrator whose input output relation is given by

\[u(t) = ki * \int_{0}^{t} u(\tau) d\tau\]

where $u(t)$ is the input, $y(t)$ is the output and $ki$ is the integration constant.

source
-======= - name=Symbol())

Constructs an integrator whose input output relation is given by

\[u(t) = ki * \int_{0}^{t} u(\tau) d\tau\]

where $u(t)$ is the input, $y(t)$ is the output and $ki$ is the integration constant.

source ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + name=Symbol())

Constructs an integrator whose input output relation is given by

\[u(t) = ki * \int_{0}^{t} u(\tau) d\tau\]

where $u(t)$ is the input, $y(t)$ is the output and $ki$ is the integration constant.

source diff --git a/docs/build/manual/components/systems/dynamicsystems/rodesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/rodesystem/index.html index d01292bc..684903e0 100644 --- a/docs/build/manual/components/systems/dynamicsystems/rodesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/rodesystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -RODESystem · Causal

RODESystem

Construction of RODESystem

A RODESystem is represented by the state function

\[\begin{array}{l} -======= -RODESystem · Jusdl

RODESystem

Construction of RODESystem

A RODESystem is represented by the state function

\[\begin{array}{l} ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +RODESystem · Causal

RODESystem

Construction of RODESystem

A RODESystem is represented by the state function

\[\begin{array}{l} dx = f(x, u, t, W) \end{array}\]

and the output function

\[ y = g(x, u, t)\]

where $t$ is the time, $x \in R^n$ is the state, $u \in R^p$ and $y \in R^m$ is output of the system. Therefore to construct a RODESystem, we need to define statefunc and outputfunc with the corresponding syntax,

function statefunc(dx, x, u, t)
     dx .= ... # Update dx 
@@ -48,56 +44,32 @@
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
 
 julia> task = launch(ds)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ee59120
-=======
-Task (runnable) @0x00007f163dfcfa90
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad8328010
 
 julia> task2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (runnable) @0x00007f5125ae9fc0

When launched, ds is ready to be driven. We can drive ds by drive(ds, t) or put!(ds.trigger, t) where t is the time until which we will drive ds.

julia> put!(trg, 1.)

When triggered, ds read the time t from its trigger link, solved its differential equation, computed its value and writes its output value to its output bus. To signal that, the evolution is succeeded, ds writes true to its handshake link which must be taken to further drive ds. (approve!(ds)) can also be used.

julia> take!(hnd)
-=======
-Task (runnable) @0x00007f1636798280

When launched, ds is ready to be driven. We can drive ds by drive(ds, t) or put!(ds.trigger, t) where t is the time until which we will drive ds.

julia> put!(trg, 1.)

When triggered, ds read the time t from its trigger link, solved its differential equation, computed its value and writes its output value to its output bus. To signal that, the evolution is succeeded, ds writes true to its handshake link which must be taken to further drive ds. (approve!(ds)) can also be used.

julia> take!(hnd)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1a544f0

When launched, ds is ready to be driven. We can drive ds by drive(ds, t) or put!(ds.trigger, t) where t is the time until which we will drive ds.

julia> put!(trg, 1.)

When triggered, ds read the time t from its trigger link, solved its differential equation, computed its value and writes its output value to its output bus. To signal that, the evolution is succeeded, ds writes true to its handshake link which must be taken to further drive ds. (approve!(ds)) can also be used.

julia> take!(hnd)
 true

We can continue to drive ds.

julia> for t in 2. : 10.
            put!(trg, t)
            take!(hnd)
        end

After each evolution, ds writes its current output value to its output bus.

julia> [outbuf(pin.link.buffer) for pin in iport]
 2-element Array{Array{Float64,1},1}:
-<<<<<<< HEAD
- [13357.936086544098, 6152.417249402505, 983.6845435513189, 307.41597304153123, 108.76504726403499, 22.594811272193592, 3.6772938886548214, 2.760743399931241, 1.1626056843795933, 0.9032263315757167  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
- [1253.3460312081259, 3360.0790856600825, 1101.2076099287801, 411.2076014966106, 74.12449584299517, 11.565918370255872, 2.217746784092843, 0.6768581628110747, 0.18368959141685776, 0.32218130973459447  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

When launched, a task was constructed which still running. As long as no exception is thrown during the evolution of ds, the state of task is running which implies ds can be driven.

julia> task
-Task (runnable) @0x00007f512ee59120
+ [0.35186430630144094, 0.6774974069924912, 0.18595393265755591, 0.050055171098182596, 0.06365023450268127, 0.33192875216664103, 0.23311623282949062, 0.09473640588534245, 0.09413124534010711, 0.43293692095336855  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+ [0.10856000636267257, 0.2401496018011247, 0.07140852153177278, 0.019935903121058744, 0.00914037971506524, 0.03675447592035419, 0.18474798657899363, 0.08946833600790209, 0.09805714336724596, 0.16338045890139266  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

When launched, a task was constructed which still running. As long as no exception is thrown during the evolution of ds, the state of task is running which implies ds can be driven.

julia> task
+Task (runnable) @0x00007fdad8328010
 
 julia> task2
-Task (runnable) @0x00007f5125ae9fc0

To terminate the task safely, ds should be terminated safely.

julia> put!(trg, NaN)
-=======
- [206.09837613031382, 203.57400806636684, 46.48337983637946, 10.365688316436716, 2.329913827082058, 0.7470798108764046, 0.2552764786454304, 0.04499031504745595, 0.05569859489384311, 0.24766294166485  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
- [317.08632109910695, 220.56387528402712, 42.640416944191394, 7.972544589451581, 3.235394102918553, 0.573552406271915, 0.32898335664917916, 0.15817700977310173, 0.07295541113383673, 0.20025542564221654  …  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

When launched, a task was constructed which still running. As long as no exception is thrown during the evolution of ds, the state of task is running which implies ds can be driven.

julia> task
-Task (runnable) @0x00007f163dfcfa90
-
-julia> task2
-Task (runnable) @0x00007f1636798280

To terminate the task safely, ds should be terminated safely.

julia> put!(trg, NaN)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1a544f0

To terminate the task safely, ds should be terminated safely.

julia> put!(trg, NaN)
 
 julia> put!(ds.output, [NaN, NaN])
 2-element Array{Float64,1}:
  NaN
  NaN

Note that the state of task is done which implies the task has been terminated safely.

julia> task
-<<<<<<< HEAD
-Task (done) @0x00007f512ee59120
-
-julia> task2
-Task (done) @0x00007f5125ae9fc0

Full API

Causal.@def_rode_systemMacro
@def_rode_system ex

where ex is the expression to define to define a new AbstractRODESystem component type. The usage is as follows:

@def_rode_system mutable struct MyRODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractRODESystem
-=======
-Task (done) @0x00007f163dfcfa90
+Task (done) @0x00007fdad8328010
 
 julia> task2
-Task (done) @0x00007f1636798280

Full API

Jusdl.@def_rode_systemMacro
@def_rode_system ex

where ex is the expression to define to define a new AbstractRODESystem component type. The usage is as follows:

@def_rode_system mutable struct MyRODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractRODESystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (done) @0x00007fdad1a544f0

Full API

Causal.@def_rode_systemMacro
@def_rode_system ex

where ex is the expression to define to define a new AbstractRODESystem component type. The usage is as follows:

@def_rode_system mutable struct MyRODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractRODESystem
     param1::T1 = param1_default                 # optional field 
     param2::T2 = param2_default                 # optional field 
     param3::T3 = param3_default                 # optional field
@@ -122,14 +94,7 @@
            output::OP = Outport(2)
        end
 
-<<<<<<< HEAD
-julia> ds = MySystem();
source
Causal.RODESystemType
RODESystem(; righthandside, readout, state, input, output)

Constructs a generic RODE system

source
Causal.MultiplicativeNoiseLinearSystemType
MultiplicativeNoiseLinearSystem()

Constructs a MultiplicativeNoiseLinearSystem with the dynamics

\[\begin{array}{l} - \dot{x} = A x W -\end{array} -where `W` is the noise process.\]
source
-======= -julia> ds = MySystem();
source
Jusdl.RODESystemType
RODESystem(; righthandside, readout, state, input, output)

Constructs a generic RODE system

source
Causal.RODESystemType
RODESystem(; righthandside, readout, state, input, output)

Constructs a generic RODE system

source
Causal.MultiplicativeNoiseLinearSystemType
MultiplicativeNoiseLinearSystem()

Constructs a MultiplicativeNoiseLinearSystem with the dynamics

\[\begin{array}{l} \dot{x} = A x W \end{array} -where `W` is the noise process.\]
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +where `W` is the noise process.\]source diff --git a/docs/build/manual/components/systems/dynamicsystems/sdesystem/index.html b/docs/build/manual/components/systems/dynamicsystems/sdesystem/index.html index b75550c5..b9a23e8d 100644 --- a/docs/build/manual/components/systems/dynamicsystems/sdesystem/index.html +++ b/docs/build/manual/components/systems/dynamicsystems/sdesystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -SDESystem · Causal

SDESystem

Construction of SDESystems

A SDESystem is represented by the state function

\[ dx = f(x, u, t) dt + h(x, u, t)dW \]

where $t$ is the time, $x \in R^n$ is the value of state, $u \in R^p$ is the value of the input. $W$ is the Wiener process of the system. The output function is defined by

\[ y = g(x, u, t)\]

where $y$ is the value of output at time $t$.

As an example consider a system with the following stochastic differential equation

\[ \begin{array}{l} -======= -SDESystem · Jusdl

SDESystem

Construction of SDESystems

A SDESystem is represented by the state function

\[ dx = f(x, u, t) dt + h(x, u, t)dW \]

where $t$ is the time, $x \in R^n$ is the value of state, $u \in R^p$ is the value of the input. $W$ is the Wiener process of the system. The output function is defined by

\[ y = g(x, u, t)\]

where $y$ is the value of output at time $t$.

As an example consider a system with the following stochastic differential equation

\[ \begin{array}{l} ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +SDESystem · Causal

SDESystem

Construction of SDESystems

A SDESystem is represented by the state function

\[ dx = f(x, u, t) dt + h(x, u, t)dW \]

where $t$ is the time, $x \in R^n$ is the value of state, $u \in R^p$ is the value of the input. $W$ is the Wiener process of the system. The output function is defined by

\[ y = g(x, u, t)\]

where $y$ is the value of output at time $t$.

As an example consider a system with the following stochastic differential equation

\[ \begin{array}{l} dx = -x dt - x dW \end{array}\]

and the following output equation

\[y = x\]

The state function statefunc and the output function outputfunc is defined as follows.

julia> using Causal # hide
 
@@ -36,11 +32,7 @@
 julia> task2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (failed) @0x00007f512fa06980
-=======
-Task (failed) @0x00007f163e74f5b0
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (failed) @0x00007fdad8a224a0
 MethodError: no method matching take!(::Missing)
 Closest candidates are:
   take!(!Matched::Distributed.WorkerPool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Distributed/src/workerpool.jl:136
@@ -97,11 +89,7 @@
 ERROR: UndefVarError: task not defined
 
 julia> task2
-<<<<<<< HEAD
-Task (failed) @0x00007f512fa06980
-=======
-Task (failed) @0x00007f163e74f5b0
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (failed) @0x00007fdad8a224a0
 MethodError: no method matching take!(::Missing)
 Closest candidates are:
   take!(!Matched::Distributed.WorkerPool) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Distributed/src/workerpool.jl:136
@@ -120,11 +108,7 @@
 materialize at ./broadcast.jl:837 [inlined]
 take!(::Inport{Inpin{Float64}}) at /home/sari/.julia/dev/Causal/src/connections/port.jl:178
 macro expansion at ./none:2 [inlined]
-<<<<<<< HEAD
 (::Main.ex-sde_system_ex.var"#1#2")() at ./task.jl:356

Full API

Causal.@def_sde_systemMacro
@def_sde_system ex

where ex is the expression to define to define a new AbstractSDESystem component type. The usage is as follows:

@def_sde_system mutable struct MySDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractSDESystem
-=======
-(::Main.ex-sde_system_ex.var"#1#2")() at ./task.jl:356

Full API

Jusdl.@def_sde_systemMacro
@def_sde_system ex

where ex is the expression to define to define a new AbstractSDESystem component type. The usage is as follows:

@def_sde_system mutable struct MySDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractSDESystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
     param1::T1 = param1_default                 # optional field 
     param2::T2 = param2_default                 # optional field 
     param3::T3 = param3_default                 # optional field
@@ -153,8 +137,4 @@
            output::OP = Outport(2)
        end
 
-<<<<<<< HEAD
-julia> ds = MySDESystem();
source
Causal.SDESystemType
SDESystem(; drift, diffusion, readout, state, input, output)

Constructs a SDE system.

source
-======= -julia> ds = MySDESystem();
source
Jusdl.SDESystemType
SDESystem(; drift, diffusion, readout, state, input, output)

Constructs a SDE system.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +julia> ds = MySDESystem();source
Causal.SDESystemType
SDESystem(; drift, diffusion, readout, state, input, output)

Constructs a SDE system.

source
diff --git a/docs/build/manual/components/systems/staticsystems/staticsystems/index.html b/docs/build/manual/components/systems/staticsystems/staticsystems/index.html index 945faf63..7c3875e1 100644 --- a/docs/build/manual/components/systems/staticsystems/staticsystems/index.html +++ b/docs/build/manual/components/systems/staticsystems/staticsystems/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -StaticSystems · Causal

StaticSystems

Basic Operation of StaticSystems

A static system is a system whose output y at time t depends on the current time t and the value of its input u. The input-output relation of a static systems is represented by its output function outputfunc which is of the form

\[ y = g(u, t)\]

where g is the output function outputfunc. Note that outputfunc is expected to have two inputs, the value u of the input and the current time t. The simulation in Causal is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t. Therefore, for example, the system modeled by

\[y(t) = g(u(t),t)\]

is actually sampled at clock ticks t which is generated by a Clock. Therefore the sampled system corresponds to

\[y[k] = g(u_k, t_k)\]

where $k$ is $k_i T_s$ where $k_i$ is an integer number, $T_s$ is the sampling interval. $T_s$ corresponds to sampling time dt of Clock. Thus, the system given above is coded like

function g(u, t)
-=======
-StaticSystems · Jusdl

StaticSystems

Basic Operation of StaticSystems

A static system is a system whose output y at time t depends on the current time t and the value of its input u. The input-output relation of a static systems is represented by its output function outputfunc which is of the form

\[ y = g(u, t)\]

where g is the output function outputfunc. Note that outputfunc is expected to have two inputs, the value u of the input and the current time t. The simulation in Jusdl is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t. Therefore, for example, the system modeled by

\[y(t) = g(u(t),t)\]

is actually sampled at clock ticks t which is generated by a Clock. Therefore the sampled system corresponds to

\[y[k] = g(u_k, t_k)\]

where $k$ is $k_i T_s$ where $k_i$ is an integer number, $T_s$ is the sampling interval. $T_s$ corresponds to sampling time dt of Clock. Thus, the system given above is coded like

function g(u, t)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+StaticSystems · Causal

StaticSystems

Basic Operation of StaticSystems

A static system is a system whose output y at time t depends on the current time t and the value of its input u. The input-output relation of a static systems is represented by its output function outputfunc which is of the form

\[ y = g(u, t)\]

where g is the output function outputfunc. Note that outputfunc is expected to have two inputs, the value u of the input and the current time t. The simulation in Causal is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t. Therefore, for example, the system modeled by

\[y(t) = g(u(t),t)\]

is actually sampled at clock ticks t which is generated by a Clock. Therefore the sampled system corresponds to

\[y[k] = g(u_k, t_k)\]

where $k$ is $k_i T_s$ where $k_i$ is an integer number, $T_s$ is the sampling interval. $T_s$ corresponds to sampling time dt of Clock. Thus, the system given above is coded like

function g(u, t)
     # Define the relation `y = g(u, t)`
 end

For further clarity, let us continue with a case study. Consider the following static system,

\[ y(t) = g(u(t), t) = \left[ \begin{array}{l} @@ -35,20 +31,12 @@ Link(state:open, eltype:Bool, isreadable:false, iswritable:false) julia> task = launch(ss) -<<<<<<< HEAD -Task (runnable) @0x00007f512ee59fc0 -======= -Task (runnable) @0x00007f163f430eb0 ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Task (runnable) @0x00007fdad9410760 julia> taskout = @async while true all(take!(iport) .=== NaN) && break end -<<<<<<< HEAD -Task (runnable) @0x00007f512ee5a980

Now, ss is drivable from its trg pin.

julia> ss.trigger.link
-=======
-Task (runnable) @0x00007f163f431ae0

Now, ss is drivable from its trg pin.

julia> ss.trigger.link
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad9411390

Now, ss is drivable from its trg pin.

julia> ss.trigger.link
 Link(state:open, eltype:Float64, isreadable:false, iswritable:true)

Now let us drive ss.

julia> put!(trg, 1.)

As this point ss wait for its to be written. Let us write some data to oport.

julia> put!(oport, [10., 10.])
 2-element Array{Float64,1}:
  10.0
@@ -102,11 +90,7 @@
     0.0
     0.0
     0.0
-<<<<<<< HEAD
     0.0

In addition to the generic StaticSystem, Causal provides some well-known static systems given in the next section.

Full API

Causal.@def_static_systemMacro
@def_static_system ex

where ex is the expression to define to define a new AbstractStaticSystem component type. The usage is as follows:

@def_source struct MyStaticSystem{T1,T2,T3,...,TN,OP, RO} <: AbstractStaticSystem
-=======
-    0.0

In addition to the generic StaticSystem, Jusdl provides some well-known static systems given in the next section.

Full API

Jusdl.@def_static_systemMacro
@def_static_system ex

where ex is the expression to define to define a new AbstractStaticSystem component type. The usage is as follows:

@def_source struct MyStaticSystem{T1,T2,T3,...,TN,OP, RO} <: AbstractStaticSystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
     param1::T1 = param1_default     # optional field 
     param2::T2 = param2_default     # optional field 
     param3::T3 = param3_default     # optional field
@@ -130,11 +114,7 @@
 
 julia> sys.input
 1-element Inport{Inpin{Float64}}:
-<<<<<<< HEAD
- Inpin(eltype:Float64, isbound:false)
source
Causal.StaticSystemType
StaticSystem(; readout, input, output)

Consructs a generic static system with readout function, input port and output port.

Example

julia> ss = StaticSystem(readout = (t,u) -> u[1] + u[2], input=Inport(2), output=Outport(1));
-=======
- Inpin(eltype:Float64, isbound:false)
source
Jusdl.StaticSystemType
StaticSystem(; readout, input, output)

Consructs a generic static system with readout function, input port and output port.

Example

julia> ss = StaticSystem(readout = (t,u) -> u[1] + u[2], input=Inport(2), output=Outport(1));
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ Inpin(eltype:Float64, isbound:false)
source
Causal.StaticSystemType
StaticSystem(; readout, input, output)

Consructs a generic static system with readout function, input port and output port.

Example

julia> ss = StaticSystem(readout = (t,u) -> u[1] + u[2], input=Inport(2), output=Outport(1));
 
 julia> ss.readout(0., ones(2))
 2.0
source
Causal.AdderType
Adder(signs=(+,+))

Construts an Adder with input bus input and signs signs. signs is a tuplle of + and/or -. The output function g of Adder is of the form,

\[ y = g(u, t) = \sum_{j = 1}^n s_k u_k\]

where n is the length of the input, $s_k$ is the kth element of signs, $u_k$ is the kth value of input and $y$ is the value of output. The default value of signs is all +.

Example

julia> adder = Adder(signs=(+, +, -));
@@ -153,8 +133,4 @@
 Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
 
 julia> Memory(delay=0.1, numtaps=5)
-<<<<<<< HEAD
-Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
source
Causal.CouplerType
Coupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)

Constructs a coupler from connection matrix conmat of size $n \times n$ and coupling matrix cplmat of size $d \times d$. The output function g of Coupler is of the form

\[ y = g(u, t) = (E \otimes P) u\]

where $\otimes$ is the Kronecker product, $E$ is conmat and $P$ is cplmat, $u$ is the value of input and y is the value of output.

source
Causal.DifferentiatorType
Differentiator(kd=1; callbacks=nothing, name=Symbol())

Consructs a Differentiator whose input output relation is of the form

\[ y(t) = k_d \dot{u}(t)\]

where $u(t)$ is the input and $y(t)$ is the output and $kd$ is the differentiation constant.

source
-======= -Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
source
Jusdl.CouplerType
Coupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)

Constructs a coupler from connection matrix conmat of size $n \times n$ and coupling matrix cplmat of size $d \times d$. The output function g of Coupler is of the form

\[ y = g(u, t) = (E \otimes P) u\]

where $\otimes$ is the Kronecker product, $E$ is conmat and $P$ is cplmat, $u$ is the value of input and y is the value of output.

source
Jusdl.DifferentiatorType
Differentiator(kd=1; callbacks=nothing, name=Symbol())

Consructs a Differentiator whose input output relation is of the form

\[ y(t) = k_d \dot{u}(t)\]

where $u(t)$ is the input and $y(t)$ is the output and $kd$ is the differentiation constant.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
source
Causal.CouplerType
Coupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)

Constructs a coupler from connection matrix conmat of size $n \times n$ and coupling matrix cplmat of size $d \times d$. The output function g of Coupler is of the form

\[ y = g(u, t) = (E \otimes P) u\]

where $\otimes$ is the Kronecker product, $E$ is conmat and $P$ is cplmat, $u$ is the value of input and y is the value of output.

source
Causal.DifferentiatorType
Differentiator(kd=1; callbacks=nothing, name=Symbol())

Consructs a Differentiator whose input output relation is of the form

\[ y(t) = k_d \dot{u}(t)\]

where $u(t)$ is the input and $y(t)$ is the output and $kd$ is the differentiation constant.

source
diff --git a/docs/build/manual/components/systems/staticsystems/subsystem/index.html b/docs/build/manual/components/systems/staticsystems/subsystem/index.html index f583fb57..ff39a11c 100644 --- a/docs/build/manual/components/systems/staticsystems/subsystem/index.html +++ b/docs/build/manual/components/systems/staticsystems/subsystem/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Subsystem · Causal

Subsystem

Construction of SubSystems

A SubSystem consists of connected components. Thus, to construct a SubSystem, we first construct components, connect them and specify the input and output of SubSystem.

Basic Operation of SubSystems

The operation of a SubSystem is very similar to that of a StaticSystem. The only difference is that when a SubSystem is triggered through its trigger pin, it distributes the trigger to the trigger pins of its components. Then, each of the components of the SubSystem takes steps individually.

Let us construct a subsystem consisting of a generator and an adder.

julia> using Causal # hide
-=======
-Subsystem · Jusdl

Subsystem

Construction of SubSystems

A SubSystem consists of connected components. Thus, to construct a SubSystem, we first construct components, connect them and specify the input and output of SubSystem.

Basic Operation of SubSystems

The operation of a SubSystem is very similar to that of a StaticSystem. The only difference is that when a SubSystem is triggered through its trigger pin, it distributes the trigger to the trigger pins of its components. Then, each of the components of the SubSystem takes steps individually.

Let us construct a subsystem consisting of a generator and an adder.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Subsystem · Causal

Subsystem

Construction of SubSystems

A SubSystem consists of connected components. Thus, to construct a SubSystem, we first construct components, connect them and specify the input and output of SubSystem.

Basic Operation of SubSystems

The operation of a SubSystem is very similar to that of a StaticSystem. The only difference is that when a SubSystem is triggered through its trigger pin, it distributes the trigger to the trigger pins of its components. Then, each of the components of the SubSystem takes steps individually.

Let us construct a subsystem consisting of a generator and an adder.

julia> using Causal # hide
 
 julia> gen = ConstantGenerator()
 ConstantGenerator(amp:1.0)
@@ -35,11 +31,7 @@
 julia> t2 = @async while true
            all(take!(iport) .=== NaN) && break
            end
-<<<<<<< HEAD
-Task (failed) @0x00007f513099d120
-=======
-Task (failed) @0x00007f163e5d6710
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (failed) @0x00007fdad7bfabf0
 UndefVarError: iport not defined
 macro expansion at ./none:2 [inlined]
 (::Main.ex-subsystem_ex.var"#1#2")() at ./task.jl:356

sub is ready to be triggered,

julia> put!(trg, 1.)
@@ -49,8 +41,4 @@
 ERROR: UndefVarError: sub not defined
 
 julia> sub.components[2].output[1].links[1].buffer[1]
-<<<<<<< HEAD
-ERROR: UndefVarError: sub not defined

Note that when sub is triggered, sub transfer the trigger to all its internal components.

-======= -ERROR: UndefVarError: sub not defined

Note that when sub is triggered, sub transfer the trigger to all its internal components.

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +ERROR: UndefVarError: sub not defined

Note that when sub is triggered, sub transfer the trigger to all its internal components.

diff --git a/docs/build/manual/connections/link/index.html b/docs/build/manual/connections/link/index.html index 868cd03f..f8840f81 100644 --- a/docs/build/manual/connections/link/index.html +++ b/docs/build/manual/connections/link/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Links · Causal

Links

Links are built on top of Channels of Julia. They are used as communication primitives for Tasks of Julia. A Link basically includes a Channel and a Buffer. The mode of the buffer is Cyclic.(see Buffer Modes for information on buffer modes). Every item sent through a Link is sent through the channel of the Link and written to the Buffer so that all the data flowing through a Link is recorded.

The construction of a Link is very simple: just specify its buffer length and element type.

julia> using Causal # hide
-=======
-Links · Jusdl

Links

Links are built on top of Channels of Julia. They are used as communication primitives for Tasks of Julia. A Link basically includes a Channel and a Buffer. The mode of the buffer is Cyclic.(see Buffer Modes for information on buffer modes). Every item sent through a Link is sent through the channel of the Link and written to the Buffer so that all the data flowing through a Link is recorded.

The construction of a Link is very simple: just specify its buffer length and element type.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Links · Causal

Links

Links are built on top of Channels of Julia. They are used as communication primitives for Tasks of Julia. A Link basically includes a Channel and a Buffer. The mode of the buffer is Cyclic.(see Buffer Modes for information on buffer modes). Every item sent through a Link is sent through the channel of the Link and written to the Buffer so that all the data flowing through a Link is recorded.

The construction of a Link is very simple: just specify its buffer length and element type.

julia> using Causal # hide
 
 julia> Link{Bool}(5)
 Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
@@ -15,11 +11,7 @@
 Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
 
 julia> Link()
-<<<<<<< HEAD
 Link(state:open, eltype:Float64, isreadable:false, iswritable:false)

The data can be read from and written into Links if active tasks are bound to them. Links can be thought of like a pipe. In order to write data to a Link from one of its ends, a task that reads written data from the other end must be bounded to the Link. Similarly, in order to read data from one of the Link from one of its end, a task that writes the read data must be bound to the Link. Reading from and writing to Link is carried out with take! and put! functions. For more clarity, let us see some examples.

Let us first construct a Link,


-=======
-Link(state:open, eltype:Float64, isreadable:false, iswritable:false)

The data can be read from and written into Links if active tasks are bound to them. Links can be thought of like a pipe. In order to write data to a Link from one of its ends, a task that reads written data from the other end must be bounded to the Link. Similarly, in order to read data from one of the Link from one of its end, a task that writes the read data must be bound to the Link. Reading from and writing to Link is carried out with take! and put! functions. For more clarity, let us see some examples.

Let us first construct a Link,


->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 julia> l = Link(5)
 Link(state:open, eltype:Float64, isreadable:false, iswritable:false)

l is a Link with a buffer length of 5 and element type of Float64. Not that the l is open, but it is not ready for data reading or writing. To write data, we must bound a task that reads the written data.

julia> function reader(link::Link)  # Define job.
            while true
@@ -30,11 +22,7 @@
 reader (generic function with 1 method)
 
 julia> t = @async reader(l)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ef53d00

The reader is defined such that the data written from one end of l is read until the data is NaN. Now, we have runnable a task t. This means the l is ready for data writing.

julia> put!(l, 1.)
-=======
-Task (runnable) @0x00007f163dbf9ae0

The reader is defined such that the data written from one end of l is read until the data is NaN. Now, we have runnable a task t. This means the l is ready for data writing.

julia> put!(l, 1.)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1a549d0

The reader is defined such that the data written from one end of l is read until the data is NaN. Now, we have runnable a task t. This means the l is ready for data writing.

julia> put!(l, 1.)
 1.0
 
 julia> put!(l, 2.)
@@ -48,19 +36,11 @@
 NaN
 
 julia> t   # Show that the `t` is terminated.
-<<<<<<< HEAD
-Task (done) @0x00007f512ef53d00

Whenever the bound task to the l is runnable, the data can be written to l. That is, the data length that can be written to l is not limited by the buffer length of l. But, beware that the buffer of Links is Cyclic. That means, when the buffer is full, its data is overwritten.

julia> l = Link(5)
+Task (done) @0x00007fdad1a549d0

Whenever the bound task to the l is runnable, the data can be written to l. That is, the data length that can be written to l is not limited by the buffer length of l. But, beware that the buffer of Links is Cyclic. That means, when the buffer is full, its data is overwritten.

julia> l = Link(5)
 Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
 
 julia> t = @async reader(l)
-Task (runnable) @0x00007f512f346980
-=======
-Task (done) @0x00007f163dbf9ae0

Whenever the bound task to the l is runnable, the data can be written to l. That is, the data length that can be written to l is not limited by the buffer length of l. But, beware that the buffer of Links is Cyclic. That means, when the buffer is full, its data is overwritten.

julia> l = Link(5)
-Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
-
-julia> t = @async reader(l)
-Task (runnable) @0x00007f163dd2e980
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1cebd00
 
 julia> for item in 1. : 10.
            put!(l, item)
@@ -87,11 +67,7 @@
 writer (generic function with 1 method)
 
 julia> t = @async writer(l, 1.:5.)
-<<<<<<< HEAD
-Task (runnable) @0x00007f512fa07a90
-=======
-Task (runnable) @0x00007f163de27340
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad7a18c40
 
 julia> bind(l, t)
 Channel{Float64}(sz_max:0,sz_curr:1)
@@ -101,11 +77,7 @@
 
 julia> take!(l)
 2.0

It is possible to read data from l until t is active. To read all the data at once, collect can be used.

julia> t
-<<<<<<< HEAD
-Task (runnable) @0x00007f512fa07a90
-=======
-Task (runnable) @0x00007f163de27340
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad7a18c40
 
 julia> collect(l)
 3-element Array{Float64,1}:
@@ -114,15 +86,11 @@
  5.0
 
 julia> t  # Show that `t` is terminated.
-<<<<<<< HEAD
-Task (done) @0x00007f512fa07a90

Full API

Causal.LinkType
Link{T}(ln::Int=64) where {T}

Constructs a Link with element type T and buffer length ln. The buffer element type is T and mode is Cyclic.

Link(ln::Int=64)

Constructs a Link with element type Float64 and buffer length ln. The buffer element type is Float64 and mode is Cyclic.

Example

julia> l = Link{Int}(5)
-=======
-Task (done) @0x00007f163de27340

Full API

Jusdl.LinkType
Link{T}(ln::Int=64) where {T}

Constructs a Link with element type T and buffer length ln. The buffer element type is T and mode is Cyclic.

Link(ln::Int=64)

Constructs a Link with element type Float64 and buffer length ln. The buffer element type is Float64 and mode is Cyclic.

Example

julia> l = Link{Int}(5)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (done) @0x00007fdad7a18c40

Full API

Causal.LinkType
Link{T}(ln::Int=64) where {T}

Constructs a Link with element type T and buffer length ln. The buffer element type is T and mode is Cyclic.

Link(ln::Int=64)

Constructs a Link with element type Float64 and buffer length ln. The buffer element type is Float64 and mode is Cyclic.

Example

julia> l = Link{Int}(5)
 Link(state:open, eltype:Int64, isreadable:false, iswritable:false)
 
 julia> l = Link{Bool}()
-Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
source
Base.bindMethod
bind(link::Link, task::Task)

Binds task to link. When task is done link is closed.

source
Base.collectMethod
collect(link::Link)

Collects all the available data on the link.

Warning

To collect all available data from link, a task must be bounded to it.

Example

julia> l = Link();  # Construct a link.
+Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
source
Base.bindMethod
bind(link::Link, task::Task)

Binds task to link. When task is done link is closed.

source
Base.collectMethod
collect(link::Link)

Collects all the available data on the link.

Warning

To collect all available data from link, a task must be bounded to it.

Example

julia> l = Link();  # Construct a link.
 
 julia> t = @async for item in 1 : 5  # Construct a task
        put!(l, item)
@@ -140,7 +108,7 @@
 3-element Array{Float64,1}:
  3.0
  4.0
- 5.0
source
Base.isopenMethod
isopen(link::Link)

Returns true if link is open. A link is open if its channel is open.

source
Base.isreadableMethod
isreadable(link::Link)

Returns true if link is readable. When link is readable, data can be read from link with take function.

source
Base.iswritableMethod
writable(link::Link)

Returns true if link is writable. When link is writable, data can be written into link with put function.

source
Base.put!Method
put!(link::Link, val)

Puts val to link. val is handed over to the channel of link. val is also written in to the buffer of link.

Warning

link must be writable to put val. That is, a runnable task that takes items from the link must be bounded to link.

Example

julia> l = Link();
+ 5.0
source
Base.isopenMethod
isopen(link::Link)

Returns true if link is open. A link is open if its channel is open.

source
Base.isreadableMethod
isreadable(link::Link)

Returns true if link is readable. When link is readable, data can be read from link with take function.

source
Base.iswritableMethod
writable(link::Link)

Returns true if link is writable. When link is writable, data can be written into link with put function.

source
Base.put!Method
put!(link::Link, val)

Puts val to link. val is handed over to the channel of link. val is also written in to the buffer of link.

Warning

link must be writable to put val. That is, a runnable task that takes items from the link must be bounded to link.

Example

julia> l = Link();
 
 julia> t  = @async while true 
        item = take!(l)
@@ -159,7 +127,7 @@
 2.0
 
 julia> put!(l, NaN)
-NaN
source
Base.take!Method
take!(link::Link)

Take an element from link.

Warning

link must be readable to take value. That is, a runnable task that puts items from the link must be bounded to link.

Example

julia> l = Link(5);
+NaN
source
Base.take!Method
take!(link::Link)

Take an element from link.

Warning

link must be readable to take value. That is, a runnable task that puts items from the link must be bounded to link.

Example

julia> l = Link(5);
 
 julia> t = @async for item in 1. : 5.
        put!(l, item)
@@ -171,8 +139,4 @@
 1.0
 
 julia> take!(l)
-<<<<<<< HEAD
-2.0
source
Causal.launchMethod
launch(link:Link, valrange)

Constructs a putter task and binds it to link. putter tasks puts the data in valrange.

source
Causal.launchMethod
launch(link::Link)

Constructs a taker task and binds it to link. The taker task reads the data and prints an info message until missing is read from the link.

source
Causal.refresh!Method
refresh!(link::Link)

Reconstructst the channel of link is its channel is closed.

source
-======= -2.0
source
Jusdl.isfullMethod
isfull(link::Link)

Returns true if the buffer of link is full.

source
Jusdl.launchMethod
launch(link:Link, valrange)

Constructs a putter task and binds it to link. putter tasks puts the data in valrange.

source
Jusdl.launchMethod
launch(link::Link)

Constructs a taker task and binds it to link. The taker task reads the data and prints an info message until missing is read from the link.

source
Jusdl.refresh!Method
refresh!(link::Link)

Reconstructst the channel of link is its channel is closed.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +2.0source
Causal.launchMethod
launch(link:Link, valrange)

Constructs a putter task and binds it to link. putter tasks puts the data in valrange.

source
Causal.launchMethod
launch(link::Link)

Constructs a taker task and binds it to link. The taker task reads the data and prints an info message until missing is read from the link.

source
Causal.refresh!Method
refresh!(link::Link)

Reconstructst the channel of link is its channel is closed.

source
diff --git a/docs/build/manual/connections/pin/index.html b/docs/build/manual/connections/pin/index.html index 1c2552ba..ce32b9b0 100644 --- a/docs/build/manual/connections/pin/index.html +++ b/docs/build/manual/connections/pin/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Pins · Causal

Pins

Pins are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin and Inpin. The data flows from inside of the components to its outside through Outpin while data flow from outside of the components to its inside through Inpin.

Connection and Disconnection of Pins

In Causal, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Causal). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Links. A Link connects Outpins to Inpins, and the data flow is from Outpin to Inpin.

Note

As the data movement is from Outpin to Inpin, connection of an Inpin to an Outpin gives a MethodError.

For example, let us construct and Outpin and Inpins and connect the together.

julia> using Causal # hide
-=======
-Pins · Jusdl

Pins

Pins are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin and Inpin. The data flows from inside of the components to its outside through Outpin while data flow from outside of the components to its inside through Inpin.

Connection and Disconnection of Pins

In Jusdl, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Jusdl). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Links. A Link connects Outpins to Inpins, and the data flow is from Outpin to Inpin.

Note

As the data movement is from Outpin to Inpin, connection of an Inpin to an Outpin gives a MethodError.

For example, let us construct and Outpin and Inpins and connect the together.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Pins · Causal

Pins

Pins are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin and Inpin. The data flows from inside of the components to its outside through Outpin while data flow from outside of the components to its inside through Inpin.

Connection and Disconnection of Pins

In Causal, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Causal). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Links. A Link connects Outpins to Inpins, and the data flow is from Outpin to Inpin.

Note

As the data movement is from Outpin to Inpin, connection of an Inpin to an Outpin gives a MethodError.

For example, let us construct and Outpin and Inpins and connect the together.

julia> using Causal # hide
 
 julia> op = Outpin()
 Outpin(eltype:Float64, isbound:false)
@@ -17,17 +13,10 @@
 true
 
 julia> ip.link === link
-<<<<<<< HEAD
 true
Note

It is possible for an Outpin to have multiple Links bound to itself. On contract, an Inpin can have just one Link.

The connected links Outpin and Inpin can be disconnected using disconnect! function. When disconnected, the data transfer from the Outpin to Inpin is not possible.

Data Flow Through Pins

The data flow from an Outpin to an Inpin. However for data flow through a pin, a running task must be bound the channel of the link of the pin. See the example below.

julia> t = @async while true
            take!(ip) === NaN && break
        end
-Task (runnable) @0x00007f5125ae8280

As the task t is bound the channel of the link data can flow through op and ip.

julia> put!(op, 1.)
-=======
-true
Note

It is possible for an Outpin to have multiple Links bound to itself. On contract, an Inpin can have just one Link.

The connected links Outpin and Inpin can be disconnected using disconnect! function. When disconnected, the data transfer from the Outpin to Inpin is not possible.

Data Flow Through Pins

The data flow from an Outpin to an Inpin. However for data flow through a pin, a running task must be bound the channel of the link of the pin. See the example below.

julia> t = @async while true
-           take!(ip) === NaN && break
-       end
-Task (runnable) @0x00007f163dbe5ae0

As the task t is bound the channel of the link data can flow through op and ip.

julia> put!(op, 1.)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdadc07a230

As the task t is bound the channel of the link data can flow through op and ip.

julia> put!(op, 1.)
 
 julia> put!(op, 2.)
 
@@ -40,21 +29,13 @@
 julia> t2 = @async for item in 1 : 5
            put!(op2, item)
        end
-<<<<<<< HEAD
-Task (runnable) @0x00007f512ed97d00
-=======
-Task (runnable) @0x00007f163dd2fa90
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1ce9ae0
 
 julia> take!(ip2)
 1.0
 
 julia> take!(ip2)
-<<<<<<< HEAD
-2.0

Note that in both of the cases given above the data flow is always from an Outpin to an Inpin.

Warning

It is not possible to take data from an Outpin and put into Inpin. Thus, take!(pin::Outpoin) and put!(pin::Inpin) throws a method error.

Full API

Causal.InpinType
Inpin{T}()

Constructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.

source
Causal.OutpinType
Outpin{T}()

Constructs and OutPut pin. The data flow from Outpin is outwards from the pin i.e., data is written from OutPort to its links.

source
Base.bindMethod
bind(link::Link, pin)

Binds link to pin. When bound, data written into or read from pin is written into or read from link.

source
Base.put!Method
put!(pin::Outpin, val)

Puts val to pin. val is put into the links of pin.

Warning

To take data from pin, a running task that puts data must be bound to link of pin.

Example

julia> op = Outpin();
-=======
-2.0

Note that in both of the cases given above the data flow is always from an Outpin to an Inpin.

Warning

It is not possible to take data from an Outpin and put into Inpin. Thus, take!(pin::Outpoin) and put!(pin::Inpin) throws a method error.

Full API

Jusdl.InpinType
Inpin{T}()

Constructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.

source
Jusdl.OutpinType
Outpin{T}()

Constructs and OutPut pin. The data flow from Outpin is outwards from the pin i.e., data is written from OutPort to its links.

source
Base.bindMethod
bind(link::Link, pin)

Binds link to pin. When bound, data written into or read from pin is written into or read from link.

source
Base.put!Method
put!(pin::Outpin, val)

Puts val to pin. val is put into the links of pin.

Warning

To take data from pin, a running task that puts data must be bound to link of pin.

Example

julia> op = Outpin();
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+2.0

Note that in both of the cases given above the data flow is always from an Outpin to an Inpin.

Warning

It is not possible to take data from an Outpin and put into Inpin. Thus, take!(pin::Outpoin) and put!(pin::Inpin) throws a method error.

Full API

Causal.InpinType
Inpin{T}()

Constructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.

source
Causal.OutpinType
Outpin{T}()

Constructs and OutPut pin. The data flow from Outpin is outwards from the pin i.e., data is written from OutPort to its links.

source
Base.bindMethod
bind(link::Link, pin)

Binds link to pin. When bound, data written into or read from pin is written into or read from link.

source
Base.put!Method
put!(pin::Outpin, val)

Puts val to pin. val is put into the links of pin.

Warning

To take data from pin, a running task that puts data must be bound to link of pin.

Example

julia> op = Outpin();
 
 julia> l = Link();
 
@@ -72,7 +53,7 @@
 julia> put!(op, 3.)
 Took 3.0
 
-julia> put!(op, NaN)
source
Base.take!Method
take!(pin::Inpin)

Takes data from pin. The data is taken from the links of pin.

Warning

To take data from pin, a running task that puts data must be bound to link of pin.

Example

julia> ip = Inpin();
+julia> put!(op, NaN)
source
Base.take!Method
take!(pin::Inpin)

Takes data from pin. The data is taken from the links of pin.

Warning

To take data from pin, a running task that puts data must be bound to link of pin.

Example

julia> ip = Inpin();
 
 julia> l = Link();
 
@@ -86,11 +67,7 @@
 1.0
 
 julia> take!(ip)
-<<<<<<< HEAD
-2.0
source
Causal.connect!Method
connect!(outpin::Link, inpin::Link)

Connects outpin to inpin. When connected, any element that is put into outpin is also put into inpin.

connect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})

Connects each link in outpin to each link in inpin one by one. See also: disconnect!

Example

julia> op, ip = Outpin(), Inpin();
-=======
-2.0
source
Jusdl.connect!Method
connect!(outpin::Link, inpin::Link)

Connects outpin to inpin. When connected, any element that is put into outpin is also put into inpin.

connect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})

Connects each link in outpin to each link in inpin one by one. See also: disconnect!

Example

julia> op, ip = Outpin(), Inpin();
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+2.0
source
Causal.connect!Method
connect!(outpin::Link, inpin::Link)

Connects outpin to inpin. When connected, any element that is put into outpin is also put into inpin.

connect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})

Connects each link in outpin to each link in inpin one by one. See also: disconnect!

Example

julia> op, ip = Outpin(), Inpin();
 
 julia> l = connect!(op, ip)
 Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
@@ -99,8 +76,4 @@
 true
 
 julia> ip.link === l
-<<<<<<< HEAD
-true
source
Causal.disconnect!Method
disconnect!(link1::Link, link2::Link)

Disconnects link1 and link2. The order of arguments is not important. See also: connect!

source
-======= -true
source
Jusdl.disconnect!Method
disconnect!(link1::Link, link2::Link)

Disconnects link1 and link2. The order of arguments is not important. See also: connect!

source
Jusdl.isboundMethod
isbound(pin::AbstractPin)

Returns true if pin is bound to other pins.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +truesource
Causal.disconnect!Method
disconnect!(link1::Link, link2::Link)

Disconnects link1 and link2. The order of arguments is not important. See also: connect!

source
diff --git a/docs/build/manual/connections/port/index.html b/docs/build/manual/connections/port/index.html index 3ff7a843..644cc4c2 100644 --- a/docs/build/manual/connections/port/index.html +++ b/docs/build/manual/connections/port/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Ports · Causal

Ports

A Port is actually is a bunch of pins (See Pins for mor information on pins.). As such, the connection, disconnection and data transfer are very similar to those of pins. Basically, there are two type of port: Outport and Inport. The data flows from outside of a component to its inside through an Inport while data flows from inside of the component to its outside through an Outport.

Construction of Ports

A port (both Inport and Outport) is constructed by specifying its element type T, the number of pins npins and the buffer length of its pins.


-=======
-Ports · Jusdl

Ports

A Port is actually is a bunch of pins (See Pins for mor information on pins.). As such, the connection, disconnection and data transfer are very similar to those of pins. Basically, there are two type of port: Outport and Inport. The data flows from outside of a component to its inside through an Inport while data flows from inside of the component to its outside through an Outport.

Construction of Ports

A port (both Inport and Outport) is constructed by specifying its element type T, the number of pins npins and the buffer length of its pins.


->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Ports · Causal

Ports

A Port is actually is a bunch of pins (See Pins for mor information on pins.). As such, the connection, disconnection and data transfer are very similar to those of pins. Basically, there are two type of port: Outport and Inport. The data flows from outside of a component to its inside through an Inport while data flows from inside of the component to its outside through an Outport.

Construction of Ports

A port (both Inport and Outport) is constructed by specifying its element type T, the number of pins npins and the buffer length of its pins.


 julia> Outport{Bool}(5)
 5-element Outport{Outpin{Bool}}:
  Outpin(eltype:Bool, isbound:false)
@@ -118,11 +114,7 @@
            all(val .=== NaN) && break
            println("Took " * string(val))
        end
-<<<<<<< HEAD
-Task (runnable) @0x00007f512fa48010
-=======
-Task (runnable) @0x00007f1645c270d0
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdadc079120
 
 julia> put!(op3, 1.);
 Took [1.0, 1.0]
@@ -183,29 +175,21 @@
        end
 pin = Inpin(eltype:Float64, isbound:false)
 pin = Inpin(eltype:Float64, isbound:false)
-<<<<<<< HEAD
-pin = Inpin(eltype:Float64, isbound:false)

Full API

Causal.InportType
Inport{T}(numpins=1)

Constructs an Inport with numpins Inpin.

Warning

Element type of an Inport must be Inpin. See also Inpin

Example

julia> Inport{Int}(2)
-=======
-pin = Inpin(eltype:Float64, isbound:false)

Full API

Jusdl.InportType
Inport{T}(numpins=1)

Constructs an Inport with numpins Inpin.

Warning

Element type of an Inport must be Inpin. See also Inpin

Example

julia> Inport{Int}(2)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+pin = Inpin(eltype:Float64, isbound:false)

Full API

Causal.InportType
Inport{T}(numpins=1)

Constructs an Inport with numpins Inpin.

Warning

Element type of an Inport must be Inpin. See also Inpin

Example

julia> Inport{Int}(2)
 2-element Inport{Inpin{Int64}}:
  Inpin(eltype:Int64, isbound:false)
  Inpin(eltype:Int64, isbound:false)
 
 julia> Inport()
 1-element Inport{Inpin{Float64}}:
-<<<<<<< HEAD
- Inpin(eltype:Float64, isbound:false)
source
Causal.OutportType
Outport{T}(numpins=1)

Constructs an Outport with numpins Outpin.

Warning

Element type of an Outport must be Outpin. See also Outpin

Example

julia> Outport{Int}(2)
-=======
- Inpin(eltype:Float64, isbound:false)
source
Jusdl.OutportType
Outport{T}(numpins=1)

Constructs an Outport with numpins Outpin.

Warning

Element type of an Outport must be Outpin. See also Outpin

Example

julia> Outport{Int}(2)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ Inpin(eltype:Float64, isbound:false)
source
Causal.OutportType
Outport{T}(numpins=1)

Constructs an Outport with numpins Outpin.

Warning

Element type of an Outport must be Outpin. See also Outpin

Example

julia> Outport{Int}(2)
 2-element Outport{Outpin{Int64}}:
  Outpin(eltype:Int64, isbound:false)
  Outpin(eltype:Int64, isbound:false)
 
 julia> Outport()
 1-element Outport{Outpin{Float64}}:
- Outpin(eltype:Float64, isbound:false)
source
Base.getindexMethod
getindex(port::AbstractPort, idx::Vararg{Int, N}) where N

Returns elements from port at index idx. Same as port[idx].

Example

julia> op = Outport(3)
+ Outpin(eltype:Float64, isbound:false)
source
Base.getindexMethod
getindex(port::AbstractPort, idx::Vararg{Int, N}) where N

Returns elements from port at index idx. Same as port[idx].

Example

julia> op = Outport(3)
 3-element Outport{Outpin{Float64}}:
  Outpin(eltype:Float64, isbound:false)
  Outpin(eltype:Float64, isbound:false)
@@ -221,7 +205,7 @@
 3-element Array{Outpin{Float64},1}:
  Outpin(eltype:Float64, isbound:false)
  Outpin(eltype:Float64, isbound:false)
- Outpin(eltype:Float64, isbound:false)
source
Base.put!Method
put!(outport::Outport, vals)

Puts vals to outport. Each item in vals is putted to the links of the outport.

Warning

The outport must be writable to be read. That is, there must be a runnable tasks bound to links of the outport that reads data from outport.

Example

julia> op, ip = Outport(), Inport() 
+ Outpin(eltype:Float64, isbound:false)
source
Base.put!Method
put!(outport::Outport, vals)

Puts vals to outport. Each item in vals is putted to the links of the outport.

Warning

The outport must be writable to be read. That is, there must be a runnable tasks bound to links of the outport that reads data from outport.

Example

julia> op, ip = Outport(), Inport() 
 (Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))
 
 julia> ls = connect!(op, ip)
@@ -241,7 +225,7 @@
 
 julia> put!(op, [NaN])
 1-element Array{Float64,1}:
- NaN
source
Base.setindex!Method
setindex!(port::AbstractPort, item, idx::Vararg{Int, N}) where N

Sets item to port at index idx. Same as port[idx] = item.

Example

julia> op = Outport(3)
+ NaN
source
Base.setindex!Method
setindex!(port::AbstractPort, item, idx::Vararg{Int, N}) where N

Sets item to port at index idx. Same as port[idx] = item.

Example

julia> op = Outport(3)
 3-element Outport{Outpin{Float64}}:
  Outpin(eltype:Float64, isbound:false)
  Outpin(eltype:Float64, isbound:false)
@@ -256,7 +240,7 @@
 julia> op[1:2] = [Outpin(), Outpin()]
 2-element Array{Outpin{Float64},1}:
  Outpin(eltype:Float64, isbound:false)
- Outpin(eltype:Float64, isbound:false)
source
Base.take!Method
take!(inport::Inport)

Takes an element from inport. Each link of the inport is a read and a vector containing the results is returned.

Warning

The inport must be readable to be read. That is, there must be a runnable tasks bound to links of the inport that writes data to inport.

Example

julia> op, ip = Outport(), Inport()
+ Outpin(eltype:Float64, isbound:false)
source
Base.take!Method
take!(inport::Inport)

Takes an element from inport. Each link of the inport is a read and a vector containing the results is returned.

Warning

The inport must be readable to be read. That is, there must be a runnable tasks bound to links of the inport that writes data to inport.

Example

julia> op, ip = Outport(), Inport()
 (Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))
 
 julia> ls = connect!(op, ip)
@@ -273,8 +257,4 @@
 
 julia> take!(ip)
 1-element Array{Float64,1}:
-<<<<<<< HEAD
- 2.0
source
Causal.similarMethod
similar(port, numpins::Int=length(outport)) where {P<:Outpin{T}} where {T}

Returns a new port that is similar to port with the same element type. The number of links in the new port is nlinks and data buffer length is ln.

source
-======= - 2.0
source
Jusdl.similarMethod
similar(port, numpins::Int=length(outport)) where {P<:Outpin{T}} where {T}

Returns a new port that is similar to port with the same element type. The number of links in the new port is nlinks and data buffer length is ln.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + 2.0source
Causal.similarMethod
similar(port, numpins::Int=length(outport)) where {P<:Outpin{T}} where {T}

Returns a new port that is similar to port with the same element type. The number of links in the new port is nlinks and data buffer length is ln.

source
diff --git a/docs/build/manual/models/model/index.html b/docs/build/manual/models/model/index.html index 1238c322..536934ec 100644 --- a/docs/build/manual/models/model/index.html +++ b/docs/build/manual/models/model/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Model · Causal

Model

Signal-Flow Approach in Modelling

Causal adopts signal-flow approach in systems modelling. In signal-flow approach, a Model consists of connected components. The components are data processing units and the behavior, i.e, the mathematical model, of the component determines how the data is processed. Connections connects the components each other and the data is transferred between components by means of connections. The data flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input bus.

Construction of Models

A Model consists of connected components. The components of are defined first and the Model consisting of these components can be constructed. Or, an empty model can be constructed.

Let us continue with some examples. We will construct very simple Model consisting of a SinewaveGenerator and a Writer. We construct an empty Model first, then we add nodes and branches as desired.

julia> using Causal # hide
-=======
-Model · Jusdl

Model

Signal-Flow Approach in Modelling

Jusdl adopts signal-flow approach in systems modelling. In signal-flow approach, a Model consists of connected components. The components are data processing units and the behavior, i.e, the mathematical model, of the component determines how the data is processed. Connections connects the components each other and the data is transferred between components by means of connections. The data flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input bus.

Construction of Models

A Model consists of connected components. The components of are defined first and the Model consisting of these components can be constructed. Or, an empty model can be constructed.

Let us continue with some examples. We will construct very simple Model consisting of a SinewaveGenerator and a Writer. We construct an empty Model first, then we add nodes and branches as desired.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Model · Causal

Model

Signal-Flow Approach in Modelling

Causal adopts signal-flow approach in systems modelling. In signal-flow approach, a Model consists of connected components. The components are data processing units and the behavior, i.e, the mathematical model, of the component determines how the data is processed. Connections connects the components each other and the data is transferred between components by means of connections. The data flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input bus.

Construction of Models

A Model consists of connected components. The components of are defined first and the Model consisting of these components can be constructed. Or, an empty model can be constructed.

Let us continue with some examples. We will construct very simple Model consisting of a SinewaveGenerator and a Writer. We construct an empty Model first, then we add nodes and branches as desired.

julia> using Causal # hide
 
 julia> model = Model()
 Model(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))
@@ -26,19 +22,11 @@
 Any[]
 
 julia> model.clock         # Model time reference
-<<<<<<< HEAD
-Clock(t:0.0, dt:0.01, tf:1.0, paused:false, isrunning:false)

The time reference is used to sample the continuous time signals flowing through the busses of the model and to rigger the components. The simulation is performed by triggering the components with the pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs and writes them to their outputs.

Simulation Stages

Inspection

The inspection stage is the first stage of the simulation process. In this stag,e the model is first inspected in terms of whether it is ready for simulation. This inspection is carried out to see whether the model has some inconsistencies such as unterminated busses or presence of algebraic loops. If the model has unterminated busses, the data that is supposed to flow those unterminated busses cannot flow through those busses and the simulation gets stuck. An algebraic is the subset of model components whose output depends directly on their inputs. In such a case, none of the components can produce outputs to break the loop which leads again the obstruction of simulation. Thus, to continue the simulation, the model must not contain any of those inconsistencies. The model inspection is done with inspect! function.

Initialization

If the inspection stage results positive, the initialization stage comes next. In this stage, the tasks required for the busses of the model to be both readable and writable are activated and bound the busses. To this end, a reader and writer task are activated and bound to both sides of each bus. To initialize the model, initialize! function is used.

When the model is initialized, the pairs of components and component tasks are recorded into the task manager of the model. During the rest of the simulation, task manager keeps track of the tasks. Any exception or error that is thrown during the run stage of the simulation can be observed by means of the task manager of the model.

Run

The run stage follows the initialization stage. The tasks activated in the initialization stage wait for the components to be triggered by the model time reference. During the run stage, time reference, that is the model clock, triggers the components by writing pulses that are generated in the intervals of the sampling period of the simulation to their trigger links. The job defined in a task is to read input dat a from the its input bus, to calculate its next state, if any, and output, and write its calculated output to its output bus. The run stage, starts at the initial time of the time reference and continues until the end time of the time reference. run! function is used to run the models,

Termination

After the run stage, the tasks opened in the initialization stage are closed and the simulation is terminated. terminate! function is used to terminate the model

Models are constructed to simulate! them. During the simulation, components of the Model process data and the data is transferred between the components via connection. Thus, to simulate the Models, the components must be connected. In our model, the writer is used to record the output of gen. Thus, the flows from gen to writer. Thus, we connect gen output to writer input.

Note

During the Model construction, the order of addition of nodes to the model is not important. The nodes can be given in any order.

Full API

Causal.BranchType
Branch(nodepair, indexpair, links)

Constructs a Branch connecting the first and second element of nodepair with links. indexpair determines the subindices by which the elements of nodepair are connected.

source
Causal.ModelType
Model(components::AbstractVector)

Constructs a Model whose with components components which are of type AbstractComponent.

Model()

Constructs a Model with empty components. After the construction, components can be added to Model.

Warning

Models are units that can be simulated. As the data flows through the branches i.e. input output busses of the components, its is important that the components must be connected to each other. See also: simulate!

source
Causal.NodeType
Node(component, idx, label)

Constructs a model Node with component. idx is the index and label is label of Node.

source
Causal.addnode!Method
addnode!(model, component; label=nothing)

Adds a node to model. Component is component and label is label the label of node. Returns added node.

Example

julia> model = Model()
+Clock(t:0.0, dt:0.01, tf:1.0, paused:false, isrunning:false)

The time reference is used to sample the continuous time signals flowing through the busses of the model and to rigger the components. The simulation is performed by triggering the components with the pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs and writes them to their outputs.

Simulation Stages

Inspection

The inspection stage is the first stage of the simulation process. In this stag,e the model is first inspected in terms of whether it is ready for simulation. This inspection is carried out to see whether the model has some inconsistencies such as unterminated busses or presence of algebraic loops. If the model has unterminated busses, the data that is supposed to flow those unterminated busses cannot flow through those busses and the simulation gets stuck. An algebraic is the subset of model components whose output depends directly on their inputs. In such a case, none of the components can produce outputs to break the loop which leads again the obstruction of simulation. Thus, to continue the simulation, the model must not contain any of those inconsistencies. The model inspection is done with inspect! function.

Initialization

If the inspection stage results positive, the initialization stage comes next. In this stage, the tasks required for the busses of the model to be both readable and writable are activated and bound the busses. To this end, a reader and writer task are activated and bound to both sides of each bus. To initialize the model, initialize! function is used.

When the model is initialized, the pairs of components and component tasks are recorded into the task manager of the model. During the rest of the simulation, task manager keeps track of the tasks. Any exception or error that is thrown during the run stage of the simulation can be observed by means of the task manager of the model.

Run

The run stage follows the initialization stage. The tasks activated in the initialization stage wait for the components to be triggered by the model time reference. During the run stage, time reference, that is the model clock, triggers the components by writing pulses that are generated in the intervals of the sampling period of the simulation to their trigger links. The job defined in a task is to read input dat a from the its input bus, to calculate its next state, if any, and output, and write its calculated output to its output bus. The run stage, starts at the initial time of the time reference and continues until the end time of the time reference. run! function is used to run the models,

Termination

After the run stage, the tasks opened in the initialization stage are closed and the simulation is terminated. terminate! function is used to terminate the model

Models are constructed to simulate! them. During the simulation, components of the Model process data and the data is transferred between the components via connection. Thus, to simulate the Models, the components must be connected. In our model, the writer is used to record the output of gen. Thus, the flows from gen to writer. Thus, we connect gen output to writer input.

Note

During the Model construction, the order of addition of nodes to the model is not important. The nodes can be given in any order.

Full API

Causal.BranchType
Branch(nodepair, indexpair, links)

Constructs a Branch connecting the first and second element of nodepair with links. indexpair determines the subindices by which the elements of nodepair are connected.

source
Causal.ModelType
Model(components::AbstractVector)

Constructs a Model whose with components components which are of type AbstractComponent.

Model()

Constructs a Model with empty components. After the construction, components can be added to Model.

Warning

Models are units that can be simulated. As the data flows through the branches i.e. input output busses of the components, its is important that the components must be connected to each other. See also: simulate!

source
Causal.NodeType
Node(component, idx, label)

Constructs a model Node with component. idx is the index and label is label of Node.

source
Causal.addnode!Method
addnode!(model, component; label=nothing)

Adds a node to model. Component is component and label is label the label of node. Returns added node.

Example

julia> model = Model()
 Model(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))
 
 julia> addnode!(model, SinewaveGenerator(), label=:gen)
-Node(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)
source
Causal.breakloop!Function
breakloop!(model, loop, breakpoint=length(loop))

Breaks the algebraic loop of model. The loop of the model is broken by inserting a Memory at the breakpoint of loop.

source
Causal.deletebranch!Method
deletebranch!(model::Model, branch::Branch)

Deletes branch from branched of model.

deletebranch!(model::Model, srcnode::Node, dstnode::Node)

Deletes branch between srcnode and dstnode of the model.

source
Causal.getnodeMethod
getnode(model, idx::Int)

Returns node of model whose index is idx.

getnode(model, label)

Returns node of model whose label is label.

Example

julia> model = Model()
-=======
-Clock(t:0.0, dt:0.01, tf:1.0, paused:false, isrunning:false)

The time reference is used to sample the continuous time signals flowing through the busses of the model and to rigger the components. The simulation is performed by triggering the components with the pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs and writes them to their outputs.

Simulation Stages

Inspection

The inspection stage is the first stage of the simulation process. In this stag,e the model is first inspected in terms of whether it is ready for simulation. This inspection is carried out to see whether the model has some inconsistencies such as unterminated busses or presence of algebraic loops. If the model has unterminated busses, the data that is supposed to flow those unterminated busses cannot flow through those busses and the simulation gets stuck. An algebraic is the subset of model components whose output depends directly on their inputs. In such a case, none of the components can produce outputs to break the loop which leads again the obstruction of simulation. Thus, to continue the simulation, the model must not contain any of those inconsistencies. The model inspection is done with inspect! function.

Initialization

If the inspection stage results positive, the initialization stage comes next. In this stage, the tasks required for the busses of the model to be both readable and writable are activated and bound the busses. To this end, a reader and writer task are activated and bound to both sides of each bus. To initialize the model, initialize! function is used.

When the model is initialized, the pairs of components and component tasks are recorded into the task manager of the model. During the rest of the simulation, task manager keeps track of the tasks. Any exception or error that is thrown during the run stage of the simulation can be observed by means of the task manager of the model.

Run

The run stage follows the initialization stage. The tasks activated in the initialization stage wait for the components to be triggered by the model time reference. During the run stage, time reference, that is the model clock, triggers the components by writing pulses that are generated in the intervals of the sampling period of the simulation to their trigger links. The job defined in a task is to read input dat a from the its input bus, to calculate its next state, if any, and output, and write its calculated output to its output bus. The run stage, starts at the initial time of the time reference and continues until the end time of the time reference. run! function is used to run the models,

Termination

After the run stage, the tasks opened in the initialization stage are closed and the simulation is terminated. terminate! function is used to terminate the model

Models are constructed to simulate! them. During the simulation, components of the Model process data and the data is transferred between the components via connection. Thus, to simulate the Models, the components must be connected. In our model, the writer is used to record the output of gen. Thus, the flows from gen to writer. Thus, we connect gen output to writer input.

Note

During the Model construction, the order of addition of nodes to the model is not important. The nodes can be given in any order.

Full API

Jusdl.BranchType
Branch(nodepair, indexpair, links)

Constructs a Branch connecting the first and second element of nodepair with links. indexpair determines the subindices by which the elements of nodepair are connected.

source
Jusdl.ModelType
Model(components::AbstractVector)

Constructs a Model whose with components components which are of type AbstractComponent.

Model()

Constructs a Model with empty components. After the construction, components can be added to Model.

Warning

Models are units that can be simulated. As the data flows through the branches i.e. input output busses of the components, its is important that the components must be connected to each other. See also: simulate!

source
Jusdl.NodeType
Node(component, idx, label)

Constructs a model Node with component. idx is the index and label is label of Node.

source
Jusdl.addnode!Method
addnode!(model, component; label=nothing)

Adds a node to model. Component is component and label is label the label of node. Returns added node.

Example

julia> model = Model()
-Model(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))
-
-julia> addnode!(model, SinewaveGenerator(), label=:gen)
-Node(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)
source
Jusdl.breakloop!Function
breakloop!(model, loop, breakpoint=length(loop))

Breaks the algebraic loop of model. The loop of the model is broken by inserting a Memory at the breakpoint of loop.

source
Jusdl.deletebranch!Method
deletebranch!(model::Model, branch::Branch)

Deletes branch from branched of model.

deletebranch!(model::Model, srcnode::Node, dstnode::Node)

Deletes branch between srcnode and dstnode of the model.

source
Jusdl.getloopsMethod
getloops(model)

Returns idx of nodes that constructs algrebraic loops.

source
Jusdl.getnodeMethod
getnode(model, idx::Int)

Returns node of model whose index is idx.

getnode(model, label)

Returns node of model whose label is label.

Example

julia> model = Model()
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Node(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)
source
Causal.breakloop!Function
breakloop!(model, loop, breakpoint=length(loop))

Breaks the algebraic loop of model. The loop of the model is broken by inserting a Memory at the breakpoint of loop.

source
Causal.deletebranch!Method
deletebranch!(model::Model, branch::Branch)

Deletes branch from branched of model.

deletebranch!(model::Model, srcnode::Node, dstnode::Node)

Deletes branch between srcnode and dstnode of the model.

source
Causal.getnodeMethod
getnode(model, idx::Int)

Returns node of model whose index is idx.

getnode(model, label)

Returns node of model whose label is label.

Example

julia> model = Model()
 Model(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))
 
 julia> addnode!(model, SinewaveGenerator(), label=:gen)
@@ -51,13 +39,8 @@
 Node(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)
 
 julia> getnode(model, 2)
-<<<<<<< HEAD
-Node(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)
source
Causal.initialize!Method
initialize!(model::Model)

Initializes model by launching component task for each of the component of model. The pairs component and component tasks are recordedin the task manager of the model. The model clock is set! and the files of Writer are openned.

source
Causal.inspect!Function
inspect!(model::Model)

Inspects the model. If model has some inconsistencies such as including algebraic loops or unterminated busses and error is thrown.

source
Causal.run!Function
run!(model::Model, withbar::Bool=true)

Runs the model by triggering the components of the model. This triggering is done by generating clock tick using the model clock model.clock. Triggering starts with initial time of model clock, goes on with a step size of the sampling period of the model clock, and finishes at the finishing time of the model clock. If withbar is true, a progress bar indicating the simulation status is displayed on the console.

Warning

The model must first be initialized to be run. See also: initialize!.

source
Causal.signalflowMethod
signalflow(model, args...; kwargs...)

Plots the signal flow of model. args and kwargs are passed into gplot function.

source
Causal.simulate!Method
simulate!(model::Model, t0::Real, dt::Real, tf::Real; kwargs...)

Simulates the model starting from the initial time t0 until the final time tf with the sampling interval of tf. For kwargs are

  • logtofile::Bool: If true, a log file is contructed logging each step of the simulation.
  • reportsim::Bool: If true, model components are written files after the simulation. When this file is read back, the model components can be consructed back with their status at the end of the simulation.
  • simdir::String: The path of the directory in which simulation file are recorded.
source
Causal.simulate!Method
simulate!(model::Model; simdir::String=tempdir(), simprefix::String="Simulation-", simname=string(uuid4()),
-    logtofile::Bool=false, loglevel::LogLevel=Logging.Info, reportsim::Bool=false, withbar::Bool=true)

Simulates model. simdir is the path of the directory into which simulation files are saved. simprefix is the prefix of the simulation name simname. If logtofile is true, a log file for the simulation is constructed. loglevel determines the logging level. If reportsim is true, model components are saved into files. If withbar is true, a progress bar indicating the simualation status is displayed on the console.

source
Causal.terminate!Method
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
Causal.troubleshootMethod
troubleshoot(model)

Prints the exceptions of the tasks that are failed during the simulation of model.

source
Causal.@defmodelMacro
@defmodel name ex

Construts a model. The expected syntax is.

    @defmodel mymodel begin 
-=======
-Node(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)
source
Jusdl.initialize!Method
initialize!(model::Model)

Initializes model by launching component task for each of the component of model. The pairs component and component tasks are recordedin the task manager of the model. The model clock is set! and the files of Writer are openned.

source
Jusdl.inspect!Function
inspect!(model::Model)

Inspects the model. If model has some inconsistencies such as including algebraic loops or unterminated busses and error is thrown.

source
Jusdl.run!Function
run!(model::Model, withbar::Bool=true)

Runs the model by triggering the components of the model. This triggering is done by generating clock tick using the model clock model.clock. Triggering starts with initial time of model clock, goes on with a step size of the sampling period of the model clock, and finishes at the finishing time of the model clock. If withbar is true, a progress bar indicating the simulation status is displayed on the console.

Warning

The model must first be initialized to be run. See also: initialize!.

source
Jusdl.signalflowMethod
signalflow(model, args...; kwargs...)

Plots the signal flow of model. args and kwargs are passed into gplot function.

source
Jusdl.simulate!Method
simulate!(model::Model, t0::Real, dt::Real, tf::Real; kwargs...)

Simulates the model starting from the initial time t0 until the final time tf with the sampling interval of tf. For kwargs are

  • logtofile::Bool: If true, a log file is contructed logging each step of the simulation.
  • reportsim::Bool: If true, model components are written files after the simulation. When this file is read back, the model components can be consructed back with their status at the end of the simulation.
  • simdir::String: The path of the directory in which simulation file are recorded.
source
Jusdl.simulate!Method
simulate!(model::Model; simdir::String=tempdir(), simprefix::String="Simulation-", simname=string(uuid4()),
-    logtofile::Bool=false, loglevel::LogLevel=Logging.Info, reportsim::Bool=false, withbar::Bool=true)

Simulates model. simdir is the path of the directory into which simulation files are saved. simprefix is the prefix of the simulation name simname. If logtofile is true, a log file for the simulation is constructed. loglevel determines the logging level. If reportsim is true, model components are saved into files. If withbar is true, a progress bar indicating the simualation status is displayed on the console.

source
Jusdl.terminate!Method
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
Jusdl.troubleshootMethod
troubleshoot(model)

Prints the exceptions of the tasks that are failed during the simulation of model.

source
Jusdl.@defmodelMacro
@defmodel name ex

Construts a model. The expected syntax is.

    @defmodel mymodel begin 
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Node(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)
source
Causal.initialize!Method
initialize!(model::Model)

Initializes model by launching component task for each of the component of model. The pairs component and component tasks are recordedin the task manager of the model. The model clock is set! and the files of Writer are openned.

source
Causal.inspect!Function
inspect!(model::Model)

Inspects the model. If model has some inconsistencies such as including algebraic loops or unterminated busses and error is thrown.

source
Causal.run!Function
run!(model::Model, withbar::Bool=true)

Runs the model by triggering the components of the model. This triggering is done by generating clock tick using the model clock model.clock. Triggering starts with initial time of model clock, goes on with a step size of the sampling period of the model clock, and finishes at the finishing time of the model clock. If withbar is true, a progress bar indicating the simulation status is displayed on the console.

Warning

The model must first be initialized to be run. See also: initialize!.

source
Causal.signalflowMethod
signalflow(model, args...; kwargs...)

Plots the signal flow of model. args and kwargs are passed into gplot function.

source
Causal.simulate!Method
simulate!(model::Model, t0::Real, dt::Real, tf::Real; kwargs...)

Simulates the model starting from the initial time t0 until the final time tf with the sampling interval of tf. For kwargs are

  • logtofile::Bool: If true, a log file is contructed logging each step of the simulation.
  • reportsim::Bool: If true, model components are written files after the simulation. When this file is read back, the model components can be consructed back with their status at the end of the simulation.
  • simdir::String: The path of the directory in which simulation file are recorded.
source
Causal.simulate!Method
simulate!(model::Model; simdir::String=tempdir(), simprefix::String="Simulation-", simname=string(uuid4()),
+    logtofile::Bool=false, loglevel::LogLevel=Logging.Info, reportsim::Bool=false, withbar::Bool=true)

Simulates model. simdir is the path of the directory into which simulation files are saved. simprefix is the prefix of the simulation name simname. If logtofile is true, a log file for the simulation is constructed. loglevel determines the logging level. If reportsim is true, model components are saved into files. If withbar is true, a progress bar indicating the simualation status is displayed on the console.

source
Causal.terminate!Method
terminate!(model::Model)

Terminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.

source
Causal.troubleshootMethod
troubleshoot(model)

Prints the exceptions of the tasks that are failed during the simulation of model.

source
Causal.@defmodelMacro
@defmodel name ex

Construts a model. The expected syntax is.

    @defmodel mymodel begin 
         @nodes begin 
             label1 = Component1()
             label2 = Component1()
@@ -68,8 +51,4 @@
             src2 => dst2 
                 ⋮
         end
-<<<<<<< HEAD
-    end

Here @nodes and @branches blocks adefine the nodes and branches of the model, respectively.

source
-======= - end

Here @nodes and @branches blocks adefine the nodes and branches of the model, respectively.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + end

Here @nodes and @branches blocks adefine the nodes and branches of the model, respectively.

source diff --git a/docs/build/manual/models/simulation/index.html b/docs/build/manual/models/simulation/index.html index 0ea2450e..0ba2e45b 100644 --- a/docs/build/manual/models/simulation/index.html +++ b/docs/build/manual/models/simulation/index.html @@ -1,8 +1,3 @@ -<<<<<<< HEAD -Simulation · Causal

Simulation

During the simulation of a model, a Simulation object is constructed. The field names of the Simulation object is

  • model::Model: The model for which the Simulation is constructed.
  • path::String: The path of the directory into which all simulation-related files (log, data files etc.) are saved.
  • logger::AbstractLogger: The logger of the simulation constructed to log each stage of the Simulation .
  • state::Symbol: The state of the Simulation. The state may be :running if the simulation is running, :halted is the simulation is terminated without being completed, :done if it is terminated.
  • retcode::Symbol: The return code of the simulation. The retcode may be :success if the simulation is completed without errors, :failed if the an error occurs during the simulation.

Full API

Causal.SimulationType
Simulation(model; simdir=tempdir(), simname=string(uuid4()), simprefix="Simulation-", logger=SimpleLogger())

Constructs a Simulation object for the simulation of model. The Simulation object is used to monitor the state of the simulation of the model. simdir is the path of the directory into which the simulation files(log, data files etc.) are recorded. simname is the name of the Simulation and simprefix is the prefix of the name of the Simulation. logger is used to log the simulation steps of the model. See also: Model, Logging

source
Causal.reportMethod
report(simulation::Simulation)

Records the state of the simulation by writing all its fields into a data file. All the fields of the simulation is written into file. When the file is read back, the simulation object is constructed back. The data file is written under the path of the simulation.

source
Causal.setloggerMethod
setlogger(path, name; setglobal::Bool=true)

Returns a logger. path is the path and name is the name of the file of the logger. If setglobal is true, the returned logger is a global logger.

Example

julia> logger = setlogger(tempdir(), "mylogger", setglobal=true)
-Base.CoreLogging.SimpleLogger(IOStream(<file /tmp/mylogger>), Info, Dict{Any,Int64}())
source
-======= -Simulation · Jusdl

Simulation

During the simulation of a model, a Simulation object is constructed. The field names of the Simulation object is

  • model::Model: The model for which the Simulation is constructed.
  • path::String: The path of the directory into which all simulation-related files (log, data files etc.) are saved.
  • logger::AbstractLogger: The logger of the simulation constructed to log each stage of the Simulation .
  • state::Symbol: The state of the Simulation. The state may be :running if the simulation is running, :halted is the simulation is terminated without being completed, :done if it is terminated.
  • retcode::Symbol: The return code of the simulation. The retcode may be :success if the simulation is completed without errors, :failed if the an error occurs during the simulation.

Full API

Jusdl.SimulationType
Simulation(model; simdir=tempdir(), simname=string(uuid4()), simprefix="Simulation-", logger=SimpleLogger())

Constructs a Simulation object for the simulation of model. The Simulation object is used to monitor the state of the simulation of the model. simdir is the path of the directory into which the simulation files(log, data files etc.) are recorded. simname is the name of the Simulation and simprefix is the prefix of the name of the Simulation. logger is used to log the simulation steps of the model. See also: Model, Logging

source
Jusdl.reportMethod
report(simulation::Simulation)

Records the state of the simulation by writing all its fields into a data file. All the fields of the simulation is written into file. When the file is read back, the simulation object is constructed back. The data file is written under the path of the simulation.

source
Jusdl.setloggerMethod
setlogger(path, name; setglobal::Bool=true)

Returns a logger. path is the path and name is the name of the file of the logger. If setglobal is true, the returned logger is a global logger.

Example

julia> logger = setlogger(tempdir(), "mylogger", setglobal=true)
-Base.CoreLogging.SimpleLogger(IOStream(<file /tmp/mylogger>), Info, Dict{Any,Int64}())
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Simulation · Causal

Simulation

During the simulation of a model, a Simulation object is constructed. The field names of the Simulation object is

  • model::Model: The model for which the Simulation is constructed.
  • path::String: The path of the directory into which all simulation-related files (log, data files etc.) are saved.
  • logger::AbstractLogger: The logger of the simulation constructed to log each stage of the Simulation .
  • state::Symbol: The state of the Simulation. The state may be :running if the simulation is running, :halted is the simulation is terminated without being completed, :done if it is terminated.
  • retcode::Symbol: The return code of the simulation. The retcode may be :success if the simulation is completed without errors, :failed if the an error occurs during the simulation.

Full API

Causal.SimulationType
Simulation(model; simdir=tempdir(), simname=string(uuid4()), simprefix="Simulation-", logger=SimpleLogger())

Constructs a Simulation object for the simulation of model. The Simulation object is used to monitor the state of the simulation of the model. simdir is the path of the directory into which the simulation files(log, data files etc.) are recorded. simname is the name of the Simulation and simprefix is the prefix of the name of the Simulation. logger is used to log the simulation steps of the model. See also: Model, Logging

source
Causal.reportMethod
report(simulation::Simulation)

Records the state of the simulation by writing all its fields into a data file. All the fields of the simulation is written into file. When the file is read back, the simulation object is constructed back. The data file is written under the path of the simulation.

source
Causal.setloggerMethod
setlogger(path, name; setglobal::Bool=true)

Returns a logger. path is the path and name is the name of the file of the logger. If setglobal is true, the returned logger is a global logger.

Example

julia> logger = setlogger(tempdir(), "mylogger", setglobal=true)
+Base.CoreLogging.SimpleLogger(IOStream(<file /tmp/mylogger>), Info, Dict{Any,Int64}())
source
diff --git a/docs/build/manual/models/taskmanager/index.html b/docs/build/manual/models/taskmanager/index.html index fbac4203..cc4dd1f2 100644 --- a/docs/build/manual/models/taskmanager/index.html +++ b/docs/build/manual/models/taskmanager/index.html @@ -1,6 +1,2 @@ -<<<<<<< HEAD -Task Manager · Causal

Task Manager

A TaskManager is actually the pairs of components and the tasks constructed corresponding to those components. In Causal, models are simulated by individually evolving the components. This individual evolution of components is performed by defining components individually and constructing tasks for each components. The jobs that are defined in these tasks are defined to make the components evolve by reading its time, input, compute its output. During this evolution, the tasks may fail because any inconsistency. Right after the failure of a task, its not possible for the component corresponding to the task to evolve any more. As the data flows through the components that connects the components, model simulation gets stuck. To keep track of the task launched for each component, a TaskManager is used. Before starting to simulate a model, a TaskManager is constructed for the model components. During the initialization of simulation, tasks corresponding to the components of the model is launched and the pair of component and component task is recorded in the TaskManager of the model. During the run stage of the simulation, TaskManager keeps track of the component tasks. In case any failure in components tasks, the cause of the failure can be investigated with TaskManager.

Full API

Causal.TaskManagerType
TaskManager(pairs)

Constructs a TaskManager with pairs. pairs is a dictionary whose keys are components and values are component tasks. Component tasks are constructed correponding to the components. A TaskManager is used to keep track of the component task launched corresponding to components.

TaskManager()

Constructs a TaskManager with empty pairs. ```

source
Causal.istaskrunningFunction
istaskrunning(task::Task)

Returns true is the state of task is runnable.

istaskrunning(task::Nothing)

Returns true

istaskrunning(comptask::ComponentTask)

Returns true if triggertask and outputtask of comptask is running.

source
-======= -Task Manager · Jusdl

Task Manager

A TaskManager is actually the pairs of components and the tasks constructed corresponding to those components. In Jusdl, models are simulated by individually evolving the components. This individual evolution of components is performed by defining components individually and constructing tasks for each components. The jobs that are defined in these tasks are defined to make the components evolve by reading its time, input, compute its output. During this evolution, the tasks may fail because any inconsistency. Right after the failure of a task, its not possible for the component corresponding to the task to evolve any more. As the data flows through the components that connects the components, model simulation gets stuck. To keep track of the task launched for each component, a TaskManager is used. Before starting to simulate a model, a TaskManager is constructed for the model components. During the initialization of simulation, tasks corresponding to the components of the model is launched and the pair of component and component task is recorded in the TaskManager of the model. During the run stage of the simulation, TaskManager keeps track of the component tasks. In case any failure in components tasks, the cause of the failure can be investigated with TaskManager.

Full API

Jusdl.TaskManagerType
TaskManager(pairs)

Constructs a TaskManager with pairs. pairs is a dictionary whose keys are components and values are component tasks. Component tasks are constructed correponding to the components. A TaskManager is used to keep track of the component task launched corresponding to components.

TaskManager()

Constructs a TaskManager with empty pairs. ```

source
Jusdl.istaskrunningFunction
istaskrunning(task::Task)

Returns true is the state of task is runnable.

istaskrunning(task::Nothing)

Returns true

istaskrunning(comptask::ComponentTask)

Returns true if triggertask and outputtask of comptask is running.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Task Manager · Causal

Task Manager

A TaskManager is actually the pairs of components and the tasks constructed corresponding to those components. In Causal, models are simulated by individually evolving the components. This individual evolution of components is performed by defining components individually and constructing tasks for each components. The jobs that are defined in these tasks are defined to make the components evolve by reading its time, input, compute its output. During this evolution, the tasks may fail because any inconsistency. Right after the failure of a task, its not possible for the component corresponding to the task to evolve any more. As the data flows through the components that connects the components, model simulation gets stuck. To keep track of the task launched for each component, a TaskManager is used. Before starting to simulate a model, a TaskManager is constructed for the model components. During the initialization of simulation, tasks corresponding to the components of the model is launched and the pair of component and component task is recorded in the TaskManager of the model. During the run stage of the simulation, TaskManager keeps track of the component tasks. In case any failure in components tasks, the cause of the failure can be investigated with TaskManager.

Full API

Causal.TaskManagerType
TaskManager(pairs)

Constructs a TaskManager with pairs. pairs is a dictionary whose keys are components and values are component tasks. Component tasks are constructed correponding to the components. A TaskManager is used to keep track of the component task launched corresponding to components.

TaskManager()

Constructs a TaskManager with empty pairs. ```

source
Causal.istaskrunningFunction
istaskrunning(task::Task)

Returns true is the state of task is runnable.

istaskrunning(task::Nothing)

Returns true

istaskrunning(comptask::ComponentTask)

Returns true if triggertask and outputtask of comptask is running.

source
diff --git a/docs/build/manual/plugins/plugins/index.html b/docs/build/manual/plugins/plugins/index.html index c12276bf..43f1e891 100644 --- a/docs/build/manual/plugins/plugins/index.html +++ b/docs/build/manual/plugins/plugins/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Plugins · Causal

Plugins

Plugins are extensions that are used to process online the data flowing through the connections of the model during the simulation. These tools are specialized tools that are used for specialized data processing. In addition to the plugins that are provided by Causal, it is also possible to write new plugins that focus on different specialized data processing. The fundamental importance of Plugins is that they make the online simulation data processing possible.

The Plugins are mostly used with Sinks. In Causal, the Sinks are used to sink simulation data flowing through the connections of the model. When a Sink is equipped with a proper Plugin according to the data processing desired, then the data flowing into the Sink is processed. For example, consider that a Writer is equipped with a Lyapunov plugin. During the simulation, data flowing into the Writer is processed to compute the maximum Lyapunov exponent, and these computed maximum Lyapunov exponents are recorded in the file of the Writer. Similarly, if a Printer is equipped with an Fft plugin, then Fast Fourier transform of the data flowing into the Printer is printed on the console.

Data processing via Plugins

Each Plugin must have a process function which does the data processing. The first argument of the process function is the Plugin and the second argument is the data to be processed. Here are some of the methods of process function

Defining New Plugins

New plugins can be defined in Causal and having they are defined properly they can work just expected. To define a new plugin, we must first define the plugin type

julia> using Causal # hide
-=======
-Plugins · Jusdl

Plugins

Plugins are extensions that are used to process online the data flowing through the connections of the model during the simulation. These tools are specialized tools that are used for specialized data processing. In addition to the plugins that are provided by Jusdl, it is also possible to write new plugins that focus on different specialized data processing. The fundamental importance of Plugins is that they make the online simulation data processing possible.

The Plugins are mostly used with Sinks. In Jusdl, the Sinks are used to sink simulation data flowing through the connections of the model. When a Sink is equipped with a proper Plugin according to the data processing desired, then the data flowing into the Sink is processed. For example, consider that a Writer is equipped with a Lyapunov plugin. During the simulation, data flowing into the Writer is processed to compute the maximum Lyapunov exponent, and these computed maximum Lyapunov exponents are recorded in the file of the Writer. Similarly, if a Printer is equipped with an Fft plugin, then Fast Fourier transform of the data flowing into the Printer is printed on the console.

Data processing via Plugins

Each Plugin must have a process function which does the data processing. The first argument of the process function is the Plugin and the second argument is the data to be processed. Here are some of the methods of process function

Defining New Plugins

New plugins can be defined in Jusdl and having they are defined properly they can work just expected. To define a new plugin, we must first define the plugin type

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Plugins · Causal

Plugins

Plugins are extensions that are used to process online the data flowing through the connections of the model during the simulation. These tools are specialized tools that are used for specialized data processing. In addition to the plugins that are provided by Causal, it is also possible to write new plugins that focus on different specialized data processing. The fundamental importance of Plugins is that they make the online simulation data processing possible.

The Plugins are mostly used with Sinks. In Causal, the Sinks are used to sink simulation data flowing through the connections of the model. When a Sink is equipped with a proper Plugin according to the data processing desired, then the data flowing into the Sink is processed. For example, consider that a Writer is equipped with a Lyapunov plugin. During the simulation, data flowing into the Writer is processed to compute the maximum Lyapunov exponent, and these computed maximum Lyapunov exponents are recorded in the file of the Writer. Similarly, if a Printer is equipped with an Fft plugin, then Fast Fourier transform of the data flowing into the Printer is printed on the console.

Data processing via Plugins

Each Plugin must have a process function which does the data processing. The first argument of the process function is the Plugin and the second argument is the data to be processed. Here are some of the methods of process function

Defining New Plugins

New plugins can be defined in Causal and having they are defined properly they can work just expected. To define a new plugin, we must first define the plugin type

julia> using Causal # hide
 
 julia> struct NewPlugin <: AbstractPlugin
            # Parameters of NewPlugin
@@ -12,8 +8,4 @@
 julia> function process(plg::NewPlugin, x)
            # Define the process according to plg
        end
-<<<<<<< HEAD
-process (generic function with 1 method)

At this point, NewPlugin is ready to be used.

-======= -process (generic function with 1 method)

At this point, NewPlugin is ready to be used.

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +process (generic function with 1 method)

At this point, NewPlugin is ready to be used.

diff --git a/docs/build/manual/utilities/buffers/index.html b/docs/build/manual/utilities/buffers/index.html index 2ff6800f..03016a6c 100644 --- a/docs/build/manual/utilities/buffers/index.html +++ b/docs/build/manual/utilities/buffers/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Buffer · Causal

Buffer

A Buffer is a used to buffer the data flowing the connections of a model. Data can be read from and written into a buffer. The mode of the buffer determines the way to read from and write into the buffers.

Buffer Modes

BufferMode determines the way the data is read from and written into a Buffer. Basically, there are four buffer modes: Normal, Cyclic, Fifo and Lifo. Normal, Fifo and Lifo are subtypes of LinearMode and Cyclic is a subtype of CyclicMode.

Buffer Constructors

The Buffer construction is very similar to the construction of arrays in Julia. Just specify the mode, element type and length of the buffer. Here are some examples:

julia> using Causal # hide
-=======
-Buffer · Jusdl

Buffer

A Buffer is a used to buffer the data flowing the connections of a model. Data can be read from and written into a buffer. The mode of the buffer determines the way to read from and write into the buffers.

Buffer Modes

BufferMode determines the way the data is read from and written into a Buffer. Basically, there are four buffer modes: Normal, Cyclic, Fifo and Lifo. Normal, Fifo and Lifo are subtypes of LinearMode and Cyclic is a subtype of CyclicMode.

Buffer Constructors

The Buffer construction is very similar to the construction of arrays in Julia. Just specify the mode, element type and length of the buffer. Here are some examples:

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Buffer · Causal

Buffer

A Buffer is a used to buffer the data flowing the connections of a model. Data can be read from and written into a buffer. The mode of the buffer determines the way to read from and write into the buffers.

Buffer Modes

BufferMode determines the way the data is read from and written into a Buffer. Basically, there are four buffer modes: Normal, Cyclic, Fifo and Lifo. Normal, Fifo and Lifo are subtypes of LinearMode and Cyclic is a subtype of CyclicMode.

Buffer Constructors

The Buffer construction is very similar to the construction of arrays in Julia. Just specify the mode, element type and length of the buffer. Here are some examples:

julia> using Causal # hide
 
 julia> Buffer{Fifo}(2, 5)
 2×5 Buffer{Fifo,Float64,2}
@@ -15,11 +11,7 @@
 2×5 Buffer{Lifo,Bool,2}
 
 julia> Buffer(5)
-<<<<<<< HEAD
 5-element Buffer{Cyclic,Float64,1}

Writing Data into Buffers

Writing data into a Buffer is done with write! function. Recall that when the buffer is full, no more data can be written into the buffer if the buffer mode is of type LinearMode.


-=======
-5-element Buffer{Cyclic,Float64,1}

Writing Data into Buffers

Writing data into a Buffer is done with write! function. Recall that when the buffer is full, no more data can be written into the buffer if the buffer mode is of type LinearMode.


->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 julia> normalbuf = Buffer{Normal}(3)
 3-element Buffer{Normal,Float64,1}
 
@@ -48,11 +40,7 @@
 3.0
 
 julia> write!(cyclicbuf, 4.)
-<<<<<<< HEAD
 4.0

Reading Data from Buffers

Reading data from a Buffer is done with read function.

julia> using Causal # hide
-=======
-4.0

Reading Data from Buffers

Reading data from a Buffer is done with read function.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 
 julia> nbuf, cbuf, fbuf, lbuf = Buffer{Normal}(5), Buffer{Cyclic}(5), Buffer{Lifo}(5), Buffer{Fifo}(5)
 (Buffer(mode:Normal, eltype:Float64, size:(5,), index:1, state:empty), Buffer(mode:Cyclic, eltype:Float64, size:(5,), index:1, state:empty), Buffer(mode:Lifo, eltype:Float64, size:(5,), index:1, state:empty), Buffer(mode:Fifo, eltype:Float64, size:(5,), index:1, state:empty))
@@ -125,22 +113,14 @@
 3-element Array{Int64,1}:
  7
  8
-<<<<<<< HEAD
  9

Full API

Causal.BufferType
Buffer{M}(dtype::Type{T}, sz::Int...) where {M, T}

Constructs a Buffer of size sz with element type of T. M is the mode of the Buffer that determines how data is to read from and written into the Buffer. There exists for different buffer modes:

The default mode for Buffer is Cyclic and default element type is Float64.

Buffer{M}(sz::Int...) where {M, T}

Constructs a Buffer of size sz and with element type of T and mode M.

Buffer(dtype::Type{T}, sz::Int...) where T

Constructs a Buffer of size sz and element type T. The mode of buffer is Cyclic.

Buffer(sz::Int...)

Constructs a Buffer of size sz with mode Cyclic and element type of Float64.

Buffer{M}(data::AbstractVecOrMat{T}) where {M, T<:Real}

Constructs a Buffer with data.

Example

julia> buf = Buffer(5)
-=======
- 9

Full API

Jusdl.BufferType
Buffer{M}(dtype::Type{T}, sz::Int...) where {M, T}

Constructs a Buffer of size sz with element type of T. M is the mode of the Buffer that determines how data is to read from and written into the Buffer. There exists for different buffer modes:

The default mode for Buffer is Cyclic and default element type is Float64.

Buffer{M}(sz::Int...) where {M, T}

Constructs a Buffer of size sz and with element type of T and mode M.

Buffer(dtype::Type{T}, sz::Int...) where T

Constructs a Buffer of size sz and element type T. The mode of buffer is Cyclic.

Buffer(sz::Int...)

Constructs a Buffer of size sz with mode Cyclic and element type of Float64.

Buffer{M}(data::AbstractVecOrMat{T}) where {M, T<:Real}

Constructs a Buffer with data.

Example

julia> buf = Buffer(5)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 5-element Buffer{Cyclic,Float64,1}
 
 julia> buf = Buffer{Fifo}(2, 5)
 2×5 Buffer{Fifo,Float64,2}
 
 julia> buf = Buffer{Lifo}(collect(reshape(1:8, 2, 4)))
-<<<<<<< HEAD
-2×4 Buffer{Lifo,Int64,2}
source
Causal.BufferModeType
BufferMode

Abstract type for buffer mode. Subtypes of BufferMode is CyclicMode and LinearMode.

source
Causal.CyclicType
Cyclic <: CyclicMode

Cyclic buffer mode. The data is written to buffer until the buffer is full. When the buffer is full, new data is written by overwriting the data available in the buffer starting from the beginning of the buffer. When the buffer is read, the element written last is returned and the returned element is not deleted from the buffer.

source
Causal.FifoType
Fifo <: LinearMode

Fifo (First-in-last-out) buffer mode. This type of buffer is a first-in-first-out buffer. The data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the first element written into the buffer is returned. The returned element is deleted from the buffer.

source
Causal.LifoType
Lifo <: LinearMode

Lifo (Last-in-first-out) buffer mode. This type of buffer is a last-in-first-out buffer. Data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the last element written into buffer is returned. The returned element is deleted from the buffer.

source
Causal.NormalType
Normal <: LinearMode

LinearMode buffer mode. The data is written to buffer until the buffer is full. When it is full, no more data is written to the buffer. When read, the data written last is returned and the returned data is not deleted from the internal container of the buffer.

source
Base.getindexMethod
getindex(buf::Buffer, idx::Vararg{Int, N})

Returns an element from buf at index idx. Same as buf[idx]

Example

julia> buf = Buffer(2, 5);  # Construct a buffer.
-=======
-2×4 Buffer{Lifo,Int64,2}
source
Jusdl.BufferModeType
BufferMode

Abstract type for buffer mode. Subtypes of BufferMode is CyclicMode and LinearMode.

source
Jusdl.CyclicType
Cyclic <: CyclicMode

Cyclic buffer mode. The data is written to buffer until the buffer is full. When the buffer is full, new data is written by overwriting the data available in the buffer starting from the beginning of the buffer. When the buffer is read, the element written last is returned and the returned element is not deleted from the buffer.

source
Jusdl.FifoType
Fifo <: LinearMode

Fifo (First-in-last-out) buffer mode. This type of buffer is a first-in-first-out buffer. The data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the first element written into the buffer is returned. The returned element is deleted from the buffer.

source
Jusdl.LifoType
Lifo <: LinearMode

Lifo (Last-in-first-out) buffer mode. This type of buffer is a last-in-first-out buffer. Data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the last element written into buffer is returned. The returned element is deleted from the buffer.

source
Jusdl.NormalType
Normal <: LinearMode

LinearMode buffer mode. The data is written to buffer until the buffer is full. When it is full, no more data is written to the buffer. When read, the data written last is returned and the returned data is not deleted from the internal container of the buffer.

source
Base.getindexMethod
getindex(buf::Buffer, idx::Vararg{Int, N})

Returns an element from buf at index idx. Same as buf[idx]

Example

julia> buf = Buffer(2, 5);  # Construct a buffer.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+2×4 Buffer{Lifo,Int64,2}
source
Causal.BufferModeType
BufferMode

Abstract type for buffer mode. Subtypes of BufferMode is CyclicMode and LinearMode.

source
Causal.CyclicType
Cyclic <: CyclicMode

Cyclic buffer mode. The data is written to buffer until the buffer is full. When the buffer is full, new data is written by overwriting the data available in the buffer starting from the beginning of the buffer. When the buffer is read, the element written last is returned and the returned element is not deleted from the buffer.

source
Causal.FifoType
Fifo <: LinearMode

Fifo (First-in-last-out) buffer mode. This type of buffer is a first-in-first-out buffer. The data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the first element written into the buffer is returned. The returned element is deleted from the buffer.

source
Causal.LifoType
Lifo <: LinearMode

Lifo (Last-in-first-out) buffer mode. This type of buffer is a last-in-first-out buffer. Data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the last element written into buffer is returned. The returned element is deleted from the buffer.

source
Causal.NormalType
Normal <: LinearMode

LinearMode buffer mode. The data is written to buffer until the buffer is full. When it is full, no more data is written to the buffer. When read, the data written last is returned and the returned data is not deleted from the internal container of the buffer.

source
Base.getindexMethod
getindex(buf::Buffer, idx::Vararg{Int, N})

Returns an element from buf at index idx. Same as buf[idx]

Example

julia> buf = Buffer(2, 5);  # Construct a buffer.
 
 julia> write!(buf, reshape(2 : 2 : 20, 2, 5))  # Write data into buffer.
 
@@ -156,11 +136,7 @@
 julia> buf[:, 2]
 2-element Array{Float64,1}:
  14.0
-<<<<<<< HEAD
- 16.0
source
Base.readMethod
read(buf::Buffer)

Reads an element from buf. Reading is performed according to the mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(3)
-=======
- 16.0
source
Base.readMethod
read(buf::Buffer)

Reads an element from buf. Reading is performed according to the mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(3)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ 16.0
source
Base.readMethod
read(buf::Buffer)

Reads an element from buf. Reading is performed according to the mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(3)
 3-element Buffer{Cyclic,Float64,1}
 
 julia> write!(buf, [2, 4, 6])
@@ -182,7 +158,7 @@
        end
 (read(buf), buf.internals) = (2.0, [[6.0, 4.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])
 (read(buf), buf.internals) = (4.0, [[6.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])
-(read(buf), buf.internals) = (6.0, [[0.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])
source
Base.setindex!Method
setindex!(buf::Buffer, val, idx)

Sets val to buf at index idx. Same as buf[idx] = val.

Example

julia> buf = Buffer(2, 5);
+(read(buf), buf.internals) = (6.0, [[0.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])
source
Base.setindex!Method
setindex!(buf::Buffer, val, idx)

Sets val to buf at index idx. Same as buf[idx] = val.

Example

julia> buf = Buffer(2, 5);
 
 julia> buf[1] = 1
 1
@@ -198,11 +174,7 @@
 julia> buf.internals
 2-element Array{Array{Float64,2},1}:
  [1.0 1.0 … 0.0 0.0; 0.0 1.0 … 0.0 10.0]
-<<<<<<< HEAD
- [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
source
Causal.contentMethod
content(buf, [flip=true])

Returns the current data of buf. If flip is true, the data to be returned is flipped. See also snapshot

Example

julia> buf = Buffer(5);
-=======
- [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
source
Jusdl.contentMethod
content(buf, [flip=true])

Returns the current data of buf. If flip is true, the data to be returned is flipped. See also snapshot

Example

julia> buf = Buffer(5);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
source
Causal.contentMethod
content(buf, [flip=true])

Returns the current data of buf. If flip is true, the data to be returned is flipped. See also snapshot

Example

julia> buf = Buffer(5);
 
 julia> write!(buf, 1:3)
 
@@ -219,11 +191,7 @@
 julia> content(buf)
 2×5 Array{Float64,2}:
  1.0  3.0  5.0  7.0   9.0
-<<<<<<< HEAD
- 2.0  4.0  6.0  8.0  10.0
source
Causal.datalengthMethod
datalength(buf::Buffer)

Returns the maximum number of data that can be hold in buf.

Example

julia> buf = Buffer(5);
-=======
- 2.0  4.0  6.0  8.0  10.0
source
Jusdl.datalengthMethod
datalength(buf::Buffer)

Returns the maximum number of data that can be hold in buf.

Example

julia> buf = Buffer(5);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ 2.0  4.0  6.0  8.0  10.0
source
Causal.datalengthMethod
datalength(buf::Buffer)

Returns the maximum number of data that can be hold in buf.

Example

julia> buf = Buffer(5);
 
 julia> datalength(buf)
 5
@@ -231,11 +199,7 @@
 julia> buf2 = Buffer(2, 10);
 
 julia> datalength(buf2)
-<<<<<<< HEAD
-10
source
Causal.inbufMethod
inbuf(buf::Buffer)

Returns the element of internals of buf that is used to input data to buf. See also [outbuf][@ref)

source
Causal.isfullMethod
isfull(buf::Buffer)

Returns true if the index of buf is equal to the length of buf.

source
Causal.ishitMethod
ishit(buf::Buffer)

Returns true when buf index is an integer multiple of datalength of buf.

Example

julia> buf = Buffer(3);
-=======
-10
source
Jusdl.inbufMethod
inbuf(buf::Buffer)

Returns the element of internals of buf that is used to input data to buf. See also [outbuf][@ref)

source
Jusdl.isfullMethod
isfull(buf::Buffer)

Returns true if the index of buf is equal to the length of buf.

source
Jusdl.ishitMethod
ishit(buf::Buffer)

Returns true when buf index is an integer multiple of datalength of buf.

Example

julia> buf = Buffer(3);
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+10
source
Causal.inbufMethod
inbuf(buf::Buffer)

Returns the element of internals of buf that is used to input data to buf. See also [outbuf][@ref)

source
Causal.isfullMethod
isfull(buf::Buffer)

Returns true if the index of buf is equal to the length of buf.

source
Causal.ishitMethod
ishit(buf::Buffer)

Returns true when buf index is an integer multiple of datalength of buf.

Example

julia> buf = Buffer(3);
 
 julia> for val in 1 : 7
        write!(buf, val)
@@ -247,11 +211,7 @@
 ishit(buf) = false
 ishit(buf) = false
 ishit(buf) = true
-<<<<<<< HEAD
-ishit(buf) = false
source
Causal.outbufMethod
outbuf(buf::Buffer)

Returns the element of intervals of buf that is used to take data out of buf. See also: inbuf

source
Causal.write!Method
write!(buf::Buffer{M, <:Real, 1}, val::Real) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 2}, val::AbstractVector{<:Real}) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 1}, vals::AbstractVector{<:Real}) where {M}

Writes each element of vals into buf.

write!(buf::Buffer{M, <:Real, 2}, vals::AbstractMatrix{<:Real}) where {M}

Writes each column of vals into buf.

Warning

Buffer mode determines how data is written into buffers. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(5)
-=======
-ishit(buf) = false
source
Jusdl.outbufMethod
outbuf(buf::Buffer)

Returns the element of intervals of buf that is used to take data out of buf. See also: inbuf

source
Jusdl.write!Method
write!(buf::Buffer{M, <:Real, 1}, val::Real) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 2}, val::AbstractVector{<:Real}) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 1}, vals::AbstractVector{<:Real}) where {M}

Writes each element of vals into buf.

write!(buf::Buffer{M, <:Real, 2}, vals::AbstractMatrix{<:Real}) where {M}

Writes each column of vals into buf.

Warning

Buffer mode determines how data is written into buffers. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(5)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+ishit(buf) = false
source
Causal.outbufMethod
outbuf(buf::Buffer)

Returns the element of intervals of buf that is used to take data out of buf. See also: inbuf

source
Causal.write!Method
write!(buf::Buffer{M, <:Real, 1}, val::Real) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 2}, val::AbstractVector{<:Real}) where {M}

Writes val into buf.

write!(buf::Buffer{M, <:Real, 1}, vals::AbstractVector{<:Real}) where {M}

Writes each element of vals into buf.

write!(buf::Buffer{M, <:Real, 2}, vals::AbstractMatrix{<:Real}) where {M}

Writes each column of vals into buf.

Warning

Buffer mode determines how data is written into buffers. See also: Normal, Cyclic, Lifo, Fifo for buffer modes.

Example

julia> buf = Buffer(5)
 5-element Buffer{Cyclic,Float64,1}
 
 julia> write!(buf, 1.)
@@ -277,8 +237,4 @@
 julia> buf.internals
 2-element Array{Array{Float64,2},1}:
  [3.0 2.0 … 0.0 0.0; 3.0 2.0 … 0.0 0.0]
-<<<<<<< HEAD
- [2.0 1.0 … 0.0 0.0; 2.0 1.0 … 0.0 0.0]
source
-======= - [2.0 1.0 … 0.0 0.0; 2.0 1.0 … 0.0 0.0]
source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + [2.0 1.0 … 0.0 0.0; 2.0 1.0 … 0.0 0.0]source diff --git a/docs/build/manual/utilities/callback/index.html b/docs/build/manual/utilities/callback/index.html index 4f8f8d6a..c0576b87 100644 --- a/docs/build/manual/utilities/callback/index.html +++ b/docs/build/manual/utilities/callback/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Callback · Causal

Callback

Callbacks are used to monitor the existence of a specific event and if that specific event occurs, some other special jobs are invoked. Callbacks are intended to provide additional monitoring capability to any user-defined composite types. As such, Callbacks are generally fields of user defined composite types. When a Callback is called, if the Callback is enabled and its condition function returns true, then its action function is invoked.

A Simple Example

Let's define a test object first that has a field named x of type Int and named callback of type Callback.

julia> mutable struct TestObject
-=======
-Callback · Jusdl

Callback

Callbacks are used to monitor the existence of a specific event and if that specific event occurs, some other special jobs are invoked. Callbacks are intended to provide additional monitoring capability to any user-defined composite types. As such, Callbacks are generally fields of user defined composite types. When a Callback is called, if the Callback is enabled and its condition function returns true, then its action function is invoked.

A Simple Example

Let's define a test object first that has a field named x of type Int and named callback of type Callback.

julia> mutable struct TestObject
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Callback · Causal

Callback

Callbacks are used to monitor the existence of a specific event and if that specific event occurs, some other special jobs are invoked. Callbacks are intended to provide additional monitoring capability to any user-defined composite types. As such, Callbacks are generally fields of user defined composite types. When a Callback is called, if the Callback is enabled and its condition function returns true, then its action function is invoked.

A Simple Example

Let's define a test object first that has a field named x of type Int and named callback of type Callback.

julia> mutable struct TestObject
        x::Int
        callback::Callback
        end

To construct an instance of TestObject, we need to construct a Callback. For that purpose, the condition and action function must be defined. For this example, condition checks whether the x field is positive, and action prints a simple message saying that the x field is positive.

julia> condition(testobject) = testobject.x > 0 
@@ -13,11 +9,7 @@
 action (generic function with 1 method)

Now a test object can be constructed

julia> testobject = TestObject(-1, Callback(condition, action))  
 TestObject(-1, Callback{typeof(condition),typeof(action)}(condition, action, true, "dac6f9eb-6daa-4622-a8fa-623f0f88780c"))

If the callback is called, no action is performed since the condition function returns false. Note the argument sent to the callback. The instance of the TestObject to which the callback is bound.

julia> testobject.callback(testobject) 

Now mutate the test object so that condition returns true.

julia> testobject.x = 3   
 3

Now, if the callback is called, since the condition returns true and the callback is enabled, the action is invoked.

julia> testobject.callback(testobject) 
-<<<<<<< HEAD
 testobject.x is greater than zero

Full API

Causal.CallbackType
Callback(condition, action)

Constructs a Callback from condition and action. The condition and action must be a single-argument function. The condition returns true if the condition it checks occurs, otherwise, it returns false. action performs the specific action for which the Callback is constructed. A Callback can be called by passing its single argument which is mostly bound to the Callback.

Example

julia> struct Object  # Define a dummy type.
-=======
-testobject.x is greater than zero

Full API

Jusdl.CallbackType
Callback(condition, action)

Constructs a Callback from condition and action. The condition and action must be a single-argument function. The condition returns true if the condition it checks occurs, otherwise, it returns false. action performs the specific action for which the Callback is constructed. A Callback can be called by passing its single argument which is mostly bound to the Callback.

Example

julia> struct Object  # Define a dummy type.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
        x::Int 
        clb::Callback 
        end
@@ -43,8 +35,4 @@
 julia> obj.x = -1
 -1
 
-<<<<<<< HEAD
-julia> applycallbacks(obj)
source
Causal.isenabledMethod
isenabled(clb::Callback)

Returns true if clb is enabled. Otherwise, returns false.

source
-======= -julia> applycallbacks(obj)
source
Jusdl.isenabledMethod
isenabled(clb::Callback)

Returns true if clb is enabled. Otherwise, returns false.

source
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +julia> applycallbacks(obj)source
Causal.isenabledMethod
isenabled(clb::Callback)

Returns true if clb is enabled. Otherwise, returns false.

source
diff --git a/docs/build/modeling_and_simulation/modeling/index.html b/docs/build/modeling_and_simulation/modeling/index.html index 8d7e9ed1..38f5a7f3 100644 --- a/docs/build/modeling_and_simulation/modeling/index.html +++ b/docs/build/modeling_and_simulation/modeling/index.html @@ -1,17 +1,9 @@ -<<<<<<< HEAD -Modeling · Causal

Modeling

Causal adopts signal-flow approach in modeling systems. Briefly, in the signal-flow approach a model consists of components and connections. The simulation of the model is performed in a clocked simulation environment. That is, the model is not simulated in one shot by solving a huge mathematical equation, but instead is simulated by evolving the components individually and in parallel in different sampling intervals.

The components interact with each other through the connections that are bound to their port. The components are data processing units, and it is the behavior of the component that determines how the data is processed. The component behavior is defined by the mathematical equations obtained as a result of the physical laws that the physical quantities used in the modeling of the component must comply. Depending upon the nature of the system and the modeling, these equations may change, i.e. they may or may not contain derivative terms, or they may contain the continuous time or discrete time variable, etc. The data-flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input port.

Model simulation is performed by evolving the components individually. To make the components have a common time base, a common clock is used. The clock generates pulses at simulation sampling intervals. These pulses are used to trigger the components during the run stage of the simulation. Each component that is triggered reads its input data from its input port, calculates its output, and writes its output to its output port.

+Modeling · Causal

Modeling

Causal adopts signal-flow approach in modeling systems. Briefly, in the signal-flow approach a model consists of components and connections. The simulation of the model is performed in a clocked simulation environment. That is, the model is not simulated in one shot by solving a huge mathematical equation, but instead is simulated by evolving the components individually and in parallel in different sampling intervals.

The components interact with each other through the connections that are bound to their port. The components are data processing units, and it is the behavior of the component that determines how the data is processed. The component behavior is defined by the mathematical equations obtained as a result of the physical laws that the physical quantities used in the modeling of the component must comply. Depending upon the nature of the system and the modeling, these equations may change, i.e. they may or may not contain derivative terms, or they may contain the continuous time or discrete time variable, etc. The data-flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input port.

Model simulation is performed by evolving the components individually. To make the components have a common time base, a common clock is used. The clock generates pulses at simulation sampling intervals. These pulses are used to trigger the components during the run stage of the simulation. Each component that is triggered reads its input data from its input port, calculates its output, and writes its output to its output port.

model

Components

The component types in Causal are shown in the figure below together with output and state equations. The components can be grouped as sources, sinks, and systems.

The sources are components that generate signals as functions of time. Having been triggered, a source computes its output according to its output function and writes it to its output port. The sources do not have input ports as their outputs depend only on time.

The sinks are data processing units. Their primary objective is to process the data flowing through the connections of the model online. Having been triggered, a sink reads its input data and processes them, i.e. data can be visualized by being plotted on a graphical user interface, can be observed by being printed on the console, can be stored on data files. The data processing capability of the sinks can be enriched by integrating new plugins that can be developed using the standard Julia library or various available Julia packages. For example, invariants, spectral properties, or statistical information can be derived from the data, parameter estimation can be performed or various signal processing techniques can be applied to the data. Causal has been designed to be flexible enough to allow one to enlarge the scope of its available plugins by integrating newly-defined ones.

model

As the output of a static system depends on input and time, a static system is defined by an output equation. Having been triggered, a static system reads its input data, calculates its output, and writes it to its output port. In dynamical systems, however, system behavior is characterized by states and output of a dynamical system depends on input, previous state and time. Therefore, a dynamical system is defined by a state equation and an output equation. When triggered, a dynamical system reads its input, updates its state according to its state equation, calculates its output according to its output equation, and writes its output to its output port. Causal is capable of simulating the dynamical systems with state equations in the form of the ordinary differential equation(ODE), differential-algebraic equation(DAE), random ordinary differential equation(RODE), stochastic differential equation(SDE), delay differential equation(DDE) or discrete difference equation. Most of the available simulation environments allow the simulation of systems represented by ordinary differential equations or differential-algebraic equations. Therefore, analyzes such as noise analysis, delay analysis or random change of system parameters cannot be performed in these simulation environments. On the contrary, Causal makes it possible for all these analyses to be performed owing to its ability to solve such a wide range of state equations.

Ports and Connections

A port is actually a bunch of pins to which the connections are bound. There are two types of pins: an output pin that transfers data from the inside of the component to its outside, and an input pin that transfers data from the outside of component to its inside. Hence, there are two types of ports: an output port that consists of output pins and input port that consists of input pins.

The data transferred to a port is transferred to its connection(or connections as an output port may drive multiple connections). The data transfer through the connections is performed over the links of the connections. The links are built on top Julia channels.The data written to(read from) a link is written to(read from) the its channel. Active Julia tasks that are bound to channels must exist for data to flow over these channels. Julia tasks are control flow features that allow calculations to be flexibly suspended and maintained without directly communicating the task scheduler of the operating system. Communication and data exchange between the tasks are carried out through Julia channels to which they are bound.

-======= -Modeling · Jusdl

Modeling

Jusdl adopts signal-flow approach in modeling systems. Briefly, in the signal-flow approach a model consists of components and connections. The simulation of the model is performed in a clocked simulation environment. That is, the model is not simulated in one shot by solving a huge mathematical equation, but instead is simulated by evolving the components individually and in parallel in different sampling intervals.

The components interact with each other through the connections that are bound to their port. The components are data processing units, and it is the behavior of the component that determines how the data is processed. The component behavior is defined by the mathematical equations obtained as a result of the physical laws that the physical quantities used in the modeling of the component must comply. Depending upon the nature of the system and the modeling, these equations may change, i.e. they may or may not contain derivative terms, or they may contain the continuous time or discrete time variable, etc. The data-flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input port.

Model simulation is performed by evolving the components individually. To make the components have a common time base, a common clock is used. The clock generates pulses at simulation sampling intervals. These pulses are used to trigger the components during the run stage of the simulation. Each component that is triggered reads its input data from its input port, calculates its output, and writes its output to its output port.

- model -

Components

The component types in Jusdl are shown in the figure below together with output and state equations. The components can be grouped as sources, sinks, and systems.

The sources are components that generate signals as functions of time. Having been triggered, a source computes its output according to its output function and writes it to its output port. The sources do not have input ports as their outputs depend only on time.

The sinks are data processing units. Their primary objective is to process the data flowing through the connections of the model online. Having been triggered, a sink reads its input data and processes them, i.e. data can be visualized by being plotted on a graphical user interface, can be observed by being printed on the console, can be stored on data files. The data processing capability of the sinks can be enriched by integrating new plugins that can be developed using the standard Julia library or various available Julia packages. For example, invariants, spectral properties, or statistical information can be derived from the data, parameter estimation can be performed or various signal processing techniques can be applied to the data. Jusdl has been designed to be flexible enough to allow one to enlarge the scope of its available plugins by integrating newly-defined ones.

- model -

As the output of a static system depends on input and time, a static system is defined by an output equation. Having been triggered, a static system reads its input data, calculates its output, and writes it to its output port. In dynamical systems, however, system behavior is characterized by states and output of a dynamical system depends on input, previous state and time. Therefore, a dynamical system is defined by a state equation and an output equation. When triggered, a dynamical system reads its input, updates its state according to its state equation, calculates its output according to its output equation, and writes its output to its output port. Jusdl is capable of simulating the dynamical systems with state equations in the form of the ordinary differential equation(ODE), differential-algebraic equation(DAE), random ordinary differential equation(RODE), stochastic differential equation(SDE), delay differential equation(DDE) or discrete difference equation. Most of the available simulation environments allow the simulation of systems represented by ordinary differential equations or differential-algebraic equations. Therefore, analyzes such as noise analysis, delay analysis or random change of system parameters cannot be performed in these simulation environments. On the contrary, Jusdl makes it possible for all these analyses to be performed owing to its ability to solve such a wide range of state equations.

Ports and Connections

A port is actually a bunch of pins to which the connections are bound. There are two types of pins: an output pin that transfers data from the inside of the component to its outside, and an input pin that transfers data from the outside of component to its inside. Hence, there are two types of ports: an output port that consists of output pins and input port that consists of input pins.

The data transferred to a port is transferred to its connection(or connections as an output port may drive multiple connections). The data transfer through the connections is performed over the links of the connections. The links are built on top Julia channels.The data written to(read from) a link is written to(read from) the its channel. Active Julia tasks that are bound to channels must exist for data to flow over these channels. Julia tasks are control flow features that allow calculations to be flexibly suspended and maintained without directly communicating the task scheduler of the operating system. Communication and data exchange between the tasks are carried out through Julia channels to which they are bound.

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 \n\n\n\n
\n
\n \"reader_task\"\n
\n
\n \"writer_task\"\n
\n
\n \"reader_writer_task\"\n
\n
\n","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"In the figure above is shown symbolically the tasks that must be bound to the channel to make a channel readable, writable and both readable and writable. The putter and the taker task is the task that writes data to and reads data from the channel, respectively. To be able to read data from one side of the channel, an active putter task must be bound to the channel at the other side of the channel, and the channel is called a readable channel. Similarly, to be able to write data to one side of the channel, an active taker task must be bound to the channel on the other side, and the channel is called a writable channel. If both active putter and taker tasks are bound to either side of the channel, then the data can both be read from and written to the channel, and the channel is called both readable and writable channel. The data-flow through the channel is only achieved if the channel is both readable and writable channels. The data read from a readable channel is the data written to the channel by the putter task of the channel. If data has not been written yet to the channel by the putter task of the channel during a reading process, then reading does not occur and the putter task is waited to put data to the channel. Similarly, if the data on the channel has not been read yet from the channel by the taker task during a writing process, then the taker task is waited to take data from the channel. ","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"In the modeling approach adopted, the components reading data from a connection are driven by other components writing data to the connection. Therefore, all of the connections of the model must be both readable and writable connections so that data can flow the connections. This means that all the connections of the model must be connected to a component from both ends. Otherwise, the simulation gets stuck and does not end during a reading process from a channel that is not connected to a component. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#ODESystem","page":"ODESystem","title":"ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Basic-Operation-of-ODESystem","page":"ODESystem","title":"Basic Operation of ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When an ODESystem is triggered, it reads its current time from its trigger link, reads its input, solves its differential equation and computes its output. Let us observe the basic operation of ODESystems with a simple example. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"We first construct an ODESystem. Since an ODESystem is represented by its state equation and output equation, we need to define those equations.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"using Causal # hide \nsfunc(dx,x,u,t) = (dx .= -0.5x)\nofunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us construct the system ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds = ODESystem(righthandside=sfunc, readout=ofunc, state=[1.], input=Inport(1), output=Outport(1))","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that ds is a single input single output ODESystem with an initial state of [1.] and initial time 0.. To drive, i.e. trigger ds, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"oport, iport, trg, hnd = Outport(1), Inport(1), Outpin(), Inpin{Bool}()\nconnect!(oport, ds.input) \nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When launched, ds is ready to driven. ds is driven from its trigger link. Note that the trigger link of ds is writable. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds.trigger.link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us drive ds to the time of t of 1 second.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When driven, ds reads current time of t from its trigger link, reads its input value from its input, solves its differential equation and computes its output values and writes its output. So, for the step to be continued, an input values must be written. Note that the input of ds is writable,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds.input[1].link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us write some value. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(oport, [5.])","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"At this point, ds completed its step and put true to its handshake link to signal that its step is succeeded.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"hnd.link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"To complete the step and be ready for another step, we need to approve the step by reading its handshake. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"At this point, ds can be driven further. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"for t in 2. : 10.\n put!(trg, t)\n put!(oport, [t * 10])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that all the output value of ds is written to its outputbus,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When we launched ds, we constructed a task and the task is still running.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"To terminate the task safely, we need to terminate ds safely.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Now, the state of the task is done. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"So, it is not possible to drive ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Mutation-in-State-Function-in-ODESystem","page":"ODESystem","title":"Mutation in State Function in ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Consider a system with the following ODE","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"beginarrayl\n dotx = f(x u t) \n y = g(x u t) \nendarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"where x in R^d y in R^m u in R^p. To construct and ODESystem, The signature of the state function statefunc must be of the form ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"function statefunc(dx, x, u, t)\n dx .= ... # Update dx\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that statefunc does not construct dx but updates dx and does not return anything. This is for performance reasons. On the contrary, the signature of the output function outputfunc must be of the form,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"function outputfunc(x, u, t)\n y = ... # Compute y\n return y\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note the output value y is computed and returned from outputfunc. y is not updated but generated in the outputfunc.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Full-API","page":"ODESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"@def_ode_system \nODESystem \nContinuousLinearSystem \nLorenzSystem \nForcedLorenzSystem \nChenSystem \nForcedChenSystem \nChuaSystem \nForcedChuaSystem \nRosslerSystem \nForcedRosslerSystem \nVanderpolSystem \nForcedVanderpolSystem\nIntegrator ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.@def_ode_system","page":"ODESystem","title":"Causal.@def_ode_system","text":"@def_ode_system ex\n\nwhere ex is the expression to define to define a new AbstractODESystem component type. The usage is as follows:\n\n@def_ode_system mutable struct MyODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractODESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandeside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \nend\n\nHere, MyODESystem has N parameters. MyODESystem is represented by the righthandside and readout function. state, input and output is the state, input port and output port of MyODESystem.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew ODE system must be a subtype of AbstractODESystem to function properly. \n\nwarning: Warning\nNew ODE system must be mutable type.\n\nExample\n\njulia> @def_ode_system mutable struct MyODESystem{RH, RO, IP, OP} <: AbstractODESystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n state::Vector{Float64} = [1.]\n input::IP = Inport(1) \n output::OP = Outport(1) \n end\n\njulia> ds = MyODESystem();\n\njulia> ds.input \n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ODESystem","page":"ODESystem","title":"Causal.ODESystem","text":"ODESystem(;righthandside, readout, state, input, output)\n\nConstructs a generic ODE system.\n\nExample\n\njulia> ds = ODESystem(righthandside=(dx,x,u,t)->(dx.=-x), readout=(x,u,t)->x, state=[1.],input=nothing, output=Outport(1));\n\njulia> ds.state\n1-element Array{Float64,1}:\n 1.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ContinuousLinearSystem","page":"ODESystem","title":"Causal.ContinuousLinearSystem","text":"ContinuousLinearSystem(input, output, modelargs=(), solverargs=(); \n A=fill(-1, 1, 1), B=fill(0, 1, 1), C=fill(1, 1, 1), D=fill(0, 1, 1), state=rand(size(A,1)), t=0., \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ContinuousLinearSystem 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.\n\nThe ContinuousLinearSystem is represented by the following state and output equations.\n\nbeginarrayl\n dotx = A x + B u 025cm\n y = C x + D u \nendarray\n\nwhere x is state. solver is used to solve the above differential equation.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.LorenzSystem","page":"ODESystem","title":"Causal.LorenzSystem","text":"LorenzSystem(input, output, modelargs=(), solverargs=(); \n sigma=10, beta=8/3, rho=28, gamma=1, outputfunc=allstates, state=rand(3), t=0.,\n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a LorenzSystem with input and output. sigma, beta, rho and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of LorenzSystem is \n\nbeginarrayl\n dotx_1 = gamma (sigma (x_2 - x_1)) 025cm\n dotx_2 = gamma (x_1 (rho - x_3) - x_2) 025cm\n dotx_3 = gamma (x_1 x_2 - beta x_3) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (sigma (x_2 - x_1)) + sum_j = 1^3 alpha_1j u_j 025cm\n dotx_2 = gamma (x_1 (rho - x_3) - x_2) + sum_j = 1^3 alpha_2j u_j 025cm\n dotx_3 = gamma (x_1 x_2 - beta x_3) + sum_j = 1^3 alpha_3j u_j \nendarray\n\nwhere A = alpha_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ForcedLorenzSystem","page":"ODESystem","title":"Causal.ForcedLorenzSystem","text":"ForcedLorenzSystem()\n\nConstructs a LorenzSystem that is driven by its inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ChenSystem","page":"ODESystem","title":"Causal.ChenSystem","text":"ChenSystem(input, output, modelargs=(), solverargs=(); \n a=35, b=3, c=28, gamma=1, outputfunc=allstates, state=rand(3), t=0.,\n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ChenSystem with input and output. a, b, c and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of ChenSystem is \n\nbeginarrayl\n dotx_1 = gamma (a (x_2 - x_1)) 025cm\n dotx_2 = gamma ((c - a) x_1 + c x_2 + x_1 x_3) 025cm\n dotx_3 = gamma (x_1 x_2 - b x_3) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (a (x_2 - x_1)) + sum_j = 1^3 alpha_1j u_j 025cm\n dotx_2 = gamma ((c - a) x_1 + c x_2 + x_1 x_3) + sum_j = 1^3 alpha_2j u_j 025cm\n dotx_3 = gamma (x_1 x_2 - b x_3) + sum_j = 1^3 alpha_3j u_j \nendarray\n\nwhere A = alpha_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ForcedChenSystem","page":"ODESystem","title":"Causal.ForcedChenSystem","text":"ForcedChenSystem()\n\nConstructs Chen system driven by its inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ChuaSystem","page":"ODESystem","title":"Causal.ChuaSystem","text":"ChuaSystem(input, output, modelargs=(), solverargs=(); \n diode=PiecewiseLinearDiode(), alpha=15.6, beta=28., gamma=1., outputfunc=allstates, state=rand(3), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ChuaSystem with input and output. diode, alpha, beta and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of ChuaSystem is \n\nbeginarrayl\n dotx_1 = gamma (alpha (x_2 - x_1 - h(x_1))) 025cm\n dotx_2 = gamma (x_1 - x_2 + x_3 ) 025cm\n dotx_3 = gamma (-beta x_2) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (alpha (x_2 - x_1 - h(x_1))) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (x_1 - x_2 + x_3 ) + sum_j = 1^3 theta_2j u_j 025cm\n dotx_3 = gamma (-beta x_2) + sum_j = 1^3 theta_3j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ForcedChuaSystem","page":"ODESystem","title":"Causal.ForcedChuaSystem","text":"ForcedChuaSystem()\n\nConstructs a Chua system with inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.RosslerSystem","page":"ODESystem","title":"Causal.RosslerSystem","text":"RosslerSystem(input, output, modelargs=(), solverargs=(); \n a=0.38, b=0.3, c=4.82, gamma=1., outputfunc=allstates, state=rand(3), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a RosllerSystem with input and output. a, b, c and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of RosslerSystem is \n\nbeginarrayl\n dotx_1 = gamma (-x_2 - x_3) 025cm\n dotx_2 = gamma (x_1 + a x_2) 025cm\n dotx_3 = gamma (b + x_3 (x_1 - c))\nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (-x_2 - x_3) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (x_1 + a x_2 ) + sum_j = 1^3 theta_2j u_j 025cm\n dotx_3 = gamma (b + x_3 (x_1 - c)) + sum_j = 1^3 theta_3j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ForcedRosslerSystem","page":"ODESystem","title":"Causal.ForcedRosslerSystem","text":"ForcedRosslerSystem()\n\nConstructs a Rossler system driven by its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.VanderpolSystem","page":"ODESystem","title":"Causal.VanderpolSystem","text":"VanderpolSystem(input, output, modelargs=(), solverargs=(); \n mu=5., gamma=1., outputfunc=allstates, state=rand(2), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a VanderpolSystem with input and output. mu and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of VanderpolSystem is \n\nbeginarrayl\n dotx_1 = gamma (x_2) 025cm\n dotx_2 = gamma (mu (x_1^2 - 1) x_2 - x_1 )\nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (x_2) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (mu (x_1^2 - 1) x_2 - x_1) + sum_j = 1^3 theta_2j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.ForcedVanderpolSystem","page":"ODESystem","title":"Causal.ForcedVanderpolSystem","text":"ForcedVanderpolSystem()\n\nConstructs a Vanderpol system driven by its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Causal.Integrator","page":"ODESystem","title":"Causal.Integrator","text":"Integrator(state=zeros(0), t=0., modelargs=(), solverargs=(); \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple(), numtaps=numtaps, callbacks=nothing, \n name=Symbol())\n\nConstructs an integrator whose input output relation is given by \n\nu(t) = ki * int_0^t u(tau) dtau\n\nwhere u(t) is the input, y(t) is the output and ki is the integration constant.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/printer/#Printer","page":"Printer","title":"Printer","text":"","category":"section"},{"location":"manual/components/sinks/printer/#Basic-Operation-of-Printers","page":"Printer","title":"Basic Operation of Printers","text":"","category":"section"},{"location":"manual/components/sinks/printer/","page":"Printer","title":"Printer","text":"See Basic Operation of Writers since the operation of Writer and that of Printer is very similar.","category":"page"},{"location":"manual/components/sinks/printer/#Full-API","page":"Printer","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/printer/","page":"Printer","title":"Printer","text":"Printer \nprint(printer::Printer, td, xd) \nopen(printer::Printer) \nclose(printer::Printer) ","category":"page"},{"location":"manual/components/sinks/printer/#Causal.Printer","page":"Printer","title":"Causal.Printer","text":"Printer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol()) where T Constructs a Printer with input bus input. buflen is the length of its internal buflen. plugin is data proccessing tool.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/printer/#Base.print-Tuple{Printer,Any,Any}","page":"Printer","title":"Base.print","text":"print(printer::Printer, td, xd)\n\nPrints xd corresponding to xd to the console.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/printer/#Base.open-Tuple{Printer}","page":"Printer","title":"Base.open","text":"open(printer::Printer)\n\nDoes nothing. Just a common interface function ot AbstractSink interface.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/printer/#Base.close-Tuple{Printer}","page":"Printer","title":"Base.close","text":"close(printer::Printer)\n\nDoes nothing. Just a common interface function ot AbstractSink interface.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#DDESystem","page":"DDESystem","title":"DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Construction-of-DDESystem","page":"DDESystem","title":"Construction of DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"A DDESystem is represented by the following state equation","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" dotx = f(x h u t) quad t geq t_0","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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 ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" x(t) = h(t) quad t leq t_0","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"and by the output equation","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" y = g(x u t) ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"where y is the value of the output. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"As an example, consider a system with the state equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" beginarrayl\n dotx = -x(t - tau) quad t geq 0 \n x(t) = 1 -tau leq t leq 0 \n endarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"First, we define the history function histfunc,","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"using Causal # hide\nconst out = zeros(1)\nhistfunc(out, u, t) = (out .= 1.);","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that histfunc mutates a vector out. This mutation is for performance reasons. Next the state function can be defined","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"function statefunc(dx, x, h, u, t)\n h(out, u, t - tau) # Update out vector\n dx[1] = out[1] + x[1]\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"and let us take all the state variables as outputs. Thus, the output function is ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"outputfunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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, ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"tau = 1\nconslags = [tau]","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"At this point, we are ready to construct the system. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"ds = DDESystem(righthandside=statefunc, history=histfunc, readout=outputfunc, state=[1.], input=nothing, output=Outport(), constlags=conslags, depslags=nothing)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Basic-Operation-of-DDESystem","page":"DDESystem","title":"Basic Operation of DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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,","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"iport, trg, hnd = Inport(), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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).","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"We can continue to drive ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"When launched, we constructed a task whose state is running which implies that ds can be driven. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"As long as the state of the task is running, ds can be driven. To terminate task safely, we need to terminate the ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"put!(trg, NaN)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that the state of task is done which implies that ds is not drivable any more. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that the output values of ds is written to its output bus. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Full-API","page":"DDESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"@def_dde_system \nDDESystem \nDelayFeedbackSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Causal.@def_dde_system","page":"DDESystem","title":"Causal.@def_dde_system","text":"@def_dde_system ex\n\nwhere ex is the expression to define to define a new AbstractDDESystem component type. The usage is as follows:\n\n@def_dde_system mutable struct MyDDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDDESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n constlags::CL = constlags_default # mandatory field\n depslags::DL = depslags_default # mandatory field\n righthandside::RH = righthandside_function # mandatory field\n history::HST = history_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_defauult # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MyDDESystem has N parameters. MyDDESystem is represented by the righthandside and readout function. state, input and output is the state, input port and output port of MyDDESystem.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew DDE system must be a subtype of AbstractDDESystem to function properly.\n\nExample\n\njulia> _delay_feedback_system_cache = zeros(1)\n1-element Array{Float64,1}:\n 0.0\n\njulia> _delay_feedback_system_tau = 1.\n1.0\n\njulia> _delay_feedback_system_constlags = [1.]\n1-element Array{Float64,1}:\n 1.0\n\njulia> _delay_feedback_system_history(cache, u, t) = (cache .= 1.)\n_delay_feedback_system_history (generic function with 1 method)\n\njulia> function _delay_feedback_system_rhs(dx, x, h, u, t, \n cache=_delay_feedback_system_cache, τ=_delay_feedback_system_tau)\n h(cache, u, t - τ) # Update cache \n dx[1] = cache[1] + x[1]\n end\n_delay_feedback_system_rhs (generic function with 3 methods)\n\njulia> @def_dde_system mutable struct MyDDESystem{RH, HST, RO, IP, OP} <: AbstractDDESystem\n constlags::Vector{Float64} = _delay_feedback_system_constlags\n depslags::Nothing = nothing\n righthandside::RH = _delay_feedback_system_rhs\n history::HST = _delay_feedback_system_history\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(1)\n input::IP = nothing \n output::OP = Outport(1)\n end\n\njulia> ds = MyDDESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Causal.DDESystem","page":"DDESystem","title":"Causal.DDESystem","text":"DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)\n\nConstruct a generic DDE system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Causal.DelayFeedbackSystem","page":"DDESystem","title":"Causal.DelayFeedbackSystem","text":"DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)\n\nConstructs DelayFeedbackSystem\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#SDESystem","page":"SDESystem","title":"SDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Construction-of-SDESystems","page":"SDESystem","title":"Construction of SDESystems","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"A SDESystem is represented by the state function ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" dx = f(x u t) dt + h(x u t)dW ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"where t is the time, x in R^n is the value of state, u in R^p is the value of the input. W is the Wiener process of the system. The output function is defined by ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" y = g(x u t)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"where y is the value of output at time t. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"As an example consider a system with the following stochastic differential equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" beginarrayl\n dx = -x dt - x dW\n endarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"and the following output equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"y = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The state function statefunc and the output function outputfunc is defined as follows.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"using Causal # hide \nf(dx, x, u, t) = (dx[1] = -x[1])\nh(dx, x, u, t) = (dx[1] = -x[1])","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The state function statefunc is the tuple of drift and diffusion functions","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"statefunc = (f, h)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The output function outputfunc is defined as,","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"g(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that the in drift function f and diffusion function g, the vector dx is mutated while in the output function g no mutation is done, but the output value is generated instead.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"From the definition of drift function f and the diffusion function g, it is seen that the system does not have any input, that is, the input of the system is nothing. Since all the state variables are taken as outputs, the system needs an output bus of length 1. Thus, ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"input = nothing \noutput = Outport(1)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"At this point, we are ready to construct the system ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"ds = SDESystem(righthandside=statefunc, readout=g, state=[1.], input=input, output=output)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Basic-Operation-of-SDESystems","page":"SDESystem","title":"Basic Operation of SDESystems","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The basic operation of a SDESystem is the same as those of other dynamical systems. When triggered from its trigger link, a SDESystem reads its time t from its trigger link, reads its input value from its input, solves its state equation, which is a stochastic differential equation, computes its output and writes its computed output to its output bus. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"In this section, we continue with the system ds constructed in the previous section. To make ds drivable, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"iport, trg, hnd = Inport(1), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"When launched, ds can be driven. For this, either of the syntax put!(ds.trigger, t) or drive(ds, t) can be used. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"After this command, ds reads its time t from its trigger link, solves its state function and computes its output. The calculated output value is written to the buffer of output. To signal that, the step is takes with success, ds writes true to its handshake link. To further drive ds, this handshake link must be read. For this either of the syntax, take!(ds.handshake) or approve!(ds) can be used","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"hnd.link\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"At this point, we can further drive ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that during the evolution, the output of ds is written into the buffers of output bus.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"warning: Warning\nThe values of the output is written into buffers if the output of the systems is not nothing.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"When we launched ds, we constructed a task whose state is running which implies that the ds can be drivable. As long as this task is running, ds can be drivable. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"warning: Warning\nThe state of the task is different from running in case an exception is thrown. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"To terminate the task securely, we need to terminate ds securely. To do that, can use terminate!(ds).","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that the task is terminated without a hassle. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Full-API","page":"SDESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"@def_sde_system \nSDESystem \nNoisyLorenzSystem \nForcedNoisyLorenzSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Causal.@def_sde_system","page":"SDESystem","title":"Causal.@def_sde_system","text":"@def_sde_system ex\n\nwhere ex is the expression to define to define a new AbstractSDESystem component type. The usage is as follows:\n\n@def_sde_system mutable struct MySDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractSDESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n drift::DR = drift_function # mandatory field\n diffusion::DF = diffusion_function # mandatory field\n readout::RO = readout_functtion # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MySDESystem has N parameters. MySDESystem is represented by the drift, diffusion and readout function. state, input and output is the initial state, input port and output port of MySDESystem.\n\nwarning: Warning\ndrift must have the signature function drift((dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx\nendand diffusion must have the signature function diffusion((dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx\nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew SDE system must be a subtype of AbstractSDESystem to function properly.\n\nExample\n\njulia> @def_sde_system mutable struct MySDESystem{DR, DF, RO, IP, OP} <: AbstractSDESystem\n η::Float64 = 1.\n drift::DR = (dx, x, u, t) -> (dx .= x)\n diffusion::DF = (dx, x, u, t, η=η) -> (dx .= η)\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(2) \n input::IP = nothing \n output::OP = Outport(2)\n end\n\njulia> ds = MySDESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Causal.SDESystem","page":"SDESystem","title":"Causal.SDESystem","text":"SDESystem(; drift, diffusion, readout, state, input, output)\n\nConstructs a SDE system. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Causal.NoisyLorenzSystem","page":"SDESystem","title":"Causal.NoisyLorenzSystem","text":"NoisyLorenzSystem()\n\nConstructs a noisy Lorenz system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Causal.ForcedNoisyLorenzSystem","page":"SDESystem","title":"Causal.ForcedNoisyLorenzSystem","text":"NoisyLorenzSystem()\n\nConstructs a noisy Lorenz system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/sinks/#Sinks","page":"Sinks","title":"Sinks","text":"","category":"section"},{"location":"manual/components/sinks/sinks/","page":"Sinks","title":"Sinks","text":"Sinks are used to simulation data flowing through the connections of the model. The data processing is done online during the simulation. Sink type is a subtype of AbstractSink. An AbstractSink is also a subtype of AbstractComponent (see Components), so an AbstractSink instance has a trigger link to be triggered and a handshake link to signal that evolution is succeeded. In addition, an AbstractSink has an input buffer inbuf whose mode is Cyclic. When an AbstractSink instance is triggered through its trigger link, it basically reads its incoming data and writes to its input buffer inbuf. When its input buffer inbuf is full, the data in inbuf is processed according to the type of AbstractSink. Causal provides three concrete subtypes of AbstractSink which are Writer, Printer and Scope. As the operation of an AbstractSink just depends on incoming data, an AbstractSink does not have an output.","category":"page"},{"location":"manual/components/sinks/sinks/#Full-API","page":"Sinks","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/sinks/","page":"Sinks","title":"Sinks","text":"@def_sink","category":"page"},{"location":"manual/components/sinks/sinks/#Causal.@def_sink","page":"Sinks","title":"Causal.@def_sink","text":"@def_sink ex\n\nwhere ex is the expression to define to define a new AbstractSink component type. The usage is as follows:\n\n@def_sink struct MySink{T1,T2,T3,...,TN, A} <: AbstractSink\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n action::A = action_function # mandatory field\nend\n\nHere, MySink has N parameters and action function\n\nwarning: Warning\naction function must have a method action(sink::MySink, t, u) where t is the time data and u is the data flowing into the sink.\n\nwarning: Warning\nNew static system must be a subtype of AbstractSink to function properly.\n\nExample\n\njulia> @def_sink struct MySink{A} <: AbstractSink \n action::A = actionfunc\n end\n\njulia> actionfunc(sink::MySink, t, u) = println(t, u)\nactionfunc (generic function with 1 method)\n\njulia> sink = MySink();\n\njulia> sink.action(sink, ones(2), ones(2) * 2)\n[1.0, 1.0][2.0, 2.0]\n\n\n\n\n\n","category":"macro"},{"location":"manual/connections/link/#Links","page":"Links","title":"Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Links are built on top of Channels of Julia. They are used as communication primitives for Tasks of Julia. A Link basically includes a Channel and a Buffer. The mode of the buffer is Cyclic.(see Buffer Modes for information on buffer modes). Every item sent through a Link is sent through the channel of the Link and written to the Buffer so that all the data flowing through a Link is recorded.","category":"page"},{"location":"manual/connections/link/#Construction-of-Links","page":"Links","title":"Construction of Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The construction of a Link is very simple: just specify its buffer length and element type.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Causal # hide \nLink{Bool}(5)\nLink{Int}(10)\nLink(5) \nLink()","category":"page"},{"location":"manual/connections/link/#Data-Flow-through-Links","page":"Links","title":"Data Flow through Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The data can be read from and written into Links if active tasks are bound to them. Links can be thought of like a pipe. In order to write data to a Link from one of its ends, a task that reads written data from the other end must be bounded to the Link. Similarly, in order to read data from one of the Link from one of its end, a task that writes the read data must be bound to the Link. Reading from and writing to Link is carried out with take! and put! functions. For more clarity, let us see some examples. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Let us first construct a Link,","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Causal # hide\nl = Link(5)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l is a Link with a buffer length of 5 and element type of Float64. Not that the l is open, but it is not ready for data reading or writing. To write data, we must bound a task that reads the written data.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"function reader(link::Link) # Define job.\n while true\n val = take!(link)\n val === NaN && break # Poison-pill the tasks to terminate safely.\n end\nend\nt = @async reader(l)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The reader is defined such that the data written from one end of l is read until the data is NaN. Now, we have runnable a task t. This means the l is ready for data writing. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"put!(l, 1.)\nput!(l, 2.)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Note that the data flown through the l is written to its buffer. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l.buffer","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"To terminate the task, we must write NaN to l.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"put!(l, NaN) # Terminate the task \nt # Show that the `t` is terminated.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Whenever the bound task to the l is runnable, the data can be written to l. That is, the data length that can be written to l is not limited by the buffer length of l. But, beware that the buffer of Links is Cyclic. That means, when the buffer is full, its data is overwritten.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l = Link(5)\nt = @async reader(l)\nfor item in 1. : 10.\n put!(l, item)\n @show outbuf(l.buffer)\nend","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The case is very similar to read data from l. Again, a runnable task is bound the l ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Causal # hide\nl = Link(5)\nfunction writer(link::Link, vals)\n for val in vals\n put!(link, val)\n end\nend\nt = @async writer(l, 1.:5.)\nbind(l, t)\ntake!(l)\ntake!(l)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"It is possible to read data from l until t is active. To read all the data at once, collect can be used. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"t \ncollect(l)\nt # Show that `t` is terminated.","category":"page"},{"location":"manual/connections/link/#Full-API","page":"Links","title":"Full API","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Modules = [Causal]\nPages = [\"link.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/link/#Causal.Link","page":"Links","title":"Causal.Link","text":"Link{T}(ln::Int=64) where {T}\n\nConstructs a Link with element type T and buffer length ln. The buffer element type is T and mode is Cyclic.\n\nLink(ln::Int=64)\n\nConstructs a Link with element type Float64 and buffer length ln. The buffer element type is Float64 and mode is Cyclic.\n\nExample\n\njulia> l = Link{Int}(5)\nLink(state:open, eltype:Int64, isreadable:false, iswritable:false)\n\njulia> l = Link{Bool}()\nLink(state:open, eltype:Bool, isreadable:false, iswritable:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/link/#Base.bind-Tuple{Link,Task}","page":"Links","title":"Base.bind","text":"bind(link::Link, task::Task)\n\nBinds task to link. When task is done link is closed.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.close-Tuple{Link}","page":"Links","title":"Base.close","text":"close(link)\n\nCloses link. All the task bound the link is also terminated safely. When closed, it is not possible to take and put element from the link. See also: take!(link::Link), put!(link::Link, val) ```\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.collect-Tuple{Link}","page":"Links","title":"Base.collect","text":"collect(link::Link)\n\nCollects all the available data on the link.\n\nwarning: Warning\nTo collect all available data from link, a task must be bounded to it.\n\nExample\n\njulia> l = Link(); # Construct a link.\n\njulia> t = @async for item in 1 : 5 # Construct a task\n put!(l, item)\n end;\n\njulia> bind(l, t); # Bind it to the link.\n\njulia> take!(l) # Take element from link.\n1.0\n\njulia> take!(l) # Take again ...\n2.0\n\njulia> collect(l) # Collect remaining data.\n3-element Array{Float64,1}:\n 3.0\n 4.0\n 5.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.eltype-Union{Tuple{Link{T}}, Tuple{T}} where T","page":"Links","title":"Base.eltype","text":"eltype(link::Link)\n\nReturns element type of link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.isopen-Tuple{Link}","page":"Links","title":"Base.isopen","text":"isopen(link::Link)\n\nReturns true if link is open. A link is open if its channel is open.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.isreadable-Tuple{Link}","page":"Links","title":"Base.isreadable","text":"isreadable(link::Link)\n\nReturns true if link is readable. When link is readable, data can be read from link with take function.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.iswritable-Tuple{Link}","page":"Links","title":"Base.iswritable","text":"writable(link::Link)\n\nReturns true if link is writable. When link is writable, data can be written into link with put function.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.put!-Tuple{Link,Any}","page":"Links","title":"Base.put!","text":"put!(link::Link, val)\n\nPuts val to link. val is handed over to the channel of link. val is also written in to the buffer of link.\n\nwarning: Warning\nlink must be writable to put val. That is, a runnable task that takes items from the link must be bounded to link.\n\nExample\n\njulia> l = Link();\n\njulia> t = @async while true \n item = take!(l)\n item === NaN && break \n println(\"Took \" * string(item))\n end;\n\njulia> bind(l, t);\n\njulia> put!(l, 1.)\nTook 1.0\n1.0\n\njulia> put!(l, 2.)\nTook 2.0\n2.0\n\njulia> put!(l, NaN)\nNaN\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.take!-Tuple{Link}","page":"Links","title":"Base.take!","text":"take!(link::Link)\n\nTake an element from link.\n\nwarning: Warning\nlink must be readable to take value. That is, a runnable task that puts items from the link must be bounded to link.\n\nExample\n\njulia> l = Link(5);\n\njulia> t = @async for item in 1. : 5.\n put!(l, item)\n end;\n\njulia> bind(l, t);\n\njulia> take!(l)\n1.0\n\njulia> take!(l)\n2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Causal.isfull-Tuple{Link}","page":"Links","title":"Causal.isfull","text":"isfull(link::Link)\n\nReturns true if the buffer of link is full.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Causal.launch-Tuple{Link,Any}","page":"Links","title":"Causal.launch","text":"launch(link:Link, valrange)\n\nConstructs a putter task and binds it to link. putter tasks puts the data in valrange.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Causal.launch-Tuple{Link}","page":"Links","title":"Causal.launch","text":"launch(link::Link)\n\nConstructs a taker task and binds it to link. The taker task reads the data and prints an info message until missing is read from the link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Causal.refresh!-Union{Tuple{Link{T}}, Tuple{T}} where T","page":"Links","title":"Causal.refresh!","text":"refresh!(link::Link)\n\nReconstructst the channel of link is its channel is closed.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Causal.snapshot-Tuple{Link}","page":"Links","title":"Causal.snapshot","text":"snapshot(link::Link)\n\nReturns all the data of the buffer of link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Pins","page":"Pins","title":"Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Pins are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin and Inpin. The data flows from inside of the components to its outside through Outpin while data flow from outside of the components to its inside through Inpin.","category":"page"},{"location":"manual/connections/pin/#Connection-and-Disconnection-of-Pins","page":"Pins","title":"Connection and Disconnection of Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"In Causal, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Causal). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Links. A Link connects Outpins to Inpins, and the data flow is from Outpin to Inpin.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"note: Note\nAs the data movement is from Outpin to Inpin, connection of an Inpin to an Outpin gives a MethodError.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"For example, let us construct and Outpin and Inpins and connect the together.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"using Causal # hide \nop = Outpin() \nip = Inpin() \nlink = connect!(op, ip)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note connect!(op, ip) connects op and ip through a Link can return the constructed link. The connection of pins can be monitored. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"isconnected(op, ip)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The constructed link can be accessed though the pins. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"op.links[1] === link \nip.link === link","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"note: Note\nIt is possible for an Outpin to have multiple Links bound to itself. On contract, an Inpin can have just one Link.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The connected links Outpin and Inpin can be disconnected using disconnect! function. When disconnected, the data transfer from the Outpin to Inpin is not possible. ","category":"page"},{"location":"manual/connections/pin/#Data-Flow-Through-Pins","page":"Pins","title":"Data Flow Through Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The data flow from an Outpin to an Inpin. However for data flow through a pin, a running task must be bound the channel of the link of the pin. See the example below. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"t = @async while true \n take!(ip) === NaN && break \nend ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"As the task t is bound the channel of the link data can flow through op and ip. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"put!(op, 1.)\nput!(op, 2.) \nput!(op, 3.)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note that t is a taker job. As the taker job t takes data from op, we were able to put values into op. The converse is also possible. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"op2, ip2 = Outpin(), Inpin() \nlink2 = connect!(op2, ip2) \nt2 = @async for item in 1 : 5\n put!(op2, item)\nend\ntake!(ip2)\ntake!(ip2)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note that in both of the cases given above the data flow is always from an Outpin to an Inpin. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"warning: Warning\nIt is not possible to take data from an Outpin and put into Inpin. Thus, take!(pin::Outpoin) and put!(pin::Inpin) throws a method error.","category":"page"},{"location":"manual/connections/pin/#Full-API","page":"Pins","title":"Full API","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Modules = [Causal]\nPages = [\"pin.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/pin/#Causal.AbstractPin","page":"Pins","title":"Causal.AbstractPin","text":"AbstractPin{T}\n\nAbstract type of Outpin and Inpin. See also: Outpin, Inpin\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Causal.Inpin","page":"Pins","title":"Causal.Inpin","text":"Inpin{T}()\n\nConstructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Causal.Outpin","page":"Pins","title":"Causal.Outpin","text":"Outpin{T}()\n\nConstructs and OutPut pin. The data flow from Outpin is outwards from the pin i.e., data is written from OutPort to its links.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Base.bind-Tuple{Link,Inpin}","page":"Pins","title":"Base.bind","text":"bind(link::Link, pin)\n\nBinds link to pin. When bound, data written into or read from pin is written into or read from link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.eltype-Union{Tuple{AbstractPin{T}}, Tuple{T}} where T","page":"Pins","title":"Base.eltype","text":"eltype(pin::AbstractPin)\n\nReturns element typef of pin.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.put!-Tuple{Outpin,Any}","page":"Pins","title":"Base.put!","text":"put!(pin::Outpin, val)\n\nPuts val to pin. val is put into the links of pin.\n\nwarning: Warning\nTo take data from pin, a running task that puts data must be bound to link of pin.\n\nExample\n\njulia> op = Outpin();\n\njulia> l = Link();\n\njulia> bind(l, op);\n\njulia> t = @async while true \n val = take!(l) \n val === NaN && break\n println(\"Took \" * string(val))\n end;\n\njulia> put!(op, 1.)\nTook 1.0\n\njulia> put!(op, 3.)\nTook 3.0\n\njulia> put!(op, NaN)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.take!-Tuple{Inpin}","page":"Pins","title":"Base.take!","text":"take!(pin::Inpin)\n\nTakes data from pin. The data is taken from the links of pin.\n\nwarning: Warning\nTo take data from pin, a running task that puts data must be bound to link of pin.\n\nExample\n\njulia> ip = Inpin();\n\njulia> l = Link();\n\njulia> bind(l, ip);\n\njulia> t = @async for item in 1 : 5 \n put!(l, item)\n end;\n\njulia> take!(ip)\n1.0\n\njulia> take!(ip)\n2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Causal.connect!-Tuple{Outpin,Inpin}","page":"Pins","title":"Causal.connect!","text":"connect!(outpin::Link, inpin::Link)\n\nConnects outpin to inpin. When connected, any element that is put into outpin is also put into inpin. \n\nconnect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})\n\nConnects each link in outpin to each link in inpin one by one. See also: disconnect!\n\nExample\n\njulia> op, ip = Outpin(), Inpin();\n\njulia> l = connect!(op, ip)\nLink(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> l in op.links\ntrue\n\njulia> ip.link === l\ntrue\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Causal.disconnect!-Tuple{Outpin,Inpin}","page":"Pins","title":"Causal.disconnect!","text":"disconnect!(link1::Link, link2::Link)\n\nDisconnects link1 and link2. The order of arguments is not important. See also: connect!\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Causal.isbound-Tuple{Outpin}","page":"Pins","title":"Causal.isbound","text":"isbound(pin::AbstractPin)\n\nReturns true if pin is bound to other pins.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Causal.isconnected-Tuple{Outpin,Inpin}","page":"Pins","title":"Causal.isconnected","text":"isconnected(link1, link2)\n\nReturns true if link1 is connected to link2. The order of the arguments are not important. See also connect!, disconnect!\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Callback","page":"Callback","title":"Callback","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Callbacks are used to monitor the existence of a specific event and if that specific event occurs, some other special jobs are invoked. Callbacks are intended to provide additional monitoring capability to any user-defined composite types. As such, Callbacks are generally fields of user defined composite types. When a Callback is called, if the Callback is enabled and its condition function returns true, then its action function is invoked. ","category":"page"},{"location":"manual/utilities/callback/#A-Simple-Example","page":"Callback","title":"A Simple Example","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Let's define a test object first that has a field named x of type Int and named callback of type Callback. ","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> mutable struct TestObject\n x::Int\n callback::Callback\n end","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"To construct an instance of TestObject, we need to construct a Callback. For that purpose, the condition and action function must be defined. For this example, condition checks whether the x field is positive, and action prints a simple message saying that the x field is positive.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> condition(testobject) = testobject.x > 0 \ncondition (generic function with 1 method)\n\njulia> action(testobject) = println(\"testobject.x is greater than zero\") \naction (generic function with 1 method)","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now a test object can be constructed","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject = TestObject(-1, Callback(condition, action)) \nTestObject(-1, Callback{typeof(condition),typeof(action)}(condition, action, true, \"dac6f9eb-6daa-4622-a8fa-623f0f88780c\"))","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"If the callback is called, no action is performed since the condition function returns false. Note the argument sent to the callback. The instance of the TestObject to which the callback is bound.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.callback(testobject) ","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now mutate the test object so that condition returns true.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.x = 3 \n3","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now, if the callback is called, since the condition returns true and the callback is enabled, the action is invoked.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.callback(testobject) \ntestobject.x is greater than zero","category":"page"},{"location":"manual/utilities/callback/#Full-API","page":"Callback","title":"Full API","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Callback","category":"page"},{"location":"manual/utilities/callback/#Causal.Callback","page":"Callback","title":"Causal.Callback","text":"Callback(condition, action)\n\nConstructs a Callback from condition and action. The condition and action must be a single-argument function. The condition returns true if the condition it checks occurs, otherwise, it returns false. action performs the specific action for which the Callback is constructed. A Callback can be called by passing its single argument which is mostly bound to the Callback.\n\nExample\n\njulia> struct Object # Define a dummy type.\n x::Int \n clb::Callback \n end\n\njulia> cond(obj) = obj.x > 0; # Define callback condition.\n\njulia> action(obj) = println(\"obj.x = \", obj.x); # Define callback action.\n\njulia> obj = Object(1, Callback(condition=cond, action=action))\nObject(1, Callback(condition:cond, action:action))\n\njulia> obj.clb(obj) # Call the callback bound `obj`.\nobj.x = 1\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Modules = [Causal]\nPages = [\"callback.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/utilities/callback/#Causal.applycallbacks-Tuple{Any}","page":"Callback","title":"Causal.applycallbacks","text":"applycallbacks(obj)\n\nCalls the callbacks of obj if the callbacks are not nothing.\n\nExample\n\njulia> mutable struct MyType{CB}\n x::Int\n callbacks::CB\n end\n\njulia> obj = MyType(5, Callback(condition=obj -> obj.x > 0, action=obj -> println(\"x is positive\")));\n\njulia> applycallbacks(obj)\nx is positive\n\njulia> obj.x = -1\n-1\n\njulia> applycallbacks(obj)\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Causal.disable!-Tuple{Callback}","page":"Callback","title":"Causal.disable!","text":"disable!(clb::Callback)\n\nDisables clb.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Causal.enable!-Tuple{Callback}","page":"Callback","title":"Causal.enable!","text":"enable!(clb::Callback)\n\nEnables clb.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Causal.isenabled-Tuple{Callback}","page":"Callback","title":"Causal.isenabled","text":"isenabled(clb::Callback)\n\nReturns true if clb is enabled. Otherwise, returns false.\n\n\n\n\n\n","category":"method"},{"location":"tutorials/defining_new_components/#Defining-New-Component-Types","page":"Extending Component Library","title":"Defining New Component Types","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Causal provides a library that includes some well-known components that are ready to be used. For example,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"FunctionGenerator, SinewaveGenerator, SquarewaveGenerator, RampGenerator, etc. as sources\nStaticSystem, Adder, Multiplier, Gain, etc. as static systems\nDiscreteSystem, DiscreteLinearSystem, HenonSystem, LogisticSystem, etc. as dynamical systems represented by discrete difference equations.\nODESystem, LorenzSystem, ChenSystem, ChuaSystem, etc. as dynamical systems represented by ODEs.\nDAESystem, RobertsonSystem, etc. as dynamical systems represented by dynamical systems represented by DAEs.\nRODESystem, MultiplicativeNoiseLinearSystem, etc. as dynamical systems represented by dynamical systems represented by RODEs.\nSDESystem, NoisyLorenzSystem, ForcedNoisyLorenzSystem, etc. as dynamical systems represented by dynamical systems represented by SDEs.\nDDESystem, DelayFeedbackSystem, etc. as dynamical systems represented by dynamical systems represented by DDEs.\nWriter, Printer, Scope, etc. as sinks.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"It is very natural that this library may lack some of the components that are wanted to be used by the user. In such a case, Causal provides the users with the flexibility to enrich this library. The users can define their new component types, including source, static system, dynamical system, sink and use them with ease. ","category":"page"},{"location":"tutorials/defining_new_components/#Defining-A-New-Source","page":"Extending Component Library","title":"Defining A New Source","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"New source types are defines using @def_source macro. Before embarking on defining new source, let us get the necessary information on how to use @def_source. This can be can be obtained through its docstrings. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"using Causal # hide \n@doc @def_source","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"From the docstring, its clear that new types of source can be defined as if we define a new Julia type. The difference is that the struct keyword is preceded by @def_source macro and the new component must be a subtype of AbstractSource. Also from the docstring is that the new type has some optional and mandatory fields. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"warning: Warning\nTo define a new source, mandatory fields must be defined. The optional fields are the parameters of the source.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"For example let us define a new source that generates waveforms of the form. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":" y(t) = \n beginbmatrix\n alpha sin(t) \n beta cos(t)\n endbmatrix","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Here alpha and beta is the system parameters. That is, while defining the new source component, alpha and beta are optional fields. readout and output are the mandatory field while defining a source. Note from above equation that the output of the new source has two pins. Thus, this new source component type, say MySource is defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_source struct MySource{RO, OP} <: AbstractSource \n α::Float64 = 1. \n β::Float64 = 2. \n readout::RO = (t, α=α, β=β) -> [α*sin(t), β*cos(t)]\n output::OP = Outport(2)\nend","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Note that the syntax is very similar to the case in which we define a normal Julia type. We start with struct keyword preceded with @def_source macro. In order for the MySource to work flawlessly, i.e. to be used a model component, it must a subtype of AbstractSource. The readout function of MySource is a function of t and the remaining parameters, i.e., alpha and beta, are passed into as optional arguments to avoid global variables. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"One other important point to note is that the MySource has additional fields that are required for it to work as a regular model component. Let us print all the field names of MySource, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"fieldnames(MySource)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"We know that we defined the fields α, β, readout, output, but, the fields trigger, callback, handshake, callbacks, name, id are defined automatically by @def_source macro. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Since the type MySource has been defined, any instance of it can be constructed. Let us see the constructors first.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"methods(MySource)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The constructor with the keyword arguments is very much easy to uses. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"gen1 = MySource()\ngen2 = MySource(α=4.)\ngen3 = MySource(α=4., β=5.)\ngen3 = MySource(α=4., β=5., name=:mygen)\ngen3.trigger \ngen3.id \ngen3.α\ngen3.β\ngen3.output","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"An instance works flawlessly as a model component, that is, it can be driven from its trigger pin and signalling cane be carried out from its handshake pin. To see this, let us construct required pins and ports to drive a MySource instance. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"gen = MySource() # `MySource` instance \ntrg = Outpin() # To trigger `gen`\nhnd = Inpin{Bool}() # To signalling with `gen`\niport = Inport(2) # To take values out of `gen` \nconnect!(trg, gen.trigger); \nconnect!(gen.handshake, hnd);\nconnect!(gen.output, iport);\nlaunch(gen) # Launch `gen,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Now gen can be driven through trg pin. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"put!(trg, 1.) # Drive `gen` for `t=1`.\ntake!(iport) # Read output of `gen` from `iport`\ntake!(hnd) # Approve `gen` has taken a step.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Thus, by using @def_source macro, it is possible for the users to define any type of sources under AbstractSource type and user them without a hassle. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The procedure is again the same for any other component types. The table below lists the macros that are used to define new component types. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Macro Component Type Supertype Mandatory Field Names\n@def_source Source AbstractSource readout, output\n@def_static_system StaticSystem AbstractStaticSystem readout, output, input\n@def_discrete_system Discrete Dynamic System AbstractDiscreteSystem righthandside, readout, state, input, output\n@def_ode_system ODE Dynamic System AbstractODESystem righthandside, readout, state, input, output\n@def_dae_system DAE Dynamic System AbstractDAESystem righthandside, readout, state, stateder, diffvars, input, output\n@def_rode_system RODE Dynamic System AbstractRODESystem righthandside, readout, state, input, output\n@def_sde_system SDE Dynamic System AbstractSDESystem drift, diffusion, readout, state, input, output\n@def_dde_system DDE Dynamic System AbstractDDESystem constlags, depslags, righthandside, history, readout, state, input, output\n@def_sink Sink AbstractSink action","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The steps followed in the previous section are the same to define other component types: start with suitable macro given above, make the newly-defined type a subtype of the corresponding supertype, define the optional fields (if exist) ands define the mandatory fields of the new type (with the default values if necessary).","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-StaticSystem","page":"Extending Component Library","title":"Defining New StaticSystem","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Consider the following readout function of the static system to be defined ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"y = u_1 t + a cos(u_2)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"where u = u_1 u_2 is the input, y is the output of the system and t is time. The system has two inputs and one output. This system can be defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_static_system struct MyStaticSystem{RO, IP, OP} <: AbstractStaticSystem\n a::Float64 = 1.\n readout::RO = (t, a = a) -> u[1] * t + a * cos(u[2])\n input::IP = Inport(2)\n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-Discrete-Dynamical-System","page":"Extending Component Library","title":"Defining New Discrete Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The discrete dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\nx_k + 1 = α x_k + u_k 025cm\ny_k = x_k\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_discrete_system struct MyDiscreteSystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-ODE-Dynamical-System","page":"Extending Component Library","title":"Defining New ODE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The ODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndotx = α x + u 025cm\ny = x\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_ode_system struct MyODESystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-DAE-Dynamical-System","page":"Extending Component Library","title":"Defining New DAE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The DAE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarray\ndx = x + 1 025cm\n0 = 2(x + 1) + 2\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_dae_system mutable struct MyDAESystem{RH, RO, ST, IP, OP} <: AbstractDAESystem\n righthandside::RH = function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end \n readout::RO = (x,u,t) -> x \n state::ST = [1., -1]\n stateder::ST = [2., 0]\n diffvars::Vector{Bool} = [true, false]\n input::IP = nothing \n output::OP = Outport(1)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-RODE-Dynamical-System","page":"Extending Component Library","title":"Defining RODE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The RODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndotx = A x W 025cm\ny = x \nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"where ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"A = beginbmatrix\n 2 0 \n 0 -2\nendbmatrix","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_rode_system struct MyRODESystem{RH, RO, IP, OP} <: AbstractRODESystem\n A::Matrix{Float64} = [2. 0.; 0 -2]\n righthandside::RH = (dx, x, u, t, W) -> (dx .= A * x * W)\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(2) \n input::IP = nothing \n output::OP = Outport(2)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-SDE-Dynamical-System","page":"Extending Component Library","title":"Defining SDE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The RODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndx = -x dt + dW 025cm\ny = x \nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_sde_system mutable struct MySDESystem{DR, DF, RO, ST, IP, OP} <: AbstractSDESystem\n drift::DR = (dx, x, u, t) -> (dx .= -x)\n diffusion::DF = (dx, x, u, t) -> (dx .= 1)\n readout::RO = (x, u, t) -> x \n state::ST = [1.] \n input::IP = nothing\n output::OP = Outport(1)\nend ","category":"page"},{"location":"tutorials/defining_new_components/#Defining-DDE-Dynamical-System","page":"Extending Component Library","title":"Defining DDE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The DDE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":" beginarrayl\n dotx = -x(t - tau) quad t geq 0 \n x(t) = 1 -tau leq t leq 0 \n endarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"_delay_feedback_system_cache = zeros(1)\n_delay_feedback_system_tau = 1.\n_delay_feedback_system_constlags = [1.]\n_delay_feedback_system_history(cache, u, t) = (cache .= 1.)\nfunction _delay_feedback_system_rhs(dx, x, h, u, t, \n cache=_delay_feedback_system_cache, τ=_delay_feedback_system_tau)\n h(cache, u, t - τ) # Update cache \n dx[1] = cache[1] + x[1]\nend\n@def_dde_system mutable struct DelayFeedbackSystem{RH, HST, RO, IP, OP} <: AbstractDDESystem\n constlags::Vector{Float64} = _delay_feedback_system_constlags\n depslags::Nothing = nothing\n righthandside::RH = _delay_feedback_system_rhs\n history::HST = _delay_feedback_system_history\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(1)\n input::IP = nothing \n output::OP = Outport(1)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-Sinks","page":"Extending Component Library","title":"Defining Sinks","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Say we want a sink type that takes the data flowing through the connections of the model and prints it. This new sink type cane be defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_sink struct MySink{A} <: AbstractSink\n action::A = actionfunc\nend\nactionfunc(sink::MySink, t, u) = println(t, u)","category":"page"},{"location":"manual/components/componentsbase/hierarchy/#Component-Type-Hierarchy","page":"Component Type Hierarchy","title":"Component Type Hierarchy","text":"","category":"section"},{"location":"manual/components/componentsbase/hierarchy/","page":"Component Type Hierarchy","title":"Component Type Hierarchy","text":"AbstractComponent \nAbstractSource \nAbstractSystem \nAbstractSink \nAbstractStaticSystem \nAbstractDynamicSystem \nAbstractSubSystem \nAbstractMemory \nAbstractDiscreteSystem\nAbstractODESystem\nAbstractRODESystem \nAbstractDAESystem \nAbstractSDESystem \nAbstractDDESystem ","category":"page"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractComponent","page":"Component Type Hierarchy","title":"Causal.AbstractComponent","text":"abstract type AbstractComponent\n\nAbstract type of all components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractSource","page":"Component Type Hierarchy","title":"Causal.AbstractSource","text":"abstract type AbstractSource <: AbstractComponent\n\nAbstract typeof all source components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractSystem","page":"Component Type Hierarchy","title":"Causal.AbstractSystem","text":"abstract type AbstractSystem <: AbstractComponent\n\nAbstract type of all system components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractSink","page":"Component Type Hierarchy","title":"Causal.AbstractSink","text":"abstract type AbstractSink <: AbstractComponent\n\nAbstract type of all sink components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractStaticSystem","page":"Component Type Hierarchy","title":"Causal.AbstractStaticSystem","text":"abstract type AbstractStaticSystem <: AbstractSystem\n\nAbstract type of all static systems\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractDynamicSystem","page":"Component Type Hierarchy","title":"Causal.AbstractDynamicSystem","text":"abstract type AbstractDynamicSystem <: AbstractSystem\n\nAbstract type of all dynamic system components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractSubSystem","page":"Component Type Hierarchy","title":"Causal.AbstractSubSystem","text":"abstract type AbstractSubSystem <: AbstractSystem\n\nAbstract type of all subsystem components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractMemory","page":"Component Type Hierarchy","title":"Causal.AbstractMemory","text":"abstract type AbstractMemory <: AbstractStaticSystem\n\nAbstract type of all memory components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractDiscreteSystem","page":"Component Type Hierarchy","title":"Causal.AbstractDiscreteSystem","text":"abstract type AbstractDiscreteSystem <: AbstractDynamicSystem\n\nAbstract type of all dynamic systems modelled by dicrete difference equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractODESystem","page":"Component Type Hierarchy","title":"Causal.AbstractODESystem","text":"abstract type AbstractODESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by ordinary differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractRODESystem","page":"Component Type Hierarchy","title":"Causal.AbstractRODESystem","text":"abstract type AbstractRODESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by random ordinary differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractDAESystem","page":"Component Type Hierarchy","title":"Causal.AbstractDAESystem","text":"abstract type AbstractDAESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by differential algebraic equations\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractSDESystem","page":"Component Type Hierarchy","title":"Causal.AbstractSDESystem","text":"abstract type AbstractSDESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by stochastic differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Causal.AbstractDDESystem","page":"Component Type Hierarchy","title":"Causal.AbstractDDESystem","text":"abstract type AbstractDDESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modlled by delay dynamical systems.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops","page":"Algebraic Loops","title":"Breaking Algebraic Loops","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"It this tutorial, we will simulate model consisting a closed loop feedback system. The model has an algebraic loop. ","category":"page"},{"location":"tutorials/algebraic_loops/#Algebraic-Loops","page":"Algebraic Loops","title":"Algebraic Loops","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. If algebraic loops exist in a model, the simulation gets stuck because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Causal provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops. ","category":"page"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops-Automatically","page":"Algebraic Loops","title":"Breaking Algebraic Loops Automatically","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Before initializing and running the simulation, Causal inspects the model first. See Simulation Stages for more information of simulation stages. In case the they exist in the model, all the algebraic loops are tried to be broken automatically without requiring a user intervention. Consider the following model ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"where ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"beginarrayl\n r(t) = t 025cm\n u(t) = r(t) - y(t) 025cm\n y(t) = u(t) \nendarray","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Note that there exist an algebraic loop consisting of adder and gain. Solving this algebraic loop, we have ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":" y(t) = u(t) = r(t) - y(t) quad Rightarrow quad y(t) = dfracr(t)2 = dfract2","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"The following script constructs and simulates the model. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Causal \n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nti, dt, tf = 0., 1. / 64., 1.\nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Read the simulation data and plot \nusing Plots\nt, y = read(getnode(model, :writerout).component)\nt, r = read(getnode(model, :writerin).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3)) \nplot!(t, y, label=\"y(t)\", marker=(:circle, 3)) \nsavefig(\"breaking_algebraic_loops_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: )","category":"page"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops-With-a-Memory","page":"Algebraic Loops","title":"Breaking Algebraic Loops With a Memory","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"It is also possible to break algebraic loops by inserting a Memory component at some point the loop. For example, consider the model consider following the model which is the model in which a memory component is inserted in the feedback path. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Note that the input to adder is not y(t), but instead is haty(t) which is one sample delayed form of y(t). That is, we have, haty(t) = y(t - dt) where dt is the step size of the simulation. If dt is small enough, haty(t) approx y(t).","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"The script given below simulates this case. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Causal \n\n# Simulation time settings.\nti, dt, tf = 0., 1. / 64., 1.\n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n mem = Memory(delay=dt, initial=zeros(1))\n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => mem[1]\n mem[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Plot the simulation data\nusing Plots\nt, r = read(getnode(model, :writerin).component)\nt, y = read(getnode(model, :writerout).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3))\nplot!(t, y, label=\"y(t)\", marker=(:circle, 3))\nsavefig(\"breaking_algebraic_loops_with_memory_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: ) The fluctuation in y(t) because of one-sample-time delay introduced by the mem component is apparent. The smaller the step size is, the smaller the amplitude of the fluctuation introduced by the mem component. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"One other important issue with using the memory component is that the initial value of mem directly affects the accuracy of the simulation. By solving the loop equation, we know that ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":" y(t) = dfracr(t)2 = dfract2 quad Rightarrow quad y(0) = 0","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"That is the memory should be initialized with an initial value of zero, which is the case in the script above. To observe that how incorrect initialization of a memory to break an algebraic loop, consider the following example in which memory is initialized randomly. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Causal \nusing Plots \n\n# Simulation time settings.\nti, dt, tf = 0., 1. / 64., 1.\n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n mem = Memory(delay=dt, initial=rand(1))\n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => mem[1]\n mem[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Plot the results \nusing Plots\nt, r = read(getnode(model, :writerin).component)\nt, y = read(getnode(model, :writerout).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3))\nplot!(t, y, label=\"y(t)\", marker=(:circle, 3))\nsavefig(\"breaking_algebraic_loops_with_memory_incorrect_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: )","category":"page"},{"location":"manual/components/sources/generators/#Generators","page":"Generators","title":"Generators","text":"","category":"section"},{"location":"manual/components/sources/generators/#Basic-Operation-AbstractSource","page":"Generators","title":"Basic Operation AbstractSource","text":"","category":"section"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"using Causal # hide \nf(t) = t * exp(t) + sin(t)\ngen = FunctionGenerator(readout=f)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"We constructed a FunctionGenerator which is an AbstractSource.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen isa AbstractSource","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"trg, hnd, iport = Outpin(), Inpin{Bool}(), Inport(length(gen.output))\nconnect!(gen.output, iport)\nconnect!(trg, gen.trigger) \nconnect!(gen.handshake, hnd)\nt = launch(gen)\ntout = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen.trigger.link\ngen.output[1].links[1]","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen is triggered by writing time t to trg","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"When triggered gen writes true to its handshake link gen.handshake which can be read from hnd.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"hnd.link","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"and to drive gen for another time hnd must be read. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"take!(hnd)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"Now continue driving gen.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"When triggered, the output of gen is written to its output gen.output.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen.output[1].links[1].buffer","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"Causal provides some other function generators which are documented in the following section.","category":"page"},{"location":"manual/components/sources/generators/#Full-API","page":"Generators","title":"Full API","text":"","category":"section"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"@def_source \nFunctionGenerator\nSinewaveGenerator \nDampedSinewaveGenerator \nSquarewaveGenerator \nTriangularwaveGenerator \nConstantGenerator \nRampGenerator \nStepGenerator \nExponentialGenerator \nDampedExponentialGenerator ","category":"page"},{"location":"manual/components/sources/generators/#Causal.@def_source","page":"Generators","title":"Causal.@def_source","text":"@def_source ex\n\nwhere ex is the expression to define to define a new AbstractSource component type. The usage is as follows:\n\n@def_source struct MySource{T1,T2,T3,...,TN,OP, RO} <: AbstractSource\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n output::OP = output_default # mandatory field \n readout::RO = readout_function # mandatory field\nend\n\nHere, MySource has N parameters, an output port and a readout function.\n\nwarning: Warning\noutput and readout are mandatory fields to define a new source. The rest of the fields are the parameters of the source.\n\nwarning: Warning\nreadout must be a single-argument function, i.e. a fucntion of time t.\n\nwarning: Warning\nNew source must be a subtype of AbstractSource to function properly.\n\nExample\n\njulia> @def_source struct MySource{OP, RO} <: AbstractSource\n a::Int = 1 \n b::Float64 = 2. \n output::OP = Outport() \n readout::RO = t -> (a + b) * sin(t)\n end\n\njulia> gen = MySource();\n\njulia> gen.a \n1\n\njulia> gen.output\n1-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/sources/generators/#Causal.FunctionGenerator","page":"Generators","title":"Causal.FunctionGenerator","text":"FunctionGenerator(; readout, output=Outport())\n\nConstructs a generic function generator with readout function and output port.\n\nExample\n\njulia> gen = FunctionGenerator(readout = t -> [t, 2t], output = Outport(2));\n\njulia> gen.readout(1.)\n2-element Array{Float64,1}:\n 1.0\n 2.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.SinewaveGenerator","page":"Generators","title":"Causal.SinewaveGenerator","text":"SinewaveGenerator(;amplitude=1., frequency=1., phase=0., delay=0., offset=0.)\n\nConstructs a SinewaveGenerator with output of the form\n\n x(t) = A sin(2 pi f (t - tau) + phi) + B\n\nwhere A is amplitude, f is frequency, tau is delay and phi is phase and B is offset.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.DampedSinewaveGenerator","page":"Generators","title":"Causal.DampedSinewaveGenerator","text":"DampedSinewaveGenerator(;amplitude=1., decay=-0.5, frequency=1., phase=0., delay=0., offset=0.)\n\nConstructs a DampedSinewaveGenerator which generates outputs of the form \n\n x(t) = A e^alpha t sin(2 pi f (t - tau) + phi) + B\n\nwhere A is amplitude, alpha is decay, f is frequency, phi is phase, tau is delay and B is offset.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.SquarewaveGenerator","page":"Generators","title":"Causal.SquarewaveGenerator","text":"SquarewaveGenerator(;level1=1., level2=0., period=1., duty=0.5, delay=0.)\n\nConstructs a SquarewaveGenerator with output of the form \n\n x(t) = leftbeginarraylr\n\tA_1 + B kT + tau leq t leq (k + alpha) T + tau \n\tA_2 + B (k + alpha) T + tau leq t leq (k + 1) T + tau\t\n\tendarray right quad k in Z\n\nwhere A_1, A_2 is level1 and level2, T is period, tau is delay alpha is duty. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.TriangularwaveGenerator","page":"Generators","title":"Causal.TriangularwaveGenerator","text":"TriangularwaveGenerator(;amplitude=1, period=1, duty=0.5, delay=0, offset=0)\n\nConstructs a TriangularwaveGenerator with output of the form\n\n x(t) = leftbeginarraylr\n\tdfracA talpha T + B kT + tau leq t leq (k + alpha) T + tau 025cm\n\tdfracA (T - t)T (1 - alpha) + B (k + alpha) T + tau leq t leq (k + 1) T + tau\t\n\tendarray right quad k in Z\n\nwhere A is amplitude, T is period, tau is delay alpha is duty. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.ConstantGenerator","page":"Generators","title":"Causal.ConstantGenerator","text":"ConstantGenerator(;amplitude=1.)\n\nConstructs a ConstantGenerator with output of the form\n\n x(t) = A\n\nwhere A is `amplitude.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.RampGenerator","page":"Generators","title":"Causal.RampGenerator","text":"RampGenerator(;scale=1, delay=0.)\n\nConstructs a RampGenerator with output of the form\n\n x(t) = alpha (t - tau)\n\nwhere alpha is the scale and tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.StepGenerator","page":"Generators","title":"Causal.StepGenerator","text":"StepGenerator(;amplitude=1, delay=0, offset=0)\n\nConstructs a StepGenerator with output of the form \n\n x(t) = leftbeginarraylr\n\tB t leq tau \n\tA + B t tau\n\tendarray right\n\nwhere A is amplitude, B is the offset and tau is the delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.ExponentialGenerator","page":"Generators","title":"Causal.ExponentialGenerator","text":"ExponentialGenerator(;scale=1, decay=-1, delay=0.)\n\nConstructs an ExponentialGenerator with output of the form\n\n x(t) = A e^alpha (t - tau)\n\nwhere A is scale, alpha is decay and tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Causal.DampedExponentialGenerator","page":"Generators","title":"Causal.DampedExponentialGenerator","text":"DampedExponentialGenerator(;scale=1, decay=-1, delay=0.)\n\nConstructs an DampedExponentialGenerator with outpsuts of the form \n\n x(t) = A (t - tau) e^alpha (t - tau)\n\nwhere A is scale, alpha is decay, tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/taskmanager/#Task-Manager","page":"Task Manager","title":"Task Manager","text":"","category":"section"},{"location":"manual/models/taskmanager/","page":"Task Manager","title":"Task Manager","text":"A TaskManager is actually the pairs of components and the tasks constructed corresponding to those components. In Causal, models are simulated by individually evolving the components. This individual evolution of components is performed by defining components individually and constructing tasks for each components. The jobs that are defined in these tasks are defined to make the components evolve by reading its time, input, compute its output. During this evolution, the tasks may fail because any inconsistency. Right after the failure of a task, its not possible for the component corresponding to the task to evolve any more. As the data flows through the components that connects the components, model simulation gets stuck. To keep track of the task launched for each component, a TaskManager is used. Before starting to simulate a model, a TaskManager is constructed for the model components. During the initialization of simulation, tasks corresponding to the components of the model is launched and the pair of component and component task is recorded in the TaskManager of the model. During the run stage of the simulation, TaskManager keeps track of the component tasks. In case any failure in components tasks, the cause of the failure can be investigated with TaskManager.","category":"page"},{"location":"manual/models/taskmanager/#Full-API","page":"Task Manager","title":"Full API","text":"","category":"section"},{"location":"manual/models/taskmanager/","page":"Task Manager","title":"Task Manager","text":"Modules = [Causal]\nPages = [\"taskmanager.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/taskmanager/#Causal.TaskManager","page":"Task Manager","title":"Causal.TaskManager","text":"TaskManager(pairs)\n\nConstructs a TaskManager with pairs. pairs is a dictionary whose keys are components and values are component tasks. Component tasks are constructed correponding to the components. A TaskManager is used to keep track of the component task launched corresponding to components.\n\nTaskManager()\n\nConstructs a TaskManager with empty pairs. ```\n\n\n\n\n\n","category":"type"},{"location":"manual/models/taskmanager/#Causal.checktaskmanager-Tuple{TaskManager}","page":"Task Manager","title":"Causal.checktaskmanager","text":"checktaskmanager(tm::TaskManager)\n\nThrows an error if any of the component task of tm is failed. See also: TaskManager\n\n\n\n\n\n","category":"method"},{"location":"manual/models/taskmanager/#Causal.istaskrunning","page":"Task Manager","title":"Causal.istaskrunning","text":"istaskrunning(task::Task)\n\nReturns true is the state of task is runnable. \n\nistaskrunning(task::Nothing)\n\nReturns true\n\nistaskrunning(comptask::ComponentTask)\n\nReturns true if triggertask and outputtask of comptask is running. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Evolution-of-Components","page":"Evolution of Components","title":"Evolution of Components","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"In Causal, the simulation of a model is performed by individual evolution of components (see Modeling and Simulation for more information of modeling and simulation adopted in Causal). Basically, when triggered through its trigger pin, based on its type, a component takes a forward step as follows, ","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"The next clock time t is read from its trigger pin.\nThe next input value u(t) is read from from its input port, \nThe component evolves from its current time t - dt to the current clock time t\nUsing the state variable x(t) at time t, current clock time t and u(t), the next output value y(t) is computed. \nThe component writes true to its handshake pin to signal that taking step is performed with success.","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"or a backward step as follows. ","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"The next clock time t is read from its trigger pin.\nUsing the state variable x(t - dt) at time t - dt, current component time t - dt and u(t - dt), the next output value y(t) is computed. \nThe next input value u(t) is read from from its input port, \nThe component evolves from its current time t - dt to the current clock time t\nThe component writes true to its handshake pin to signal that taking step is performed with success.","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"Here dt is the simulation step size. ","category":"page"},{"location":"manual/components/componentsbase/evolution/#Reading-Time","page":"Evolution of Components","title":"Reading Time","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readtime!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.readtime!","page":"Evolution of Components","title":"Causal.readtime!","text":"readtime!(comp::AbstractComponent)\n\nReturns current time of comp read from its trigger link.\n\nnote: Note\nTo read time of comp, comp must be launched. See also: launch(comp::AbstractComponent).\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Reading-State","page":"Evolution of Components","title":"Reading State","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readstate","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.readstate","page":"Evolution of Components","title":"Causal.readstate","text":"readstate(comp::AbstractComponent)\n\nReturns the state of comp if comp is AbstractDynamicSystem. Otherwise, returns nothing. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Reading-Input","page":"Evolution of Components","title":"Reading Input","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readinput!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.readinput!","page":"Evolution of Components","title":"Causal.readinput!","text":"readinput!(comp::AbstractComponent)\n\nReturns the input value of comp if the input of comp is Inport. Otherwise, returns nothing.\n\nnote: Note\nTo read input value of comp, comp must be launched. See also: launch(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Writing-Output","page":"Evolution of Components","title":"Writing Output","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"writeoutput!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.writeoutput!","page":"Evolution of Components","title":"Causal.writeoutput!","text":"writeoutput!(comp::AbstractComponent, out)\n\nWrites out to the output of comp if the output of comp is Outport. Otherwise, does nothing.\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Computing-Output","page":"Evolution of Components","title":"Computing Output","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"computeoutput ","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.computeoutput","page":"Evolution of Components","title":"Causal.computeoutput","text":"computeoutput(comp, x, u, t)\n\nComputes the output of comp according to its readout if readout is not nothing. Otherwise, nothing is done. x is the state, u is the value of input, t is the time. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Evolve","page":"Evolution of Components","title":"Evolve","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"evolve!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.evolve!","page":"Evolution of Components","title":"Causal.evolve!","text":"evolve!(comp::AbstractSource, u, t)\n\nDoes nothing. u is the value of input and t is time.\n\nevolve!(comp::AbstractSink, u, t)\n\nWrites t to time buffer timebuf and u to databuf of comp. u is the value of input and t is time.\n\nevolve!(comp::AbstractStaticSystem, u, t)\n\nWrites u to buffer of comp if comp is an AbstractMemory. Otherwise, nothing is done. u is the value of input and t is time. \n\nevolve!(comp::AbstractDynamicSystem, u, t)\n\nSolves the differential equation of the system of comp for the time interval (comp.t, t) for the inital condition x where x is the current state of comp . u is the input function defined for (comp.t, t). The comp is updated with the computed state and time t. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Taking-Steps","page":"Evolution of Components","title":"Taking Steps","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"takestep!\nCausal.forwardstep\nCausal.backwardstep\nlaunch(comp::AbstractComponent)\nlaunch(comp::AbstractSubSystem)\ndrive!\napprove!\nterminate!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Causal.takestep!","page":"Evolution of Components","title":"Causal.takestep!","text":"takestep!(comp::AbstractComponent)\n\nReads the time t from the trigger link of comp. If comp is an AbstractMemory, a backward step is taken. Otherwise, a forward step is taken. See also: forwardstep, backwardstep.\n\n\n\n\n\ntakestep!(comp::AbstractSubSystem)\n\nMakes comp to take a step by making each subcomponent of comp take a step. See also: takestep!(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Causal.forwardstep","page":"Evolution of Components","title":"Causal.forwardstep","text":"forwardstep(comp, t)\n\nMakes comp takes a forward step. The input value u and state x of comp are read. Using x, u and time t, comp is evolved. The output y of comp is computed and written into the output bus of comp. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Causal.backwardstep","page":"Evolution of Components","title":"Causal.backwardstep","text":"backwardstep(comp, t)\n\nReads the state x. Using the time t and x, computes and writes the ouput value y of comp. Then, the input value u is read and comp is evolved. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Causal.launch-Tuple{AbstractComponent}","page":"Evolution of Components","title":"Causal.launch","text":"launch(comp::AbstractComponent)\n\nReturns a tuple of tasks so that trigger link and output bus of comp is drivable. When launched, comp is ready to be driven from its trigger link. See also: drive!(comp::AbstractComponent, t)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/componentsbase/evolution/#Causal.launch-Tuple{AbstractSubSystem}","page":"Evolution of Components","title":"Causal.launch","text":"launch(comp::AbstractSubSystem)\n\nLaunches all subcomponents of comp. See also: launch(comp::AbstractComponent)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/componentsbase/evolution/#Causal.drive!","page":"Evolution of Components","title":"Causal.drive!","text":"drive!(comp::AbstractComponent, t)\n\nWrites t to the trigger link of comp. When driven, comp takes a step. See also: takestep!(comp::AbstractComponent)\n\n\n\n\n\ndrive!(comp::AbstractSubSystem, t)\n\nDrives comp by driving each subcomponent of comp. See also: drive!(comp::AbstractComponent, t)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Causal.approve!","page":"Evolution of Components","title":"Causal.approve!","text":"approve!(comp::AbstractComponent)\n\nRead handshake link of comp. When not approved or false is read from the handshake link, the task launched for the trigger link of comp gets stuck during comp is taking step.\n\n\n\n\n\napprove!(comp::AbstractSubSystem)\n\nApproves comp by approving each subcomponent of comp. See also: approve!(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Causal.terminate!","page":"Evolution of Components","title":"Causal.terminate!","text":"terminate!(comp::AbstractComponent)\n\nCloses the trigger link and output bus of comp.\n\n\n\n\n\nterminate!(comp::AbstractSubSystem)\n\nTerminates comp by terminating each subcomponent of comp. See also: terminate!(comp::AbstractComponent)\n\n\n\n\n\nterminate!(model::Model)\n\nTerminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.\n\n\n\n\n\n","category":"function"},{"location":"manual/plugins/plugins/#Plugins","page":"Plugins","title":"Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Plugins are extensions that are used to process online the data flowing through the connections of the model during the simulation. These tools are specialized tools that are used for specialized data processing. In addition to the plugins that are provided by Causal, it is also possible to write new plugins that focus on different specialized data processing. The fundamental importance of Plugins is that they make the online simulation data processing possible. ","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"The Plugins are mostly used with Sinks. In Causal, the Sinks are used to sink simulation data flowing through the connections of the model. When a Sink is equipped with a proper Plugin according to the data processing desired, then the data flowing into the Sink is processed. For example, consider that a Writer is equipped with a Lyapunov plugin. During the simulation, data flowing into the Writer is processed to compute the maximum Lyapunov exponent, and these computed maximum Lyapunov exponents are recorded in the file of the Writer. Similarly, if a Printer is equipped with an Fft plugin, then Fast Fourier transform of the data flowing into the Printer is printed on the console.","category":"page"},{"location":"manual/plugins/plugins/#Data-processing-via-Plugins","page":"Plugins","title":"Data processing via Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Each Plugin must have a process function which does the data processing. The first argument of the process function is the Plugin and the second argument is the data to be processed. Here are some of the methods of process function","category":"page"},{"location":"manual/plugins/plugins/#Defining-New-Plugins","page":"Plugins","title":"Defining New Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"New plugins can be defined in Causal and having they are defined properly they can work just expected. To define a new plugin, we must first define the plugin type ","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"using Causal # hide \nstruct NewPlugin <: AbstractPlugin\n # Parameters of NewPlugin\nend","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"warning: Warning\nNote that to the NewPlugin is defined to be a subtype of AbstractPlugin. This is important for the NewPlugin to work as expected.","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Since each plugin must have implement a process method, and for that Causal.process function must be imported.","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"import Causal.process\nfunction process(plg::NewPlugin, x)\n # Define the process according to plg\nend","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"At this point, NewPlugin is ready to be used. ","category":"page"},{"location":"manual/models/simulation/#Simulation","page":"Simulation","title":"Simulation","text":"","category":"section"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"During the simulation of a model, a Simulation object is constructed. The field names of the Simulation object is ","category":"page"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"model::Model: The model for which the Simulation is constructed. \npath::String: The path of the directory into which all simulation-related files (log, data files etc.) are saved.\nlogger::AbstractLogger: The logger of the simulation constructed to log each stage of the Simulation . \nstate::Symbol: The state of the Simulation. The state may be :running if the simulation is running, :halted is the simulation is terminated without being completed, :done if it is terminated.\nretcode::Symbol: The return code of the simulation. The retcode may be :success if the simulation is completed without errors, :failed if the an error occurs during the simulation. ","category":"page"},{"location":"manual/models/simulation/#Full-API","page":"Simulation","title":"Full API","text":"","category":"section"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"Modules = [Causal]\nPages = [\"simulation.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/simulation/#Causal.Simulation","page":"Simulation","title":"Causal.Simulation","text":"Simulation(model; simdir=tempdir(), simname=string(uuid4()), simprefix=\"Simulation-\", logger=SimpleLogger())\n\nConstructs a Simulation object for the simulation of model. The Simulation object is used to monitor the state of the simulation of the model. simdir is the path of the directory into which the simulation files(log, data files etc.) are recorded. simname is the name of the Simulation and simprefix is the prefix of the name of the Simulation. logger is used to log the simulation steps of the model. See also: Model, Logging\n\n\n\n\n\n","category":"type"},{"location":"manual/models/simulation/#Causal.SimulationError","page":"Simulation","title":"Causal.SimulationError","text":"SimulationError(msg::String)\n\nThrown when an error occurs during a simulation.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/simulation/#Causal.closelogger","page":"Simulation","title":"Causal.closelogger","text":"closelogger(logger=global_logger())\n\nCloses the logger the file of the loggger. See also: setlogger\n\n\n\n\n\n","category":"function"},{"location":"manual/models/simulation/#Causal.report-Tuple{Simulation}","page":"Simulation","title":"Causal.report","text":"report(simulation::Simulation)\n\nRecords the state of the simulation by writing all its fields into a data file. All the fields of the simulation is written into file. When the file is read back, the simulation object is constructed back. The data file is written under the path of the simulation.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/simulation/#Causal.setlogger-Tuple{AbstractString,AbstractString}","page":"Simulation","title":"Causal.setlogger","text":"setlogger(path, name; setglobal::Bool=true)\n\nReturns a logger. path is the path and name is the name of the file of the logger. If setglobal is true, the returned logger is a global logger.\n\nExample\n\njulia> logger = setlogger(tempdir(), \"mylogger\", setglobal=true)\nBase.CoreLogging.SimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Scope","page":"Scope","title":"Scope","text":"","category":"section"},{"location":"manual/components/sinks/scope/#Basic-Operation-of-Scopes","page":"Scope","title":"Basic Operation of Scopes","text":"","category":"section"},{"location":"manual/components/sinks/scope/","page":"Scope","title":"Scope","text":"See Basic Operation of Writers since the operation of Writer and that of Scope is very similar.","category":"page"},{"location":"manual/components/sinks/scope/#Full-API","page":"Scope","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/scope/","page":"Scope","title":"Scope","text":"Scope \nupdate!(s::Scope, x, yi)\nclose(sink::Scope)\nopen(sink::Scope)","category":"page"},{"location":"manual/components/sinks/scope/#Causal.Scope","page":"Scope","title":"Causal.Scope","text":"Scope(input=Inport(), args...; buflen::Int=64, plugin=nothing, callbacks=nothing, name=Symbol(), kwargs...)\n\nConstructs a Scope with input bus input. buflen is the length of the internal buffer of Scope. plugin is the additional data processing tool. args,kwargs are passed into plots(args...; kwargs...)). See (https://github.com/JuliaPlots/Plots.jl) for more information.\n\nwarning: Warning\nWhen initialized, the plot of Scope is closed. See open(sink::Scope) and close(sink::Scope).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/scope/#Causal.update!-Tuple{Scope,Any,Any}","page":"Scope","title":"Causal.update!","text":"update!(s::Scope, x, yi)\n\nUpdates the series of the plot windows of s with x and yi.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Base.close-Tuple{Scope}","page":"Scope","title":"Base.close","text":"close(sink::Scope)\n\nCloses the plot window of the plot of sink.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Base.open-Tuple{Scope}","page":"Scope","title":"Base.open","text":"open(sink::Scope)\n\nOpens the plot window for the plots of sink.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#DiscreteSystem","page":"DiscreteSystem","title":"DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Construction-of-DiscreteSystem","page":"DiscreteSystem","title":"Construction of DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"DiscreteSystems evolve by the following discrete time difference equation.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":" x_k + 1 = f(x_k u_k k) \n y_k = g(x_k u_k k)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Basic-Construction-of-DiscreteSystem","page":"DiscreteSystem","title":"Basic Construction of DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We first define state function sfunc and output function ofunc of the system,","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"using Causal # hide \nsfunc(dx, x, u, t) = (dx .= -0.5x)\nofunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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 ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"input = nothing \noutput = Outport(1)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We also need to specify the initial condition and time of the system","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"x0 = [1.]\nt = 0.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We are now ready to construct the system ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"ds = DiscreteSystem(righthandside=sfunc, readout=ofunc, state=x0, input=input, output=output)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"To drive ds, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"iport, trg, hnd = Inport(1), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"At this point, ds is ready to be driven. To drive ds, we can either use drive(ds, t) or put!(ds.trigger, t). ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"hnd.link # `handshake` link is readable\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We continue to drive ds,","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"for i in 2. : 10. \n put!(trg, i)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"Note that all the output values of ds is written to its output bus.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"When we launched ds, we constructed a task which is still running.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We can confirm that the task is not running and its state is done.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"Since the task is not running any more, ds cannot be drivable any more. However to drive ds again, we need launch ds again.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Full-API","page":"DiscreteSystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"@def_discrete_system \nDiscreteSystem \nDiscreteLinearSystem \nHenonSystem \nLoziSystem \nBogdanovSystem \nGingerbreadmanSystem\nLogisticSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.@def_discrete_system","page":"DiscreteSystem","title":"Causal.@def_discrete_system","text":"@def_discrete_system ex\n\nwhere ex is the expression to define to define a new AbstractDiscreteSystem component type. The usage is as follows:\n\n@def_discrete_system mutable struct MyDiscreteSystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDiscreteSystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \nend\n\nHere, 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.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew discrete system must be a subtype of AbstractDiscreteSystem to function properly.\n\nExample\n\njulia> @def_discrete_system mutable struct MyDiscreteSystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n state::Vector{Float64} = [1.]\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \n end\n\njulia> ds = MyDiscreteSystem();\n\njulia> ds.input \n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.DiscreteSystem","page":"DiscreteSystem","title":"Causal.DiscreteSystem","text":"DiscreteSystem(; righthandside, readout, state, input, output)\n\nConstructs a generic discrete system \n\nExample\n\njulia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);\n\njulia> ofuncdiscrete(x, u, t) = x;\n\njulia> DiscreteSystem(righthandside=sfuncdiscrete, readout=ofuncdiscrete, state=[1.], input=nothing, output=Outport())\nDiscreteSystem(righthandside:sfuncdiscrete, readout:ofuncdiscrete, state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.DiscreteLinearSystem","page":"DiscreteSystem","title":"Causal.DiscreteLinearSystem","text":"DiscreteLinearSystem(input, output, modelargs=(), solverargs=(); \n A=fill(-1, 1, 1), B=fill(0, 1, 1), C=fill(1, 1, 1), D=fill(0, 1, 1), state=rand(size(A,1)), t=0., \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs 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.\n\nThe DiscreteLinearSystem is represented by the following state and output equations.\n\nbeginarrayl\n dotx = A x + B u 025cm\n y = C x + D u \nendarray\n\nwhere x is state. solver is used to solve the above differential equation.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.HenonSystem","page":"DiscreteSystem","title":"Causal.HenonSystem","text":"Henon()\n\nConstructs a Henon system evolving with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - alpha (x_1^2) + x_2 025cm\n dotx_2 = beta x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.LoziSystem","page":"DiscreteSystem","title":"Causal.LoziSystem","text":"LoziSystem()\n\nConstructs a Lozi system evolving with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - alpha x_1 + x_2 025cm\n dotx_2 = beta x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.BogdanovSystem","page":"DiscreteSystem","title":"Causal.BogdanovSystem","text":"BogdanovSystem()\n\nConstructs a Bogdanov system with equations\n\nbeginarrayl\n dotx_1 = x_1 + dotx_2 025cm\n dotx_2 = x_2 + epsilon + x_2 + k x_1 (x_1 - 1) + mu x_1 x_2\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.GingerbreadmanSystem","page":"DiscreteSystem","title":"Causal.GingerbreadmanSystem","text":"GingerbreadmanSystem()\n\nConstructs a GingerbreadmanSystem with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - x_2 + x_1025cm\n dotx_2 = x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Causal.LogisticSystem","page":"DiscreteSystem","title":"Causal.LogisticSystem","text":"LogisticSystem()\n\nConstructs a LogisticSystem with the dynamics \n\nbeginarrayl\n dotx = r x (1 - x)\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Buffer","page":"Buffer","title":"Buffer","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"A Buffer is a used to buffer the data flowing the connections of a model. Data can be read from and written into a buffer. The mode of the buffer determines the way to read from and write into the buffers. ","category":"page"},{"location":"manual/utilities/buffers/#Buffer-Modes","page":"Buffer","title":"Buffer Modes","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"BufferMode determines the way the data is read from and written into a Buffer. Basically, there are four buffer modes: Normal, Cyclic, Fifo and Lifo. Normal, Fifo and Lifo are subtypes of LinearMode and Cyclic is a subtype of CyclicMode.","category":"page"},{"location":"manual/utilities/buffers/#Buffer-Constructors","page":"Buffer","title":"Buffer Constructors","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"The Buffer construction is very similar to the construction of arrays in Julia. Just specify the mode, element type and length of the buffer. Here are some examples: ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Causal # hide \nBuffer{Fifo}(2, 5)\nBuffer{Cyclic}(2, 10)\nBuffer{Lifo}(Bool, 2, 5)\nBuffer(5)","category":"page"},{"location":"manual/utilities/buffers/#Writing-Data-into-Buffers","page":"Buffer","title":"Writing Data into Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Writing data into a Buffer is done with write! function. Recall that when the buffer is full, no more data can be written into the buffer if the buffer mode is of type LinearMode. ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Causal # hide\nnormalbuf = Buffer{Normal}(3)\nforeach(item -> write!(normalbuf, item), 1:3)\nnormalbuf\nwrite!(normalbuf, 4.)","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"This situation is the same for Lifo and Fifo buffers, but not the case for Cyclic buffer. ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Causal # hide\ncyclicbuf = Buffer{Cyclic}(3)\nforeach(item -> write!(cyclicbuf, item), 1:3)\ncyclicbuf\nwrite!(cyclicbuf, 3.)\nwrite!(cyclicbuf, 4.)","category":"page"},{"location":"manual/utilities/buffers/#Reading-Data-from-Buffers","page":"Buffer","title":"Reading Data from Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Reading data from a Buffer is done with read function.","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Causal # hide \nnbuf, cbuf, fbuf, lbuf = Buffer{Normal}(5), Buffer{Cyclic}(5), Buffer{Lifo}(5), Buffer{Fifo}(5)\nforeach(buf -> foreach(item -> write!(buf, item), 1 : 5), [nbuf, cbuf, fbuf, lbuf])\nfor buf in [nbuf, cbuf, fbuf, lbuf]\n @show buf \n for i in 1 : 5 \n @show read(buf)\n end\nend","category":"page"},{"location":"manual/utilities/buffers/#AbstractArray-Interface-of-Buffers","page":"Buffer","title":"AbstractArray Interface of Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"A Buffer can be indexed using the similar syntax of arrays in Julia. That is, getindex and setindex! methods can be used with known Julia syntax. i.e. getindex(buf, idx) is equal to buf[idx] and setindex(buf, val, idx) is equal to buf[idx] = val.","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Causal # hide\nbuf = Buffer(5)\nsize(buf)\nlength(buf)\nfor val in 1 : 5 \n write!(buf, 2val)\nend \nbuf[1]\nbuf[3:4]\nbuf[[3, 5]]\nbuf[end]\nbuf[1] = 5 \nbuf[3:5] = [7, 8, 9]","category":"page"},{"location":"manual/utilities/buffers/#Full-API","page":"Buffer","title":"Full API","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Modules = [Causal]\nPages = [\"buffer.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/utilities/buffers/#Causal.Buffer","page":"Buffer","title":"Causal.Buffer","text":"Buffer{M}(dtype::Type{T}, sz::Int...) where {M, T}\n\nConstructs a Buffer of size sz with element type of T. M is the mode of the Buffer that determines how data is to read from and written into the Buffer. There exists for different buffer modes: \n\nNormal: See Normal\nCyclic: See Cyclic\nLifo: See Lifo\nFifo: See Fifo\n\nThe default mode for Buffer is Cyclic and default element type is Float64.\n\nBuffer{M}(sz::Int...) where {M, T}\n\nConstructs a Buffer of size sz and with element type of T and mode M.\n\nBuffer(dtype::Type{T}, sz::Int...) where T\n\nConstructs a Buffer of size sz and element type T. The mode of buffer is Cyclic.\n\nBuffer(sz::Int...)\n\nConstructs a Buffer of size sz with mode Cyclic and element type of Float64.\n\nBuffer{M}(data::AbstractVecOrMat{T}) where {M, T<:Real}\n\nConstructs a Buffer with data.\n\nExample\n\njulia> buf = Buffer(5)\n5-element Buffer{Cyclic,Float64,1}\n\njulia> buf = Buffer{Fifo}(2, 5)\n2×5 Buffer{Fifo,Float64,2}\n\njulia> buf = Buffer{Lifo}(collect(reshape(1:8, 2, 4)))\n2×4 Buffer{Lifo,Int64,2}\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.BufferMode","page":"Buffer","title":"Causal.BufferMode","text":"BufferMode\n\nAbstract type for buffer mode. Subtypes of BufferMode is CyclicMode and LinearMode.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.Cyclic","page":"Buffer","title":"Causal.Cyclic","text":"Cyclic <: CyclicMode\n\nCyclic buffer mode. The data is written to buffer until the buffer is full. When the buffer is full, new data is written by overwriting the data available in the buffer starting from the beginning of the buffer. When the buffer is read, the element written last is returned and the returned element is not deleted from the buffer.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.CyclicMode","page":"Buffer","title":"Causal.CyclicMode","text":"CyclicMode <: BufferMode\n\nAbstract type of cyclic buffer modes. See Cyclic\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.Fifo","page":"Buffer","title":"Causal.Fifo","text":"Fifo <: LinearMode\n\nFifo (First-in-last-out) buffer mode. This type of buffer is a first-in-first-out buffer. The data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the first element written into the buffer is returned. The returned element is deleted from the buffer. \n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.Lifo","page":"Buffer","title":"Causal.Lifo","text":"Lifo <: LinearMode\n\nLifo (Last-in-first-out) buffer mode. This type of buffer is a last-in-first-out buffer. Data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the last element written into buffer is returned. The returned element is deleted from the buffer.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.LinearMode","page":"Buffer","title":"Causal.LinearMode","text":"LinearMode <: BufferMode\n\nAbstract type of linear buffer modes. See Normal, Lifo, Fifo\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Causal.Normal","page":"Buffer","title":"Causal.Normal","text":"Normal <: LinearMode\n\nLinearMode buffer mode. The data is written to buffer until the buffer is full. When it is full, no more data is written to the buffer. When read, the data written last is returned and the returned data is not deleted from the internal container of the buffer. \n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Base.getindex-Union{Tuple{N}, Tuple{Buffer,Vararg{Int64,N}}} where N","page":"Buffer","title":"Base.getindex","text":"getindex(buf::Buffer, idx::Vararg{Int, N})\n\nReturns an element from buf at index idx. Same as buf[idx]\n\nExample\n\njulia> buf = Buffer(2, 5); # Construct a buffer.\n\njulia> write!(buf, reshape(2 : 2 : 20, 2, 5)) # Write data into buffer.\n\njulia> buf[1]\n18.0\n\njulia> buf[1, 2]\n14.0\n\njulia> buf[1, end]\n2.0\n\njulia> buf[:, 2]\n2-element Array{Float64,1}:\n 14.0\n 16.0\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.isempty-Tuple{Buffer}","page":"Buffer","title":"Base.isempty","text":"isempty(buf::Buffer)\n\nReturns true if the index of buf is 1.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.read-Tuple{Buffer}","page":"Buffer","title":"Base.read","text":"read(buf::Buffer)\n\nReads an element from buf. Reading is performed according to the mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\nExample\n\njulia> buf = Buffer(3)\n3-element Buffer{Cyclic,Float64,1}\n\njulia> write!(buf, [2, 4, 6])\n\njulia> for i = 1 : 3 \n @show (read(buf), buf.internals)\n end\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n\njulia> buf = Buffer{Fifo}(5)\n5-element Buffer{Fifo,Float64,1}\n\njulia> write!(buf, [2, 4, 6])\n\njulia> for i = 1 : 3 \n @show (read(buf), buf.internals)\n end\n(read(buf), buf.internals) = (2.0, [[6.0, 4.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n(read(buf), buf.internals) = (4.0, [[6.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[0.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.setindex!-Union{Tuple{N}, Tuple{Buffer,Any,Vararg{Int64,N}}} where N","page":"Buffer","title":"Base.setindex!","text":"setindex!(buf::Buffer, val, idx)\n\nSets val to buf at index idx. Same as buf[idx] = val.\n\nExample\n\njulia> buf = Buffer(2, 5);\n\njulia> buf[1] = 1\n1\n\njulia> buf[:, 2] = [1, 1]\n2-element Array{Int64,1}:\n 1\n 1\n\njulia> buf[end] = 10\n10\n\njulia> buf.internals\n2-element Array{Array{Float64,2},1}:\n [1.0 1.0 … 0.0 0.0; 0.0 1.0 … 0.0 10.0]\n [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.size-Tuple{Buffer}","page":"Buffer","title":"Base.size","text":"size(buf::Buffer)\n\nReturns the size of buf.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.content-Tuple{Buffer}","page":"Buffer","title":"Causal.content","text":"content(buf, [flip=true])\n\nReturns the current data of buf. If flip is true, the data to be returned is flipped. See also snapshot\n\nExample\n\njulia> buf = Buffer(5);\n\njulia> write!(buf, 1:3)\n\njulia> content(buf, flip=false)\n3-element Array{Float64,1}:\n 3.0\n 2.0\n 1.0\n\njulia> buf = Buffer(2, 5);\n\njulia> write!(buf, reshape(1:10, 2, 5))\n\njulia> content(buf)\n2×5 Array{Float64,2}:\n 1.0 3.0 5.0 7.0 9.0\n 2.0 4.0 6.0 8.0 10.0\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.datalength-Union{Tuple{Buffer{M,T,N}}, Tuple{N}, Tuple{T}, Tuple{M}} where N where T where M","page":"Buffer","title":"Causal.datalength","text":"datalength(buf::Buffer)\n\nReturns the maximum number of data that can be hold in buf.\n\nExample\n\njulia> buf = Buffer(5);\n\njulia> datalength(buf)\n5\n\njulia> buf2 = Buffer(2, 10);\n\njulia> datalength(buf2)\n10\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.inbuf-Tuple{Buffer}","page":"Buffer","title":"Causal.inbuf","text":"inbuf(buf::Buffer)\n\nReturns the element of internals of buf that is used to input data to buf. See also [outbuf][@ref)\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.isfull-Tuple{Buffer}","page":"Buffer","title":"Causal.isfull","text":"isfull(buf::Buffer)\n\nReturns true if the index of buf is equal to the length of buf.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.ishit-Tuple{Buffer}","page":"Buffer","title":"Causal.ishit","text":"ishit(buf::Buffer)\n\nReturns true when buf index is an integer multiple of datalength of buf. \n\nExample\n\njulia> buf = Buffer(3);\n\njulia> for val in 1 : 7\n write!(buf, val)\n @show ishit(buf)\n end\nishit(buf) = false\nishit(buf) = false\nishit(buf) = true\nishit(buf) = false\nishit(buf) = false\nishit(buf) = true\nishit(buf) = false\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.mode-Union{Tuple{Buffer{M,T,N}}, Tuple{N}, Tuple{T}, Tuple{M}} where N where T where M","page":"Buffer","title":"Causal.mode","text":"mode(buf::Buffer)\n\nReturns buffer mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.outbuf-Tuple{Buffer}","page":"Buffer","title":"Causal.outbuf","text":"outbuf(buf::Buffer)\n\nReturns the element of intervals of buf that is used to take data out of buf. See also: inbuf\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.snapshot-Tuple{Buffer}","page":"Buffer","title":"Causal.snapshot","text":"snapshot(buf::Buffer)\n\nReturns all elements in buf. See also: content\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Causal.write!-Tuple{Buffer,Any}","page":"Buffer","title":"Causal.write!","text":"write!(buf::Buffer{M, <:Real, 1}, val::Real) where {M}\n\nWrites val into buf.\n\nwrite!(buf::Buffer{M, <:Real, 2}, val::AbstractVector{<:Real}) where {M}\n\nWrites val into buf.\n\nwrite!(buf::Buffer{M, <:Real, 1}, vals::AbstractVector{<:Real}) where {M}\n\nWrites each element of vals into buf.\n\nwrite!(buf::Buffer{M, <:Real, 2}, vals::AbstractMatrix{<:Real}) where {M}\n\nWrites each column of vals into buf.\n\nwarning: Warning\nBuffer mode determines how data is written into buffers. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\nExample\n\njulia> buf = Buffer(5)\n5-element Buffer{Cyclic,Float64,1}\n\njulia> write!(buf, 1.)\n1.0\n\njulia> write!(buf, [2, 3])\n\njulia> buf.internals\n2-element Array{Array{Float64,1},1}:\n [3.0, 2.0, 1.0, 0.0, 0.0]\n [2.0, 1.0, 0.0, 0.0, 0.0]\n\njulia> buf = Buffer(2,5)\n2×5 Buffer{Cyclic,Float64,2}\n\njulia> write!(buf, [1, 1])\n2-element Array{Int64,1}:\n 1\n 1\n\njulia> write!(buf, [2 3; 2 3])\n\njulia> buf.internals\n2-element Array{Array{Float64,2},1}:\n [3.0 2.0 … 0.0 0.0; 3.0 2.0 … 0.0 0.0]\n [2.0 1.0 … 0.0 0.0; 2.0 1.0 … 0.0 0.0]\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Clock","page":"Clock","title":"Clock","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Causal is a clocked simulation environment. That is, model components are evolved in different time intervals, called the sampling interval. During the simulation, model components are triggered by these generated time pulses. A Clock instance is used to to generate those time pulses. The simulation time settings–the simulation start time, stop time, sampling interval–are configured through the Clock.","category":"page"},{"location":"manual/components/sources/clock/#Construction-of-Clock","page":"Clock","title":"Construction of Clock","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Construction of Clock is done by specifying its start time and final time and the simulation sampling period. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Causal # hide \nClock(0., 1, 10.)\nClock{Int}(1, 1, 10)","category":"page"},{"location":"manual/components/sources/clock/#Basic-Usage-of-Clocks","page":"Clock","title":"Basic Usage of Clocks","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"A Clock has a Callback list so that a Callback can be constructed to trigger specific events configured with the time settings. See the following case study. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Let us consider a Clock with initial time of 0, sampling interval of 1 and final time of 10.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Causal # hide \nclk = Clock(0., 1., 10.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Notice that clk is not running, since it is not set. Now, let us set it","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"set!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"clk is ready to run, i.e., to be iterated. The following commands generated clock ticks and shows it on the console.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"for t in clk \n @show t \nend","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"At this point, clk is out of time. The current time of clk does not advance any more. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"take!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"But, clk can be reset again.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"set!(clk, 0., 1., 10.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Consider that we want to configure an alarm. For this, let us consider that when the time of clk is greater than 5 an alarm message is printed on the console. To this end, we need to construct a Callback and add it to the callbacks of clk. (When constructed callback list of clk is empty.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"condition(clk) = clk.t > 5\naction(clk) = println(\"Clock time = \", clk.t)\nclk = Clock(0., 1., 10., callbacks=Callback(condition=condition, action=action))\nset!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Now, let us run clk by iterating it. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"for t in clk \n @show t \nend ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Note that we, constructed a simple callback. It is of course possible to construct more complex callbacks.","category":"page"},{"location":"manual/components/sources/clock/#Usage-of-Clocks-with-ProgressMeter","page":"Clock","title":"Usage of Clocks with ProgressMeter","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"It also possible to iterate the Clocks by using a progress meter. See ProgressMeter for further information for progress meter.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Causal\nusing ProgressMeter\nclk = Clock(0., 0.01, 1.)\nset!(clk)\n@showprogress for t in clk \nend ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Note that clk is just iterated.","category":"page"},{"location":"manual/components/sources/clock/#Full-API","page":"Clock","title":"Full API","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Modules = [Causal]\nPages = [\"clock.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/components/sources/clock/#Causal.Clock","page":"Clock","title":"Causal.Clock","text":"Clock(t::Real, dt::Real, tf::Real)\n\nConstructs a Clock with starting time t, final time tf and sampling inteval dt. When iterated, the Clock returns its current time. \n\nwarning: Warning\nWhen constructed, Clock is not running. To take clock ticks from Clock, the Clock must be setted. See take!(clk::Clock) and set! \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/clock/#Base.iterate","page":"Clock","title":"Base.iterate","text":"iterate(clk::Clock[, t=clk.t)\n\nIterationk interface for clk. clk can be iterated in a loop.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.3);\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.3, paused:false, isrunning:true)\n\njulia> for t in clk \n @show t\n end\nt = 0.0\nt = 0.1\nt = 0.2\nt = 0.3\n\n\n\n\n\n","category":"function"},{"location":"manual/components/sources/clock/#Base.take!-Tuple{Clock}","page":"Clock","title":"Base.take!","text":"take!(clk::Clock)\n\nTakes a values from clk.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:true)\n\njulia> for i in 0 : 5\n @show take!(clk)\n end\ntake!(clk) = 0.0\ntake!(clk) = 0.1\ntake!(clk) = 0.2\ntake!(clk) = 0.3\ntake!(clk) = 0.4\ntake!(clk) = 0.5\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Causal.isoutoftime-Tuple{Clock}","page":"Clock","title":"Causal.isoutoftime","text":"isoutoftime(clk::Clock)\n\nReturns true if clk is out of time, i.e., the current time of clk exceeds its final time. \n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Causal.ispaused-Tuple{Clock}","page":"Clock","title":"Causal.ispaused","text":"ispaused(clk::Clock)\n\nReturns true if clk is paused. When paused, the currnent time of clk is not advanced. See also pause!(clk::Clock)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Causal.isrunning-Tuple{Clock}","page":"Clock","title":"Causal.isrunning","text":"isrunning(clk::Clock)\n\nReturns true if clk if clk is running.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Causal.pause!-Tuple{Clock}","page":"Clock","title":"Causal.pause!","text":"pause!(clk::Clock)\n\nPauses clk. When paused, the current time of clk does not advance.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5);\n\njulia> set!(clk);\n\njulia> for i = 1 : 5\n i > 3 && pause!(clk)\n @show take!(clk)\n end\ntake!(clk) = 0.0\ntake!(clk) = 0.1\ntake!(clk) = 0.2\n┌ Warning: Clock is paused.\n└ @ Causal ~/.julia/dev/Causal/src/components/sources/clock.jl:61\ntake!(clk) = 0.2\n┌ Warning: Clock is paused.\n└ @ Causal ~/.julia/dev/Causal/src/components/sources/clock.jl:61\ntake!(clk) = 0.2\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Causal.set!","page":"Clock","title":"Causal.set!","text":"set(clk::Clock, t::Real, dt::Real, tf::Real)\n\nSets clk for current clock time t, sampling time dt and final time tf. After the set, it is possible to take clock tick from clk. See also take!(clk::Clock)\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:true)\n\njulia> take!(clk)\n0.0\n\n\n\n\n\n","category":"function"},{"location":"manual/components/sources/clock/#Causal.stop!-Tuple{Clock}","page":"Clock","title":"Causal.stop!","text":"stop!(clk::Clock)\n\nUnsets clk. After the stpp, it is possible to take clock ticks from clk. See also take!(clk::Clock)\n\n\n\n\n\n","category":"method"},{"location":"modeling_and_simulation/simulation/#section","page":"Simulation","title":"Simulation","text":"","category":"section"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"A model to be simulated consists of components connected to each other and a time reference. The time reference is used to sample the continuous-time signals flowing through the connections of the model and to trigger the components. The simulation is performed by triggering the components with pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs, and writes them to their output ports.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"The simulation stages are shown in the flow chart in the figure above. Performing, inspecting, and reporting of all the stages of the simulation is carried out automatically without requiring any user intervention.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"In the first stage, the model is inspected to see if there are connections having any unconnected terminals. If a connection having an unconnected terminal is detected, the simulation is terminated at this stage. Another case where the model is not suitable for simulation is when algebraic loops exist. For example, almost every feedback system model includes algebraic loops. An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. The simulation does not continue because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Causal provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops. ","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"In case the inspection phase results positive, the putter and taker tasks are launched in order to ensure the data flow through the model connections. At this point, a putter and a taker task are bound to each connection. For example, in the figure below(on the left) is given an example model section consisting of components B1, B and the connections L1, L2, L3. When triggered, the B1 reads data from L1 calculates its output and writes to L2. Similarly, when triggered B2 reads data from the L2, calculates its output, and writes to the L3. The tasks that are bounded to L1, L2, and L3 corresponding to B1 and B2 are shown in the figure below(on the right). Since B1 reads the data from L1 and writes data to L2, a taker task is bounded to L1 and a putter task is bounded L2. Similarly, since B2 reads the data from L2 and writes data to L3, a taker task is bounded to L2 and a putter task is bounded L3. Since both a putter and a taker task are bound to the L2, data can flow from B1 to B2 through L2. A task manager is constructed to check whether the tasks launched during the initialization stage are active or not throughout the simulation and to report the error in case an error occurs.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"\n \n\n\n\n
\n
\n \"components\"\n
\n
\n \"tasks\"\n
\n
\n","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"The initialization stage is followed by the run the stage. The tasks that are launched corresponding to the components during the initialization stage expect the components to be triggered through their trigger pins. These triggers are generated in the sampling intervals of the simulation by the model clock during the run stage. It is possible to sample the signals of flowing through the connections at equal or independent time intervals. The generated triggers are put into the trigger pins of the components. The task corresponding to a triggered component is defined as reading data from the input of the component, calculating the output of the component, and writing to the output port. ","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"When the run stage is completed, the tasks launched at the initialization stage are closed and the simulation is ended.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"note: Note\nIn some simulation environments, a unified mathematical equation representing the model as a whole is obtained and solved in just a single shot for the entire simulation duration, even if the model is thought to consist of components]. In Causal, a model is, again, thought to consist of components, but is not represented by a unified mathematical equation. Instead, the model is evolved by evolving the components individually by solving their own mathematical equations. The components do not evolve in one shot, but instead, they evolve in parallel during the time intervals between subsequent sampling instants. Here, it worths noting that the type of the mathematical equations of the components of a model does not have to be the same. Thus, Causal allows the simulation of the models consisting of components represented by different types of mathematical equations.","category":"page"},{"location":"manual/components/sinks/writer/#Writer","page":"Writer","title":"Writer","text":"","category":"section"},{"location":"manual/components/sinks/writer/#Basic-Operation-of-Writers","page":"Writer","title":"Basic Operation of Writers","text":"","category":"section"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Having launched, a Writer is triggered through its trigger pin. When triggered, a Writer reads its input and then writes it to its internal buffer databuf. When databuf is full, the data in databuf is processed. Thus, the length of the data that is to be processed by the Writer is determined by the length of their internal buffer databuf. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us construct a Writer. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"using Causal # hide \nw = Writer(input=Inport(), buflen=5)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"The file of w is closed and the trigger pin of w is not writable. That is, it is not possible to trigger w from its trigger pin.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file \nw.trigger","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"To trigger w, we need to open and launch it, ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"oport, trg, hnd = Outport(), Outpin(), Inpin{Bool}()\nconnect!(oport, w.input)\nconnect!(trg, w.trigger)\nconnect!(w.handshake, hnd)\nopen(w)\nt = launch(w)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now, the internal file of w is opened in read/write mode and its trigger pin is writable. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file\nw.trigger.link","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us now trigger w. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"The input of w is now readable and handshake pin is not readable since w have not signaled that its triggering is succeeded yet. To do that, we need to put a value to the input of w","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(oport, [10.])","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now, w signalled that its step is succeeded. It read the data from its input and written it into is databuf. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"hnd.link\ntake!(hnd)\nw.databuf","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Since the databuf is not full nothing is written to the file of w. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us continue triggering w until the databuf of w is full.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"for t in 2. : 5.\n put!(trg, t)\n put!(oport, [t * 10])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now check that the content of the file of w.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Note that the content of databuf is written to the file of w. The operation of w can be terminated. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(trg, NaN)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"When terminated, the file of w is closed.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"note: Note\nIn this example, w does not have a plugin so nothing has been derived or computed from the data in databuf. The data in databuf is just written to file of w. To further data processing, see Plugins","category":"page"},{"location":"manual/components/sinks/writer/#Full-API","page":"Writer","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Writer \nwrite!(writer::Writer, td, xd)\nread(writer::Writer; flatten=true)\nfread \nmv(writer::Writer, dst; force::Bool=false)\ncp(writer::Writer, dst; force=false, follow_symlinks=false)\nopen(writer::Writer)\nclose(writer::Writer)","category":"page"},{"location":"manual/components/sinks/writer/#Causal.Writer","page":"Writer","title":"Causal.Writer","text":"Writer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol(uuid4()), \n path=joinpath(tempdir(), string(name)))\n\nConstructs a Writer whose input bus is input. buflen is the length of the internal buffer of Writer. If not nothing, plugin is used to processes the incomming data. path determines the path of the file of Writer.\n\nnote: Note\nThe type of file of Writer is JLD2. \n\nwarning: Warning\nWhen initialized, the file of Writer is closed. See open(writer::Writer) and close(writer::Writer).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/writer/#Causal.write!-Tuple{Writer,Any,Any}","page":"Writer","title":"Causal.write!","text":"write!(writer, td, xd)\n\nWrites xd corresponding to xd to the file of writer.\n\nExample\n\njulia> w = Writer(Inport(1))\nWriter(path:/tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2, nin:1)\n\njulia> open(w)\nWriter(path:/tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2, nin:1)\n\njulia> write!(w, 0., 10.)\n10.0\n\njulia> write!(w, 1., 20.)\n20.0\n\njulia> w.file\nJLDFile /tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2 (read/write)\n ├─🔢 0.0\n └─🔢 1.0\n\njulia> w.file[string(0.)]\n10.0\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.read-Tuple{Writer}","page":"Writer","title":"Base.read","text":"read(writer::Writer, flatten=false)\n\nRead the contents of the file of writer and returns the sorted content of the file. If flatten is true, the content is also flattened.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Causal.fread","page":"Writer","title":"Causal.fread","text":"fread(path::String)\n\nReads the content of jld2 file and returns the sorted file content. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/sinks/writer/#Base.Filesystem.mv-Tuple{Writer,Any}","page":"Writer","title":"Base.Filesystem.mv","text":"mv(writer::Writer, dst; force::Bool=false)\n\nMoves the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed.\n\nExample\n\njulia> mkdir(joinpath(tempdir(), \"testdir1\"))\n\"/tmp/testdir1\"\n\njulia> mkdir(joinpath(tempdir(), \"testdir2\"))\n\"/tmp/testdir2\"\n\njulia> w = Writer(Inport(), path=\"/tmp/testdir1/myfile.jld2\")\nWriter(path:/tmp/testdir1/myfile.jld2, nin:1)\n\njulia> mv(w, \"/tmp/testdir2\")\nWriter(path:/tmp/testdir2/myfile.jld2, nin:1)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.Filesystem.cp-Tuple{Writer,Any}","page":"Writer","title":"Base.Filesystem.cp","text":"cp(writer::Writer, dst; force=false, follow_symlinks=false)\n\nCopies the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed. If follow_symlinks is true, symbolinks are followed.\n\nExample\n\njulia> mkdir(joinpath(tempdir(), \"testdir1\"))\n\"/tmp/testdir1\"\n\njulia> mkdir(joinpath(tempdir(), \"testdir2\"))\n\"/tmp/testdir2\"\n\njulia> w = Writer(Inport(), path=\"/tmp/testdir1\")\nWriter(path:/tmp/testdir1.jld2, nin:1)\n\njulia> cp(w, \"/tmp/testdir2\")\nWriter(path:/tmp/testdir2/1e72bad1-9800-4ca0-bccd-702afe75e555, nin:1)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.open-Tuple{Writer}","page":"Writer","title":"Base.open","text":"open(writer::Writer)\n\nOpens writer by opening the its file in read/write mode. When writer is not openned, it is not possible to write data in writer. See also close(writer::Writer)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.close-Tuple{Writer}","page":"Writer","title":"Base.close","text":"close(writer::Writer)\n\nCloses writer by closing its file. When writer is closed, it is not possible to write data in writer. See also open(writer::Writer)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/staticsystems/subsystem/#Subsystem","page":"Subsystem","title":"Subsystem","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/#Construction-of-SubSystems","page":"Subsystem","title":"Construction of SubSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"A SubSystem consists of connected components. Thus, to construct a SubSystem, we first construct components, connect them and specify the input and output of SubSystem.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/#Basic-Operation-of-SubSystems","page":"Subsystem","title":"Basic Operation of SubSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"The operation of a SubSystem is very similar to that of a StaticSystem. The only difference is that when a SubSystem is triggered through its trigger pin, it distributes the trigger to the trigger pins of its components. Then, each of the components of the SubSystem takes steps individually.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Let us construct a subsystem consisting of a generator and an adder. ","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"using Causal # hide \ngen = ConstantGenerator()\nadder = Adder((+,+))","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Connect the generator and adder.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"connect!(gen.output, adder.input[1])","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"We are ready to construct a SubSystem.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub = SubSystem([gen, adder], [adder.input[2]], adder.output)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"To trigger the sub, we need to launch it. For that purpose, we construct ports and pins for input-output and signaling.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"oport, iport, trg, hnd = Outport(length(sub.input)), Inport(length(sub.output)), Outpin(), Inpin{Bool}()\nconnect!(oport, sub.input)\nconnect!(sub.output, iport)\nconnect!(trg, sub.trigger)\nconnect!(sub.handshake, hnd)\nt = launch(sub)\nt2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub is ready to be triggered,","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Put some data to the input of sub via oport (since oport is connected to sub.input)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"put!(oport, [1.])","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"The step needs to be approved.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Now print the data written to the outputs of the components of sub.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub.components[1].output[1].links[1].buffer[1]\nsub.components[2].output[1].links[1].buffer[1]","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Note that when sub is triggered, sub transfer the trigger to all its internal components.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Modules = [Causal]\nPages = [\"subsystem.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/model/#Model","page":"Model","title":"Model","text":"","category":"section"},{"location":"manual/models/model/#Signal-Flow-Approach-in-Modelling","page":"Model","title":"Signal-Flow Approach in Modelling","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Causal adopts signal-flow approach in systems modelling. In signal-flow approach, a Model consists of connected components. The components are data processing units and the behavior, i.e, the mathematical model, of the component determines how the data is processed. Connections connects the components each other and the data is transferred between components by means of connections. The data flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input bus. ","category":"page"},{"location":"manual/models/model/#Construction-of-Models","page":"Model","title":"Construction of Models","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"A Model consists of connected components. The components of are defined first and the Model consisting of these components can be constructed. Or, an empty model can be constructed. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Let us continue with some examples. We will construct very simple Model consisting of a SinewaveGenerator and a Writer. We construct an empty Model first, then we add nodes and branches as desired.","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"using Causal # hide \nmodel = Model() \naddnode!(model, SinewaveGenerator(), label=:gen)\naddnode!(model, Writer(Inport()), label=:writer)\naddbranch!(model, :gen => :writer, 1 => 1)","category":"page"},{"location":"manual/models/model/#Simulation-of-Models","page":"Model","title":"Simulation of Models","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"A Model to to be simulated consists of components connected to each other an a time reference.","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"model.nodes # Model components \nmodel.branches # Model components \nmodel.clock # Model time reference","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The time reference is used to sample the continuous time signals flowing through the busses of the model and to rigger the components. The simulation is performed by triggering the components with the pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs and writes them to their outputs.","category":"page"},{"location":"manual/models/model/#Simulation-Stages","page":"Model","title":"Simulation Stages","text":"","category":"section"},{"location":"manual/models/model/#Inspection","page":"Model","title":"Inspection","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The inspection stage is the first stage of the simulation process. In this stag,e the model is first inspected in terms of whether it is ready for simulation. This inspection is carried out to see whether the model has some inconsistencies such as unterminated busses or presence of algebraic loops. If the model has unterminated busses, the data that is supposed to flow those unterminated busses cannot flow through those busses and the simulation gets stuck. An algebraic is the subset of model components whose output depends directly on their inputs. In such a case, none of the components can produce outputs to break the loop which leads again the obstruction of simulation. Thus, to continue the simulation, the model must not contain any of those inconsistencies. The model inspection is done with inspect! function.","category":"page"},{"location":"manual/models/model/#Initialization","page":"Model","title":"Initialization","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"If the inspection stage results positive, the initialization stage comes next. In this stage, the tasks required for the busses of the model to be both readable and writable are activated and bound the busses. To this end, a reader and writer task are activated and bound to both sides of each bus. To initialize the model, initialize! function is used. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"When the model is initialized, the pairs of components and component tasks are recorded into the task manager of the model. During the rest of the simulation, task manager keeps track of the tasks. Any exception or error that is thrown during the run stage of the simulation can be observed by means of the task manager of the model.","category":"page"},{"location":"manual/models/model/#Run","page":"Model","title":"Run","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The run stage follows the initialization stage. The tasks activated in the initialization stage wait for the components to be triggered by the model time reference. During the run stage, time reference, that is the model clock, triggers the components by writing pulses that are generated in the intervals of the sampling period of the simulation to their trigger links. The job defined in a task is to read input dat a from the its input bus, to calculate its next state, if any, and output, and write its calculated output to its output bus. The run stage, starts at the initial time of the time reference and continues until the end time of the time reference. run! function is used to run the models, ","category":"page"},{"location":"manual/models/model/#Termination","page":"Model","title":"Termination","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"After the run stage, the tasks opened in the initialization stage are closed and the simulation is terminated. terminate! function is used to terminate the model ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Models are constructed to simulate! them. During the simulation, components of the Model process data and the data is transferred between the components via connection. Thus, to simulate the Models, the components must be connected. In our model, the writer is used to record the output of gen. Thus, the flows from gen to writer. Thus, we connect gen output to writer input. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"note: Note\nDuring the Model construction, the order of addition of nodes to the model is not important. The nodes can be given in any order.","category":"page"},{"location":"manual/models/model/#Full-API","page":"Model","title":"Full API","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Modules = [Causal]\nPages = [\"model.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/model/#Causal.Branch","page":"Model","title":"Causal.Branch","text":"Branch(nodepair, indexpair, links)\n\nConstructs a Branch connecting the first and second element of nodepair with links. indexpair determines the subindices by which the elements of nodepair are connected.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Causal.Model","page":"Model","title":"Causal.Model","text":"Model(components::AbstractVector)\n\nConstructs a Model whose with components components which are of type AbstractComponent.\n\nModel()\n\nConstructs a Model with empty components. After the construction, components can be added to Model.\n\nwarning: Warning\nModels are units that can be simulated. As the data flows through the branches i.e. input output busses of the components, its is important that the components must be connected to each other. See also: simulate!\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Causal.Node","page":"Model","title":"Causal.Node","text":"Node(component, idx, label)\n\nConstructs a model Node with component. idx is the index and label is label of Node.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Causal.addbranch!","page":"Model","title":"Causal.addbranch!","text":"addbranch!(model::Model, branch::Branch)\n\nAdds branch to branched of model.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Causal.addnode!-Tuple{Model,AbstractComponent}","page":"Model","title":"Causal.addnode!","text":"addnode!(model, component; label=nothing)\n\nAdds a node to model. Component is component and label is label the label of node. Returns added node.\n\nExample\n\njulia> model = Model()\nModel(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))\n\njulia> addnode!(model, SinewaveGenerator(), label=:gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.breakloop!","page":"Model","title":"Causal.breakloop!","text":"breakloop!(model, loop, breakpoint=length(loop))\n\nBreaks the algebraic loop of model. The loop of the model is broken by inserting a Memory at the breakpoint of loop.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Causal.deletebranch!-Tuple{Model,Pair{Int64,Int64}}","page":"Model","title":"Causal.deletebranch!","text":"deletebranch!(model::Model, branch::Branch)\n\nDeletes branch from branched of model.\n\ndeletebranch!(model::Model, srcnode::Node, dstnode::Node)\n\nDeletes branch between srcnode and dstnode of the model.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.getloops-Tuple{Model}","page":"Model","title":"Causal.getloops","text":"getloops(model)\n\nReturns idx of nodes that constructs algrebraic loops.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.getnode-Tuple{Model,Int64}","page":"Model","title":"Causal.getnode","text":"getnode(model, idx::Int)\n\nReturns node of model whose index is idx.\n\ngetnode(model, label)\n\nReturns node of model whose label is label.\n\nExample\n\njulia> model = Model()\nModel(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))\n\njulia> addnode!(model, SinewaveGenerator(), label=:gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\njulia> addnode!(model, Gain(), label=:gain)\nNode(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)\n\njulia> getnode(model, :gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\njulia> getnode(model, 2)\nNode(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.initialize!-Tuple{Model}","page":"Model","title":"Causal.initialize!","text":"initialize!(model::Model)\n\nInitializes model by launching component task for each of the component of model. The pairs component and component tasks are recordedin the task manager of the model. The model clock is set! and the files of Writer are openned.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.inspect!","page":"Model","title":"Causal.inspect!","text":"inspect!(model::Model)\n\nInspects the model. If model has some inconsistencies such as including algebraic loops or unterminated busses and error is thrown.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Causal.run!","page":"Model","title":"Causal.run!","text":"run!(model::Model, withbar::Bool=true)\n\nRuns the model by triggering the components of the model. This triggering is done by generating clock tick using the model clock model.clock. Triggering starts with initial time of model clock, goes on with a step size of the sampling period of the model clock, and finishes at the finishing time of the model clock. If withbar is true, a progress bar indicating the simulation status is displayed on the console.\n\nwarning: Warning\nThe model must first be initialized to be run. See also: initialize!.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Causal.signalflow-Tuple{Model,Vararg{Any,N} where N}","page":"Model","title":"Causal.signalflow","text":"signalflow(model, args...; kwargs...)\n\nPlots the signal flow of model. args and kwargs are passed into gplot function.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.simulate!-Tuple{Model,Real,Real,Real}","page":"Model","title":"Causal.simulate!","text":"simulate!(model::Model, t0::Real, dt::Real, tf::Real; kwargs...)\n\nSimulates the model starting from the initial time t0 until the final time tf with the sampling interval of tf. For kwargs are \n\nlogtofile::Bool: If true, a log file is contructed logging each step of the simulation. \nreportsim::Bool: If true, model components are written files after the simulation. When this file is read back, the model components can be consructed back with their status at the end of the simulation.\nsimdir::String: The path of the directory in which simulation file are recorded. \n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.simulate!-Tuple{Model}","page":"Model","title":"Causal.simulate!","text":"simulate!(model::Model; simdir::String=tempdir(), simprefix::String=\"Simulation-\", simname=string(uuid4()),\n logtofile::Bool=false, loglevel::LogLevel=Logging.Info, reportsim::Bool=false, withbar::Bool=true)\n\nSimulates model. simdir is the path of the directory into which simulation files are saved. simprefix is the prefix of the simulation name simname. If logtofile is true, a log file for the simulation is constructed. loglevel determines the logging level. If reportsim is true, model components are saved into files. If withbar is true, a progress bar indicating the simualation status is displayed on the console.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.terminate!-Tuple{Model}","page":"Model","title":"Causal.terminate!","text":"terminate!(model::Model)\n\nTerminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Causal.troubleshoot-Tuple{Model}","page":"Model","title":"Causal.troubleshoot","text":"troubleshoot(model)\n\nPrints the exceptions of the tasks that are failed during the simulation of model.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"@defmodel","category":"page"},{"location":"manual/models/model/#Causal.@defmodel","page":"Model","title":"Causal.@defmodel","text":"@defmodel name ex\n\nConstruts a model. The expected syntax is. \n\n @defmodel mymodel begin \n @nodes begin \n label1 = Component1()\n label2 = Component1()\n ⋮\n end\n @branches begin \n src1 => dst1 \n src2 => dst2 \n ⋮\n end\n end\n\nHere @nodes and @branches blocks adefine the nodes and branches of the model, respectively. \n\n\n\n\n\n","category":"macro"},{"location":"manual/components/componentsbase/interpolation/#Interpolation","page":"Interpolation","title":"Interpolation","text":"","category":"section"},{"location":"manual/components/componentsbase/interpolation/#Full-API","page":"Interpolation","title":"Full API","text":"","category":"section"},{"location":"manual/components/componentsbase/interpolation/","page":"Interpolation","title":"Interpolation","text":"Modules = [Causal]\nPages = [\"interpolant.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/components/componentsbase/interpolation/#Causal.Interpolant","page":"Interpolation","title":"Causal.Interpolant","text":"Interpolant(tinit, tfinal, coefinit, coeffinal)\n\nConstructs a linnear interpolant that interpolates between the poinsts (tinit, coefinit) and (tfinal, coeffinal).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/interpolation/#Causal.update!-Union{Tuple{Interpolant{T1,var\"#s25\",T2} where var\"#s25\"<:(AbstractArray{T,1} where T)}, Tuple{T2}, Tuple{T1}} where T2 where T1","page":"Interpolation","title":"Causal.update!","text":"update!(intepolant)\n\nUpdates interpolant using the data in timebuf and databuf of interpolant.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Ports","page":"Ports","title":"Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"A Port is actually is a bunch of pins (See Pins for mor information on pins.). As such, the connection, disconnection and data transfer are very similar to those of pins. Basically, there are two type of port: Outport and Inport. The data flows from outside of a component to its inside through an Inport while data flows from inside of the component to its outside through an Outport.","category":"page"},{"location":"manual/connections/port/#Construction-of-Ports","page":"Ports","title":"Construction of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"A port (both Inport and Outport) is constructed by specifying its element type T, the number of pins npins and the buffer length of its pins.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"using Causal # hide\nOutport{Bool}(5)\nOutport{Int}(2) \nOutport(3) \nOutport() \nInport{Bool}(5)\nInport{Int}(2) \nInport(3) \nInport() ","category":"page"},{"location":"manual/connections/port/#Connection-and-Disconnection-of-Ports","page":"Ports","title":"Connection and Disconnection of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The ports can be connected to and disconnected from each other. See the following example.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Let us construct and Outport and an Inport and connect them together.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op1 = Outport(2) \nip1 = Inport(2) \nls = connect!(op1, ip1)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Note that we connected all pins of op to ip. We cannot connect the ports partially. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op2, ip21, ip22 = Outport(5), Inport(2), Inport(3) \nls1 = connect!(op2[1:2], ip21)\nls2 = connect!(op2[3:5], ip22)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The connectedness of ports can be checked. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"isconnected(op2[1], ip21[1])\nisconnected(op2[1], ip21[2])\nisconnected(op2[1:2], ip21)\nisconnected(op2[3:5], ip22)\nisconnected(op2[5], ip22[3])","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Connected ports can be disconnected.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"disconnect!(op2[1], ip21[1])\ndisconnect!(op2[2], ip21[2])\ndisconnect!(op2[3:5], ip22)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Now check again the connectedness,","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"isconnected(op2[1], ip21[1])\nisconnected(op2[1], ip21[2])\nisconnected(op2[1:2], ip21)\nisconnected(op2[3:5], ip22)\nisconnected(op2[5], ip22[3])","category":"page"},{"location":"manual/connections/port/#Data-Flow-Through-Ports","page":"Ports","title":"Data Flow Through Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Data flow through the ports is very similar to the case in pins(see Data Flow Through Pins for information about data flow through pins). Running tasks must be bound to the links of pins of the ports for data flow through the ports.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Let us construct an Outport and an Inport, connect them together with links and perform data transfer from the Outport to the Inport through the links. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op3, ip3 = Outport(2), Inport(2)\nls = connect!(op3, ip3)\nt = @async while true\n val = take!(ip3)\n all(val .=== NaN) && break\n println(\"Took \" * string(val))\nend\nput!(op3, 1.);\nip3[1].link.buffer","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Note that the data flowing through the links are also written into the buffers of links.","category":"page"},{"location":"manual/connections/port/#Indexing-and-Iteration-of-Ports","page":"Ports","title":"Indexing and Iteration of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Ports can be indexed similarly to the arrays in Julia. When indexed, the corresponding pin of the port is returned.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op4 = Outport(3) \nop4[1]\nop4[end] \nop4[:]\nop4[1] = Outpin()\nop4[1:2] = [Outpin(), Outpin()]","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The iteration of Ports in a loop is also possible. When iterated, the pins of the Port is returned.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"ip5 = Inport(3)\nfor pin in ip5\n @show pin\nend","category":"page"},{"location":"manual/connections/port/#Full-API","page":"Ports","title":"Full API","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Modules = [Causal]\nPages = [\"port.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/port/#Causal.AbstractPort","page":"Ports","title":"Causal.AbstractPort","text":"AbstractPort{P}\n\nAbstract type of Outport and Inport. See also: Outport, Inport.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Causal.Inport","page":"Ports","title":"Causal.Inport","text":"Inport{T}(numpins=1)\n\nConstructs an Inport with numpins Inpin.\n\nwarning: Warning\nElement type of an Inport must be Inpin. See also Inpin\n\nExample\n\njulia> Inport{Int}(2)\n2-element Inport{Inpin{Int64}}:\n Inpin(eltype:Int64, isbound:false)\n Inpin(eltype:Int64, isbound:false)\n\njulia> Inport()\n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Causal.Outport","page":"Ports","title":"Causal.Outport","text":"Outport{T}(numpins=1)\n\nConstructs an Outport with numpins Outpin.\n\nwarning: Warning\nElement type of an Outport must be Outpin. See also Outpin\n\nExample\n\njulia> Outport{Int}(2)\n2-element Outport{Outpin{Int64}}:\n Outpin(eltype:Int64, isbound:false)\n Outpin(eltype:Int64, isbound:false)\n\njulia> Outport()\n1-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Base.getindex-Union{Tuple{N}, Tuple{AbstractPort,Vararg{Int64,N}}} where N","page":"Ports","title":"Base.getindex","text":"getindex(port::AbstractPort, idx::Vararg{Int, N}) where N\n\nReturns elements from port at index idx. Same as port[idx].\n\nExample\n\njulia> op = Outport(3)\n3-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\njulia> op[1]\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[end]\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[:]\n3-element Array{Outpin{Float64},1}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.put!-Tuple{Outport,Any}","page":"Ports","title":"Base.put!","text":"put!(outport::Outport, vals)\n\nPuts vals to outport. Each item in vals is putted to the links of the outport.\n\nwarning: Warning\nThe outport must be writable to be read. That is, there must be a runnable tasks bound to links of the outport that reads data from outport.\n\nExample\n\njulia> op, ip = Outport(), Inport() \n(Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))\n\njulia> ls = connect!(op, ip)\n1-element Array{Link{Float64},1}:\n Link(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> t = @async while true \n val = take!(ip)\n all(val .=== NaN) && break \n println(\"Took \" * string(val))\n end;\n\njulia> put!(op, [1.])\nTook [1.0]\n1-element Array{Float64,1}:\n 1.0\n\njulia> put!(op, [NaN])\n1-element Array{Float64,1}:\n NaN\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.setindex!-Union{Tuple{N}, Tuple{AbstractPort,Any,Vararg{Int64,N}}} where N","page":"Ports","title":"Base.setindex!","text":"setindex!(port::AbstractPort, item, idx::Vararg{Int, N}) where N\n\nSets item to port at index idx. Same as port[idx] = item.\n\nExample\n\njulia> op = Outport(3)\n3-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\njulia> op[1] = Outpin()\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[end] = Outpin()\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[1:2] = [Outpin(), Outpin()]\n2-element Array{Outpin{Float64},1}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.size-Tuple{AbstractPort}","page":"Ports","title":"Base.size","text":"size(port::AbstractPort)\n\nRetruns size of port.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.take!-Tuple{Inport}","page":"Ports","title":"Base.take!","text":"take!(inport::Inport)\n\nTakes an element from inport. Each link of the inport is a read and a vector containing the results is returned.\n\nwarning: Warning\nThe inport must be readable to be read. That is, there must be a runnable tasks bound to links of the inport that writes data to inport.\n\nExample\n\njulia> op, ip = Outport(), Inport()\n(Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))\n\njulia> ls = connect!(op, ip)\n1-element Array{Link{Float64},1}:\n Link(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> t = @async for val in 1 : 5 \n put!(op, [val])\n end;\n\njulia> take!(ip)\n1-element Array{Float64,1}:\n 1.0\n\njulia> take!(ip)\n1-element Array{Float64,1}:\n 2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Causal.datatype-Union{Tuple{AbstractPort{var\"#s25\"} where var\"#s25\"<:AbstractPin{T}}, Tuple{T}} where T","page":"Ports","title":"Causal.datatype","text":"datatype(port::AbstractPort)\n\nReturns the data type of port.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Causal.similar-Union{Tuple{Outport{P}}, Tuple{P}, Tuple{T}, Tuple{Outport{P},Int64}} where P<:Outpin{T} where T","page":"Ports","title":"Causal.similar","text":"similar(port, numpins::Int=length(outport)) where {P<:Outpin{T}} where {T}\n\nReturns a new port that is similar to port with the same element type. The number of links in the new port is nlinks and data buffer length is ln.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/staticsystems/staticsystems/#StaticSystems","page":"StaticSystems","title":"StaticSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/#Basic-Operation-of-StaticSystems","page":"StaticSystems","title":"Basic Operation of StaticSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"A static system is a system whose output y at time t depends on the current time t and the value of its input u. The input-output relation of a static systems is represented by its output function outputfunc which is of the form ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":" y = g(u t)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"where g is the output function outputfunc. Note that outputfunc is expected to have two inputs, the value u of the input and the current time t. The simulation in Causal is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t. Therefore, for example, the system modeled by","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"y(t) = g(u(t)t)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"is actually sampled at clock ticks t which is generated by a Clock. Therefore the sampled system corresponds to","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"yk = g(u_k t_k)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"where k is k_i T_s where k_i is an integer number, T_s is the sampling interval. T_s corresponds to sampling time dt of Clock. Thus, the system given above is coded like ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"function g(u, t)\n # Define the relation `y = g(u, t)`\nend","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"For further clarity, let us continue with a case study. Consider the following static system,","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":" y(t) = g(u(t) t) = left\n beginarrayl\n t u_1(t) \n sin(u_1(t)) \n cos(u_2(t))\n endarray\n right","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note that the number of inputs is 2 and the number of outputs of is 3. To define such a system, the output function is written as","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"using Causal # hide\ng(u, t) = [t * u[1], sin(u[1]), cos(u[2])]","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note that the function g is defined in such a way that the input value u is sampled, which implies u is not a vector of function but is a vector of real. Having defined output function outputfunc, the system can be constructed. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss = StaticSystem(readout=g, input=Inport(2), output=Outport(3))","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note the construction of input bus Inport(2) and output bus Outport(3) by recalling that the number of input is 2 and the number of output is 3.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"A StaticSystem evolves by being triggered through its trigger pin. When triggered from its trigger pin, a StaticSystem reads the current time t from its trigger pin and computes its output y according to its output function outputfunc and writes its output y(t) to its output port (if output port exists since output port may be nothing depending on the relation defined by outputfunc). When constructed, a StaticSystem is not ready to be triggered since its trigger pin is not writeable. To make ss drivable, we need to construct the ports and pins for input-output and signaling. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"oport, iport, trg, hnd = Outport(length(ss.input)), Inport(length(ss.output)), Outpin(), Inpin{Bool}()\nconnect!(oport, ss.input) \nconnect!(ss.output, iport) \nconnect!(trg, ss.trigger)\nconnect!(ss.handshake, hnd)\ntask = launch(ss)\ntaskout = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Now, ss is drivable from its trg pin. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss.trigger.link","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Now let us drive ss.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"As this point ss wait for its to be written. Let us write some data to oport.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"put!(oport, [10., 10.])","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss read the value u of its input(since ss.input is connected to oport), read the current time t, and computed its output value y and wrote it its output port. To signal that it succeeded to be take the step, it put a true to its handshake which needs to be taken.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"hnd.link\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"We can see the current data in the output of ss through iport (since iport is connected to ss.output)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Let us further drive ss.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"for t in 2. : 10.\n put!(trg, t)\n put!(oport, [10 * t, 20 * t])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"The data written to the output of ss is also written to the internal buffers of output.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"In addition to the generic StaticSystem, Causal provides some well-known static systems given in the next section.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/#Full-API","page":"StaticSystems","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"@def_static_system \nStaticSystem \nAdder \nMultiplier \nGain \nTerminator \nMemory \nCoupler \nDifferentiator ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.@def_static_system","page":"StaticSystems","title":"Causal.@def_static_system","text":"@def_static_system ex\n\nwhere ex is the expression to define to define a new AbstractStaticSystem component type. The usage is as follows:\n\n@def_source struct MyStaticSystem{T1,T2,T3,...,TN,OP, RO} <: AbstractStaticSystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \n readout::RO = readout_function # mandatory field\nend\n\nHere, MyStaticSystem has N parameters, an output port, an input port and a readout function.\n\nwarning: Warning\ninput, output and readout are mandatory fields to define a new static system. The rest of the fields are the parameters of the system.\n\nwarning: Warning\nreadout must be a two-argument function, i.e. a function of time t and input value u.\n\nwarning: Warning\nNew static system must be a subtype of AbstractStaticSystem to function properly.\n\nExample\n\njulia> @def_static_system struct MyStaticSystem{IP, OP, RO} <: AbstractStaticSystem \n α::Float64 = 1. \n β::Float64 = 2. \n input::IP = Inport() \n output::OP = Outport() \n readout::RO = (t,u) -> α * u[1] + β * u[2]\n end\n\njulia> sys = MyStaticSystem(); \n\njulia> sys.α\n1.0\n\njulia> sys.input\n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.StaticSystem","page":"StaticSystems","title":"Causal.StaticSystem","text":"StaticSystem(; readout, input, output)\n\nConsructs a generic static system with readout function, input port and output port.\n\nExample\n\njulia> ss = StaticSystem(readout = (t,u) -> u[1] + u[2], input=Inport(2), output=Outport(1));\n\njulia> ss.readout(0., ones(2))\n2.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Adder","page":"StaticSystems","title":"Causal.Adder","text":"Adder(signs=(+,+))\n\nConstruts an Adder with input bus input and signs signs. signs is a tuplle of + and/or -. The output function g of Adder is of the form,\n\n y = g(u t) = sum_j = 1^n s_k u_k\n\nwhere n is the length of the input, s_k is the kth element of signs, u_k is the kth value of input and y is the value of output. The default value of signs is all +.\n\nExample\n\njulia> adder = Adder(signs=(+, +, -));\n\njulia> adder.readout([3, 4, 5], 0.) == 3 + 4 - 5\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Multiplier","page":"StaticSystems","title":"Causal.Multiplier","text":"Multiplier(ops=(*,*))\n\nConstruts an Multiplier with input bus input and signs signs. signs is a tuplle of * and/or /. The output function g of Multiplier is of the form,\n\n y = g(u t) = prod_j = 1^n s_k u_k\n\nwhere n is the length of the input, s_k is the kth element of signs, u_k is the kth value of input and y is the value of the output. The default value of signs is all *.\n\nExample\n\njulia> mlt = Multiplier(ops=(*, *, /));\n\njulia> mlt.readout([3, 4, 5], 0.) == 3 * 4 / 5\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Gain","page":"StaticSystems","title":"Causal.Gain","text":"Gain(input; gain=1.)\n\nConstructs a Gain whose output function g is of the form \n\n y = g(u t) = K u\n\nwhere K is gain, u is the value of input and y is the value of output.\n\nExample\n\njulia> K = [1. 2.; 3. 4.];\n\njulia> sfunc = Gain(input=Inport(2), gain=K);\n\njulia> sfunc.readout([1., 2.], 0.) == K * [1., 2.]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Terminator","page":"StaticSystems","title":"Causal.Terminator","text":"Terminator(input::Inport)\n\nConstructs a Terminator with input bus input. The output function g is eqaul to nothing. A Terminator is used just to sink the incomming data flowing from its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Memory","page":"StaticSystems","title":"Causal.Memory","text":"Memory(delay=1.; initial::AbstractVector{T}=zeros(1), numtaps::Int=5, t0=0., dt=0.01, callbacks=nothing, \n name=Symbol()) where T\n\nConstructs a 'Memorywith input businput. A 'Memory delays the values of input by an amount of numdelay. initial determines the transient output from the Memory, that is, until the internal buffer of Memory is full, the values from initial is returned.\n\nExample\n\njulia> Memory(delay=0.1)\nMemory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))\n\njulia> Memory(delay=0.1, numtaps=5)\nMemory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Coupler","page":"StaticSystems","title":"Causal.Coupler","text":"Coupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)\n\nConstructs a coupler from connection matrix conmat of size n times n and coupling matrix cplmat of size d times d. The output function g of Coupler is of the form \n\n y = g(u t) = (E otimes P) u\n\nwhere otimes is the Kronecker product, E is conmat and P is cplmat, u is the value of input and y is the value of output.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Causal.Differentiator","page":"StaticSystems","title":"Causal.Differentiator","text":"Differentiator(kd=1; callbacks=nothing, name=Symbol())\n\nConsructs a Differentiator whose input output relation is of the form \n\n y(t) = k_d dotu(t)\n\nwhere u(t) is the input and y(t) is the output and kd is the differentiation constant.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/model_construction/#page_header","page":"Model Construction","title":"Model Construction","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"This tutorial illustrates model construction and the relation between models and graphs. A model consists of components and connections. These components and connections can be associated with a signal-flow graph signifying the topology of the model. In the realm of graph theory, components and connections of a model are associated with nodes and branches of the signal-flow graph. As the model is modified by adding or deleting components or connections, the signal-flow graph of the model is modified accordingly to keep track of topological modifications. By associating a signal-flow graph to a model, any graph-theoretical analysis can be performed. An example to such an analysis is the determination and braking of algebraic loops. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"In Causal, a model can be constructed either by describing it in one-shot or by gradually modifying it by adding new nodes and branches. To show the relation between models and graphs, we start with the latter.","category":"page"},{"location":"tutorials/model_construction/#section_header","page":"Model Construction","title":"Modifying Models","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"In this tutorial, we construct the model with the following block diagram","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"and with the following signal-flow graph ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Let's start with an empty Model.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using Causal # hide \nmodel = Model()","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"We constructed an empty model, i.e., the model has no components and connections. To modify the model, we need to add components and connections to the model. As the model is grown by adding components and connections, the components and connections are added into the model as nodes and branches (see Node, Branch). Let's add our first component, a SinewaveGenerator to the model.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, SinewaveGenerator(), label=:gen)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"To add components to the model, we use addnode! function. As seen, our node consists of a component, an index, and a label. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"node1 = model.nodes[1]\nnode1.component\nnode1.idx \nnode1.label ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Let us add another component, a Adder, to the model, ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, Adder(signs=(+,-)), label=:adder)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"and investigate our new node.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"node2 = model.nodes[2] \nnode2.component \nnode2.idx\nnode2.label","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note that as new nodes are added to the model, they are given an index idx and a label label. The label is not mandatory, if not specified explicitly, nothing is assigned as label. The reason to add components as nodes is to access them through their node index idx or labels. For instance, we can access our first node by using its node index idx or node label label. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"getnode(model, :gen) # Access by label\ngetnode(model, 1) # Access by index","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"At this point, we have two nodes in our model. Let's add two more nodes, a Gain and a Writer","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, Gain(), label=:gain)\naddnode!(model, Writer(), label=:writer)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"As the nodes are added to the model, its graph is modified accordingly.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model.graph","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model has no connections. Let's add our first connection by connecting the first pin of the output port of the node 1 (which is labelled as :gen) to the first input pin of input port of node 2 (which is labelled as :adder). ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addbranch!(model, :gen => :adder, 1 => 1)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The node labelled with :gen has an output port having one pin, and the node labelled with :adder has an input port of two pins. In our first connection, we connected the first(and the only) pin of the output port of the node labelled with :gen to the first pin of the input port of the node labelled with :adder. The connections are added to model as branches, ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model.branches","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"A branch between any pair of nodes can be accessed through the indexes or labels of nodes. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"br = getbranch(model, :gen => :adder)\nbr.nodepair \nbr.indexpair \nbr.links","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note the branch br has one link(see Link). This is because we connected one pin to another pin. The branch that connects n pins to each other has n links. Let us complete the construction of the model by adding other connections. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addbranch!(model, :adder => :gain, 1 => 1)\naddbranch!(model, :gain => :adder, 1 => 2)\naddbranch!(model, :gain => :writer, 1 => 1)","category":"page"},{"location":"tutorials/model_construction/#Describing-Models","page":"Model Construction","title":"Describing Models","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The second approach is to describe the whole model. In this approach the model is constructed in single-shot. The syntax here is ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"@defmodel modelname begin \n @nodes begin \n label1 = Component1(args...; kwargs...) # Node 1\n label2 = Component2(args...; kwargs...) # Node 2\n ⋮ ⋮\n \n labelN = ComponentN(args...; kwargs...) # Node N\n end \n @branches begin \n src_label1[src_index1] = dst_label1[dst_index1] # Branch 1\n src_label2[src_index2] = dst_label1[dst_index2] # Branch 2 \n ⋮ ⋮\n src_labelM[src_indexM] = dst_labelM[dst_indexM] # Branch M\n end\nend ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note that modelname is the name of the model to be compiled. The nodes of the model is defined in @nodes begin ... end block and the branches of the model is defined in @branches begin ... end. The syntax src_label1[src_index1] = dst_label1[dst_index1] means that there is a branch between the node labelled with src_label1 and the node labelled with dst_label1.And, this branch connects the pins indexed by src_index1 of the output port of src_label1 to the pins indexed by dst_index1 of the input port of dst_label1. The indexing of the pins here is just like any one dimensional array indexing. That is src_index1( or dst_index1) may be integer, vector of integers, vector of booleans, range, etc.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For example, the model given above can also be constructed as follows ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using Causal # hide \n\n@defmodel model begin \n @nodes begin \n gen = SinewaveGenerator() \n adder = Adder(signs=(+,-))\n gain = Gain() \n writer = Writer() \n end \n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => adder[2]\n gain[1] => writer[1]\n end\nend","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"This macro is expanded to construct the model.","category":"page"},{"location":"tutorials/model_construction/#Usage-of-Signal-Flow-Graph","page":"Model Construction","title":"Usage of Signal-Flow Graph","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The signal-flow graph constructed alongside of the construction of the model can be used to perform any topological analysis. An example to such an analysis is the detection of algebraic loops. For instance, our model in this tutorial has an algebraic loop consisting of the nodes labelled with :gen and gain. This loop can be detected using the signal-flow graph of the node ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"loops = getloops(model)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"We have one loop consisting the nodes with indexes 2 and 3. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For further analysis on model graph, we use LightGraphs package.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using LightGraphs \ngraph = model.graph ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For example, the adjacency matrix of model graph can be obtained. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"adjacency_matrix(model.graph)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"or inneighbors or outneighbors of a node can be obtained.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"inneighbors(model.graph, getnode(model, :adder).idx)\noutneighbors(model.graph, getnode(model, :adder).idx)","category":"page"},{"location":"manual/components/systems/dynamicsystems/daesystem/#DAESystem","page":"DAESystem","title":"DAESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Full-API","page":"DAESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/daesystem/","page":"DAESystem","title":"DAESystem","text":"@def_dae_system \nDAESystem \nRobertsonSystem \nPendulumSystem\nRLCSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Causal.@def_dae_system","page":"DAESystem","title":"Causal.@def_dae_system","text":"@def_dae_system ex\n\nwhere ex is the expression to define to define a new AbstractDAESystem component type. The usage is as follows:\n\n@def_dae_system mutable struct MyDAESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDAESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n stateder::ST = stateder_default # mandatory field\n diffvars::Vector{Bool} = diffvars_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MyDAESystem has N parameters. MyDAESystem is represented by the righthandside and readout function. state, 'stateder,diffvars,inputandoutputis the initial state, initial value of differential variables, vector signifing differetial variables, input port and output port ofMyDAESystem`.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(out, dx, x, u, t, args...; kwargs...)\n out .= .... # update out\nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew DAE system must be a subtype of AbstractDAESystem to function properly.\n\nExample\n\njulia> @def_dae_system mutable struct MyDAESystem{RH, RO, ST, IP, OP} <: AbstractDAESystem\n righthandside::RH = function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end \n readout::RO = (x,u,t) -> x \n state::ST = [1., -1]\n stateder::ST = [2., 0]\n diffvars::Vector{Bool} = [true, false]\n input::IP = nothing \n output::OP = Outport(1)\n end\n\njulia> ds = MyDAESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Causal.DAESystem","page":"DAESystem","title":"Causal.DAESystem","text":"DAESystem(; righthandside, readout, state, stateder, diffvars, input, output)\n\nConstructs a generic DAE system.\n\nExample\n\njulia> function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end;\n\njulia> ofuncdae(x, u, t) = x;\n\njulia> x0 = [1., -1];\n\njulia> dx0 = [2., 0.];\n\njulia> DAESystem(righthandside=sfuncdae, readout=ofuncdae, state=x0, input=nothing, output=Outport(1), diffvars=[true, false], stateder=dx0)\nDAESystem(righthandside:sfuncdae, readout:ofuncdae, state:[1.0, -1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Causal.RobertsonSystem","page":"DAESystem","title":"Causal.RobertsonSystem","text":"RobertsonSystem()\n\nConstructs a Robertson systme with the dynamcis \n\nbeginarrayl\n dotx_1 = -k_1 x_1 + k_3 x_2 x_3 025cm\n dotx_2 = k_1 x_1 - k_2 x_2^2 - k_3 x_2 x_3 025cm\n 1 = x_1 + x_2 + x_3 \nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Causal.PendulumSystem","page":"DAESystem","title":"Causal.PendulumSystem","text":"PendulumSystem()\n\nConstructs a Pendulum systme with the dynamics\n\nbeginarrayl\n dotx_1 = x_3 025cm\n dotx_2 = x_4 025cm\n dotx_3 = -dfracFm l x_1 025cm\n dotx_4 = g dfracFl x_2 025cm\n 0 = x_1^2 + x_2^2 - l^2 \nendarray\n\nwhere F is the external force, l is the length, m is the mass and g is the accelaration of gravity.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Causal.RLCSystem","page":"DAESystem","title":"Causal.RLCSystem","text":"RLCSystem()\n\nConstrusts a RLC system with the dynamics\n\nbeginarrayl\n dotx_1 = x_3 025cm\n dotx_2 = x_4 025cm\n dotx_3 = -dfracFm l x_1 025cm\n dotx_4 = g dfracFl x_2 025cm\n 0 = x_1^2 + x_2^2 - l^2 \nendarray\n\nwhere F is the external force, l is the length, m is the mass and g is the accelaration of gravity.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/model_simulation/#Construction-and-Simulation-of-a-Simple-Model","page":"Model Simulation","title":"Construction and Simulation of a Simple Model","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_simulation/#Model-Simulation","page":"Model Simulation","title":"Model Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"Let us construct the model first. See Model Construction for more detailed information about model construction.","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using Causal \n\n# Describe the model \n@defmodel model begin \n @nodes begin \n gen = SinewaveGenerator() \n writer = Writer() \n end \n @branches begin \n gen => writer\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"In this simple model, we have a single output sinusoidal wave generator gen and a writer. In the script above, we constructed the components, connected them together and constructed the model.","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"We can specify simulation settings such as whether a simulation log file is be to constructed, model components are to be saved in a file, etc. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"simdir = \"/tmp\" \nlogtofile = true\nreportsim = true\nnothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"At this point, the model is ready for simulation. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"t0 = 0. # Start time \ndt = 0.01 # Sampling interval\ntf = 10. # Final time\nsim = simulate!(model, t0, dt, tf, simdir=simdir, logtofile=logtofile, reportsim=reportsim)","category":"page"},{"location":"tutorials/model_simulation/#Investigation-of-Simulation","page":"Model Simulation","title":"Investigation of Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"foreach(println, readlines(`ls -al $(sim.path)`))","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"The simulation directory includes a log file simlog.log which helps the user monitor simulation steps. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"# Print the contents of log file \nopen(joinpath(sim.path, \"simlog.log\"), \"r\") do file \n for line in readlines(file)\n println(line)\n end\nend","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"report.jld2 file, which includes the information about the simulation and model components, can be read back after the simulation. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using FileIO, JLD2 \nfilecontent = load(joinpath(sim.path, \"report.jld2\"))\nclock = filecontent[\"model/clock\"]","category":"page"},{"location":"tutorials/model_simulation/#Analysis-of-Simulation-Data","page":"Model Simulation","title":"Analysis of Simulation Data","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"After the simulation, the data saved in simulation data files, i.e. in the files of writers, can be read back any offline data analysis can be performed. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"# Read the simulation data\nt, x = read(getnode(model, :writer).component) \n\n# Plot the data\nusing Plots\nplot(t, x, xlabel=\"t\", ylabel=\"x\", label=\"\")\nsavefig(\"simple_model_plot.svg\"); nothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"(Image: )","category":"page"},{"location":"tutorials/model_simulation/#A-Larger-Model-Simulation","page":"Model Simulation","title":"A Larger Model Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"Consider a larger model whose block diagram is given below","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"The script below illustrates the construction and simulation of this model ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using Causal \nusing Plots\n\n# Construct the model \n@defmodel model begin \n @nodes begin \n gen1 = SinewaveGenerator(frequency=2.)\n gain1 = Gain()\n adder1 = Adder(signs=(+,+))\n gen2 = SinewaveGenerator(frequency=3.)\n adder2 = Adder(signs=(+,+,-))\n gain2 = Gain()\n writer = Writer() \n gain3 = Gain()\n end \n @branches begin \n gen1[1] => gain1[1] \n gain1[1] => adder1[1]\n adder1[1] => adder2[1]\n gen2[1] => adder1[2]\n gen2[1] => adder2[2]\n adder2[1] => gain2[1]\n gain2[1] => writer[1]\n gain2[1] => gain3[1]\n gain3[1] => adder2[3]\n end\nend\n\n# Simulation of the model \nsimulate!(model, withbar=false)\n\n# Reading and plotting the simulation data\nt, x = read(getnode(model, :writer).component)\nplot(t, x)\nsavefig(\"larger_model_plot.svg\"); nothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"(Image: )","category":"page"},{"location":"#Causal","page":"Home","title":"Causal","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Causal enables fast and effective systems simulations together with online and offline data analysis. In Causal, it is possible to simulate discrete-time and continuous-time, static or dynamical systems. In particular, it is possible to simulate dynamical systems modeled by different types of differential equations such as ODE (Ordinary Differential Equation), Random Ordinary Differential Equation (RODE), SDE (Stochastic Differential Equation), DDE (Delay Differential Equation) and DAE (Differential Algebraic Equation), and discrete difference equations. During the simulation, the data flowing through the links of the model can be processed online and offline and specialized analyzes can be performed. These analyses can also be enriched with plugins that can easily be defined using the standard Julia library or various Julia packages. The simulation is performed by evolving the components individually and in parallel during sampling time intervals. The individual evolution of the components allows the simulation of the models that include components represented by different kinds of mathematical equations.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Installation of Causal is the similar to any other registered Julia package. Start a Julia session and type ","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add Causal","category":"page"}] -======= -[{"location":"tutorials/coupled_systems/#Coupled-Systems","page":"Coupled Systems","title":"Coupled Systems","text":"","category":"section"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"Consider two coupled LorenzSystems. The first system evolves by","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"beginarrayl\n dotx_11 = sigma (x_12 - x_11) + epsilon (x_21 - x_11) 025cm\n dotx_12 = x_11 (rho - x_13) - x_12 025cm\n dotx_13 = x_11 x_12 - beta x_13\nendarray","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"and the second one evolves by","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"beginarrayl\n dotx_21 = sigma (x_22 - x_21) + epsilon (x_11 - x_21) 025cm\n dotx_22 = x_21 (rho - x_23) - x_22 025cm\n dotx_23 = x_21 x_22 - beta x_23 \nendarray","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"where x_1 = x_11 x_12 x_13, x_2 = x_21 x_22 x_23 are the state vectors of the first and second system, respectively. The coupled system can be written more compactly as, ","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"beginarrayl\n dotX = F(X) + epsilon (A P) X \nendarray","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"where X = x_1 x_2, F(X) = f(x_1) f(x_2),","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":" A = beginbmatrix\n -1 1 \n 1 -1 \n endbmatrix","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":" P = beginbmatrix\n 1 0 0 \n 0 0 0 \n 0 0 0 \n endbmatrix","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"and f is the Lorenz dynamics given by ","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"beginarrayl\n dotx_1 = sigma (x_2 - x_1) 025cm\n dotx_2 = x_1 (rho - x_3) - x_2 025cm\n dotx_3 = x_1 x_2 - beta x_3\nendarray","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"The script below constructs and simulates the model","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"using Jusdl \n\n# Describe the model\nε = 10.\n@defmodel model begin \n @nodes begin\n ds1 = ForcedLorenzSystem()\n ds2 = ForcedLorenzSystem()\n coupler = Coupler(conmat=ε*[-1 1; 1 -1], cplmat=[1 0 0; 0 0 0; 0 0 0])\n writer = Writer(input=Inport(6))\n end\n @branches begin \n ds1[1:3] => coupler[1:3]\n ds2[1:3] => coupler[4:6]\n coupler[1:3] => ds1[1:3]\n coupler[4:6] => ds2[1:3]\n ds1[1:3] => writer[1:3]\n ds2[1:3] => writer[4:6]\n end\nend\nnothing # hide ","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"To construct the model, we added ds1 and ds2 each of which has input ports of length 3 and output port of length 3. To couple them together, we constructed a coupler which has input port of length 6 and output port of length 6. The output port of ds1 is connected to the first 3 pins of coupler input port, and the output of ds2 is connected to last 3 pins of coupler input port. Then, the first 3 pins of coupler output is connected to the input port of ds1 and last 3 pins of coupler output is connected to the input port of ds2. The block diagram of the model is given below.","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"The the signal-flow graph of the model has 4 directed branches and each of these branches has 3 links. ","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"It also worths pointing out that the model has two algebraic loops. The first loop consists of ds1 and coupler, and the second loop consists of ds2 and coupler. During the simulation these loops are broken automatically without requiring any user intervention.","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"The model is ready for simulation. The code block below simulates the model and plots the simulation data.","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"using Plots\n\n# Simulation settings.\nti, dt, tf = 0, 0.01, 100.\n\n# Simulate the model \nsimulate!(model, ti, dt, tf, withbar=false)\n\n# Read simulation data \nt, x = read(getnode(model, :writer).component)\n\n# Compute errors\nerr = x[:, 1] - x[:, 4]\n\n# Plot the results.\np1 = plot(x[:, 1], x[:, 2], label=\"ds1\")\np2 = plot(x[:, 4], x[:, 5], label=\"ds2\")\np3 = plot(t, err, label=\"err\")\nplot(p1, p2, p3, layout=(3, 1))\nsavefig(\"coupled_systems_plot.svg\"); nothing # hide","category":"page"},{"location":"tutorials/coupled_systems/","page":"Coupled Systems","title":"Coupled Systems","text":"(Image: )","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#RODESystem","page":"RODESystem","title":"RODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Construction-of-RODESystem","page":"RODESystem","title":"Construction of RODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"A RODESystem is represented by the state function ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"beginarrayl\n dx = f(x u t W)\nendarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"and the output function ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":" y = g(x u t)","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"where t is the time, x in R^n is the state, u in R^p and y in R^m is output of the system. Therefore to construct a RODESystem, we need to define statefunc and outputfunc with the corresponding syntax,","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"function statefunc(dx, x, u, t)\n dx .= ... # Update dx \nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"and ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"function outputfunc(x, u, t)\n y = ... # Compute y\n return y\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"As an example, consider the system with the state function","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":" beginarrayl\n dx_1 = 2 x_1 sin(W_1 - W_2) \n dx_2 = -2 x_2 cos(W_1 + W_2)\n endarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"and with the output function ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":" y = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"That is, all the state variable are taken as output. The statefunc and the outputfunc is defined as,","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"using Jusdl # hide\nfunction statefunc(dx, x, u, t, W)\n dx[1] = 2x[1]*sin(W[1] - W[2])\n dx[2] = -2x[2]*cos(W[1] + W[2])\nend\noutputfunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"To construct the RODESystem, we need to specify the initial condition and time.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"x0 = [1., 1.]\nt = 0.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"Note from statefunc, the system has not any input, i.e. input is nothing, and has an output with a dimension of 1.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"input = nothing\noutput = Outport(2)","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"We are ready to construct the system","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"ds = RODESystem(righthandside=statefunc, readout=outputfunc, state=x0, input=input, output=output, solverkwargs=(dt=0.01,))","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"Note that ds has a solver to solve its state function statefunc which is random differential equation. To solve its statefunc, the step size of the solver must be specified. See Random Differential Equtions of DifferentialEquations package.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Basic-Operation-of-RODESystem","page":"RODESystem","title":"Basic Operation of RODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"When a RODESystem is triggered from its trigger link, it read the current time from its trigger link, reads its input (if available, i.e. its input is not nothing), solves its state function, computes its output value and writes its output value its output bus (again, if available, i.e., its output bus is not nothing). To drive a RODESystem, it must be launched. Let us continue with ds constructed in the previous section.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"iport, trg, hnd = Inport(2), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"When launched, ds is ready to be driven. We can drive ds by drive(ds, t) or put!(ds.trigger, t) where t is the time until which we will drive ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"When triggered, ds read the time t from its trigger link, solved its differential equation, computed its value and writes its output value to its output bus. To signal that, the evolution is succeeded, ds writes true to its handshake link which must be taken to further drive ds. (approve!(ds)) can also be used. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"We can continue to drive ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"After each evolution, ds writes its current output value to its output bus. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"[outbuf(pin.link.buffer) for pin in iport]","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"When launched, a task was constructed which still running. As long as no exception is thrown during the evolution of ds, the state of task is running which implies ds can be driven. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"To terminate the task safely, ds should be terminated safely. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN, NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"Note that the state of task is done which implies the task has been terminated safely.","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Full-API","page":"RODESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/rodesystem/","page":"RODESystem","title":"RODESystem","text":"@def_rode_system \nRODESystem \nMultiplicativeNoiseLinearSystem","category":"page"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Jusdl.@def_rode_system","page":"RODESystem","title":"Jusdl.@def_rode_system","text":"@def_rode_system ex\n\nwhere ex is the expression to define to define a new AbstractRODESystem component type. The usage is as follows:\n\n@def_rode_system mutable struct MyRODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractRODESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MyRODESystem has N parameters. MyRODESystem is represented by the righthandside and readout function. state, input and output is the initial state, input port and output port of MyRODESystem.\n\nwarning: Warning\nrighthandside must have the signature function righthandside((dx, x, u, t, W, args...; kwargs...)\n dx .= .... # update dx\nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew RODE system must be a subtype of AbstractRODESystem to function properly.\n\nExample\n\njulia> @def_rode_system mutable struct MySystem{RH, RO, IP, OP} <: AbstractRODESystem\n A::Matrix{Float64} = [2. 0.; 0 -2]\n righthandside::RH = (dx, x, u, t, W) -> (dx .= A * x * W)\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(2) \n input::IP = nothing \n output::OP = Outport(2)\n end\n\njulia> ds = MySystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Jusdl.RODESystem","page":"RODESystem","title":"Jusdl.RODESystem","text":"RODESystem(; righthandside, readout, state, input, output)\n\nConstructs a generic RODE system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/rodesystem/#Jusdl.MultiplicativeNoiseLinearSystem","page":"RODESystem","title":"Jusdl.MultiplicativeNoiseLinearSystem","text":"MultiplicativeNoiseLinearSystem()\n\nConstructs a MultiplicativeNoiseLinearSystem with the dynamics \n\nbeginarrayl\n dotx = A x W\nendarray\nwhere W is the noise process\n\n\n\n\n\n","category":"type"},{"location":"modeling_and_simulation/modeling/#Modeling","page":"Modeling","title":"Modeling","text":"","category":"section"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"Jusdl adopts signal-flow approach in modeling systems. Briefly, in the signal-flow approach a model consists of components and connections. The simulation of the model is performed in a clocked simulation environment. That is, the model is not simulated in one shot by solving a huge mathematical equation, but instead is simulated by evolving the components individually and in parallel in different sampling intervals.","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"The components interact with each other through the connections that are bound to their port. The components are data processing units, and it is the behavior of the component that determines how the data is processed. The component behavior is defined by the mathematical equations obtained as a result of the physical laws that the physical quantities used in the modeling of the component must comply. Depending upon the nature of the system and the modeling, these equations may change, i.e. they may or may not contain derivative terms, or they may contain the continuous time or discrete time variable, etc. The data-flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input port.","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"Model simulation is performed by evolving the components individually. To make the components have a common time base, a common clock is used. The clock generates pulses at simulation sampling intervals. These pulses are used to trigger the components during the run stage of the simulation. Each component that is triggered reads its input data from its input port, calculates its output, and writes its output to its output port.","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"
\n \"model\"\n
","category":"page"},{"location":"modeling_and_simulation/modeling/#Components","page":"Modeling","title":"Components","text":"","category":"section"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"The component types in Jusdl are shown in the figure below together with output and state equations. The components can be grouped as sources, sinks, and systems. ","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"The sources are components that generate signals as functions of time. Having been triggered, a source computes its output according to its output function and writes it to its output port. The sources do not have input ports as their outputs depend only on time. ","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"The sinks are data processing units. Their primary objective is to process the data flowing through the connections of the model online. Having been triggered, a sink reads its input data and processes them, i.e. data can be visualized by being plotted on a graphical user interface, can be observed by being printed on the console, can be stored on data files. The data processing capability of the sinks can be enriched by integrating new plugins that can be developed using the standard Julia library or various available Julia packages. For example, invariants, spectral properties, or statistical information can be derived from the data, parameter estimation can be performed or various signal processing techniques can be applied to the data. Jusdl has been designed to be flexible enough to allow one to enlarge the scope of its available plugins by integrating newly-defined ones.","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"
\n \"model\"\n
","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"As the output of a static system depends on input and time, a static system is defined by an output equation. Having been triggered, a static system reads its input data, calculates its output, and writes it to its output port. In dynamical systems, however, system behavior is characterized by states and output of a dynamical system depends on input, previous state and time. Therefore, a dynamical system is defined by a state equation and an output equation. When triggered, a dynamical system reads its input, updates its state according to its state equation, calculates its output according to its output equation, and writes its output to its output port. Jusdl is capable of simulating the dynamical systems with state equations in the form of the ordinary differential equation(ODE), differential-algebraic equation(DAE), random ordinary differential equation(RODE), stochastic differential equation(SDE), delay differential equation(DDE) or discrete difference equation. Most of the available simulation environments allow the simulation of systems represented by ordinary differential equations or differential-algebraic equations. Therefore, analyzes such as noise analysis, delay analysis or random change of system parameters cannot be performed in these simulation environments. On the contrary, Jusdl makes it possible for all these analyses to be performed owing to its ability to solve such a wide range of state equations.","category":"page"},{"location":"modeling_and_simulation/modeling/#Ports-and-Connections","page":"Modeling","title":"Ports and Connections","text":"","category":"section"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"A port is actually a bunch of pins to which the connections are bound. There are two types of pins: an output pin that transfers data from the inside of the component to its outside, and an input pin that transfers data from the outside of component to its inside. Hence, there are two types of ports: an output port that consists of output pins and input port that consists of input pins. ","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"The data transferred to a port is transferred to its connection(or connections as an output port may drive multiple connections). The data transfer through the connections is performed over the links of the connections. The links are built on top Julia channels.The data written to(read from) a link is written to(read from) the its channel. Active Julia tasks that are bound to channels must exist for data to flow over these channels. Julia tasks are control flow features that allow calculations to be flexibly suspended and maintained without directly communicating the task scheduler of the operating system. Communication and data exchange between the tasks are carried out through Julia channels to which they are bound.","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"\n \n\n\n\n
\n
\n \"reader_task\"\n
\n
\n \"writer_task\"\n
\n
\n \"reader_writer_task\"\n
\n
\n","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"In the figure above is shown symbolically the tasks that must be bound to the channel to make a channel readable, writable and both readable and writable. The putter and the taker task is the task that writes data to and reads data from the channel, respectively. To be able to read data from one side of the channel, an active putter task must be bound to the channel at the other side of the channel, and the channel is called a readable channel. Similarly, to be able to write data to one side of the channel, an active taker task must be bound to the channel on the other side, and the channel is called a writable channel. If both active putter and taker tasks are bound to either side of the channel, then the data can both be read from and written to the channel, and the channel is called both readable and writable channel. The data-flow through the channel is only achieved if the channel is both readable and writable channels. The data read from a readable channel is the data written to the channel by the putter task of the channel. If data has not been written yet to the channel by the putter task of the channel during a reading process, then reading does not occur and the putter task is waited to put data to the channel. Similarly, if the data on the channel has not been read yet from the channel by the taker task during a writing process, then the taker task is waited to take data from the channel. ","category":"page"},{"location":"modeling_and_simulation/modeling/","page":"Modeling","title":"Modeling","text":"In the modeling approach adopted, the components reading data from a connection are driven by other components writing data to the connection. Therefore, all of the connections of the model must be both readable and writable connections so that data can flow the connections. This means that all the connections of the model must be connected to a component from both ends. Otherwise, the simulation gets stuck and does not end during a reading process from a channel that is not connected to a component. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#ODESystem","page":"ODESystem","title":"ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Basic-Operation-of-ODESystem","page":"ODESystem","title":"Basic Operation of ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When an ODESystem is triggered, it reads its current time from its trigger link, reads its input, solves its differential equation and computes its output. Let us observe the basic operation of ODESystems with a simple example. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"We first construct an ODESystem. Since an ODESystem is represented by its state equation and output equation, we need to define those equations.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"using Jusdl # hide \nsfunc(dx,x,u,t) = (dx .= -0.5x)\nofunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us construct the system ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds = ODESystem(righthandside=sfunc, readout=ofunc, state=[1.], input=Inport(1), output=Outport(1))","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that ds is a single input single output ODESystem with an initial state of [1.] and initial time 0.. To drive, i.e. trigger ds, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"oport, iport, trg, hnd = Outport(1), Inport(1), Outpin(), Inpin{Bool}()\nconnect!(oport, ds.input) \nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When launched, ds is ready to driven. ds is driven from its trigger link. Note that the trigger link of ds is writable. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds.trigger.link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us drive ds to the time of t of 1 second.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When driven, ds reads current time of t from its trigger link, reads its input value from its input, solves its differential equation and computes its output values and writes its output. So, for the step to be continued, an input values must be written. Note that the input of ds is writable,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"ds.input[1].link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Let us write some value. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(oport, [5.])","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"At this point, ds completed its step and put true to its handshake link to signal that its step is succeeded.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"hnd.link","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"To complete the step and be ready for another step, we need to approve the step by reading its handshake. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"At this point, ds can be driven further. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"for t in 2. : 10.\n put!(trg, t)\n put!(oport, [t * 10])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that all the output value of ds is written to its outputbus,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"When we launched ds, we constructed a task and the task is still running.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"To terminate the task safely, we need to terminate ds safely.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Now, the state of the task is done. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"So, it is not possible to drive ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Mutation-in-State-Function-in-ODESystem","page":"ODESystem","title":"Mutation in State Function in ODESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Consider a system with the following ODE","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"beginarrayl\n dotx = f(x u t) \n y = g(x u t) \nendarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"where x in R^d y in R^m u in R^p. To construct and ODESystem, The signature of the state function statefunc must be of the form ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"function statefunc(dx, x, u, t)\n dx .= ... # Update dx\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note that statefunc does not construct dx but updates dx and does not return anything. This is for performance reasons. On the contrary, the signature of the output function outputfunc must be of the form,","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"function outputfunc(x, u, t)\n y = ... # Compute y\n return y\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"Note the output value y is computed and returned from outputfunc. y is not updated but generated in the outputfunc.","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Full-API","page":"ODESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/odesystem/","page":"ODESystem","title":"ODESystem","text":"@def_ode_system \nODESystem \nContinuousLinearSystem \nLorenzSystem \nForcedLorenzSystem \nChenSystem \nForcedChenSystem \nChuaSystem \nForcedChuaSystem \nRosslerSystem \nForcedRosslerSystem \nVanderpolSystem \nForcedVanderpolSystem\nIntegrator ","category":"page"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.@def_ode_system","page":"ODESystem","title":"Jusdl.@def_ode_system","text":"@def_ode_system ex\n\nwhere ex is the expression to define to define a new AbstractODESystem component type. The usage is as follows:\n\n@def_ode_system mutable struct MyODESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractODESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandeside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \nend\n\nHere, MyODESystem has N parameters. MyODESystem is represented by the righthandside and readout function. state, input and output is the state, input port and output port of MyODESystem.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew ODE system must be a subtype of AbstractODESystem to function properly. \n\nwarning: Warning\nNew ODE system must be mutable type.\n\nExample\n\njulia> @def_ode_system mutable struct MyODESystem{RH, RO, IP, OP} <: AbstractODESystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n state::Vector{Float64} = [1.]\n input::IP = Inport(1) \n output::OP = Outport(1) \n end\n\njulia> ds = MyODESystem();\n\njulia> ds.input \n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ODESystem","page":"ODESystem","title":"Jusdl.ODESystem","text":"ODESystem(;righthandside, readout, state, input, output)\n\nConstructs a generic ODE system.\n\nExample\n\njulia> ds = ODESystem(righthandside=(dx,x,u,t)->(dx.=-x), readout=(x,u,t)->x, state=[1.],input=nothing, output=Outport(1));\n\njulia> ds.state\n1-element Array{Float64,1}:\n 1.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ContinuousLinearSystem","page":"ODESystem","title":"Jusdl.ContinuousLinearSystem","text":"ContinuousLinearSystem(input, output, modelargs=(), solverargs=(); \n A=fill(-1, 1, 1), B=fill(0, 1, 1), C=fill(1, 1, 1), D=fill(0, 1, 1), state=rand(size(A,1)), t=0., \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ContinuousLinearSystem 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.\n\nThe ContinuousLinearSystem is represented by the following state and output equations.\n\nbeginarrayl\n dotx = A x + B u 025cm\n y = C x + D u \nendarray\n\nwhere x is state. solver is used to solve the above differential equation.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.LorenzSystem","page":"ODESystem","title":"Jusdl.LorenzSystem","text":"LorenzSystem(input, output, modelargs=(), solverargs=(); \n sigma=10, beta=8/3, rho=28, gamma=1, outputfunc=allstates, state=rand(3), t=0.,\n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a LorenzSystem with input and output. sigma, beta, rho and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of LorenzSystem is \n\nbeginarrayl\n dotx_1 = gamma (sigma (x_2 - x_1)) 025cm\n dotx_2 = gamma (x_1 (rho - x_3) - x_2) 025cm\n dotx_3 = gamma (x_1 x_2 - beta x_3) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (sigma (x_2 - x_1)) + sum_j = 1^3 alpha_1j u_j 025cm\n dotx_2 = gamma (x_1 (rho - x_3) - x_2) + sum_j = 1^3 alpha_2j u_j 025cm\n dotx_3 = gamma (x_1 x_2 - beta x_3) + sum_j = 1^3 alpha_3j u_j \nendarray\n\nwhere A = alpha_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ForcedLorenzSystem","page":"ODESystem","title":"Jusdl.ForcedLorenzSystem","text":"ForcedLorenzSystem()\n\nConstructs a LorenzSystem that is driven by its inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ChenSystem","page":"ODESystem","title":"Jusdl.ChenSystem","text":"ChenSystem(input, output, modelargs=(), solverargs=(); \n a=35, b=3, c=28, gamma=1, outputfunc=allstates, state=rand(3), t=0.,\n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ChenSystem with input and output. a, b, c and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of ChenSystem is \n\nbeginarrayl\n dotx_1 = gamma (a (x_2 - x_1)) 025cm\n dotx_2 = gamma ((c - a) x_1 + c x_2 + x_1 x_3) 025cm\n dotx_3 = gamma (x_1 x_2 - b x_3) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (a (x_2 - x_1)) + sum_j = 1^3 alpha_1j u_j 025cm\n dotx_2 = gamma ((c - a) x_1 + c x_2 + x_1 x_3) + sum_j = 1^3 alpha_2j u_j 025cm\n dotx_3 = gamma (x_1 x_2 - b x_3) + sum_j = 1^3 alpha_3j u_j \nendarray\n\nwhere A = alpha_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ForcedChenSystem","page":"ODESystem","title":"Jusdl.ForcedChenSystem","text":"ForcedChenSystem()\n\nConstructs Chen system driven by its inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ChuaSystem","page":"ODESystem","title":"Jusdl.ChuaSystem","text":"ChuaSystem(input, output, modelargs=(), solverargs=(); \n diode=PiecewiseLinearDiode(), alpha=15.6, beta=28., gamma=1., outputfunc=allstates, state=rand(3), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a ChuaSystem with input and output. diode, alpha, beta and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of ChuaSystem is \n\nbeginarrayl\n dotx_1 = gamma (alpha (x_2 - x_1 - h(x_1))) 025cm\n dotx_2 = gamma (x_1 - x_2 + x_3 ) 025cm\n dotx_3 = gamma (-beta x_2) \nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (alpha (x_2 - x_1 - h(x_1))) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (x_1 - x_2 + x_3 ) + sum_j = 1^3 theta_2j u_j 025cm\n dotx_3 = gamma (-beta x_2) + sum_j = 1^3 theta_3j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ForcedChuaSystem","page":"ODESystem","title":"Jusdl.ForcedChuaSystem","text":"ForcedChuaSystem()\n\nConstructs a Chua system with inputs.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.RosslerSystem","page":"ODESystem","title":"Jusdl.RosslerSystem","text":"RosslerSystem(input, output, modelargs=(), solverargs=(); \n a=0.38, b=0.3, c=4.82, gamma=1., outputfunc=allstates, state=rand(3), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1., 1.]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a RosllerSystem with input and output. a, b, c and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of RosslerSystem is \n\nbeginarrayl\n dotx_1 = gamma (-x_2 - x_3) 025cm\n dotx_2 = gamma (x_1 + a x_2) 025cm\n dotx_3 = gamma (b + x_3 (x_1 - c))\nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (-x_2 - x_3) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (x_1 + a x_2 ) + sum_j = 1^3 theta_2j u_j 025cm\n dotx_3 = gamma (b + x_3 (x_1 - c)) + sum_j = 1^3 theta_3j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ForcedRosslerSystem","page":"ODESystem","title":"Jusdl.ForcedRosslerSystem","text":"ForcedRosslerSystem()\n\nConstructs a Rossler system driven by its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.VanderpolSystem","page":"ODESystem","title":"Jusdl.VanderpolSystem","text":"VanderpolSystem(input, output, modelargs=(), solverargs=(); \n mu=5., gamma=1., outputfunc=allstates, state=rand(2), t=0., \n alg=ODEAlg, cplmat=diagm([1., 1]), modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs a VanderpolSystem with input and output. mu and gamma is the system parameters. 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.\n\nIf input is nothing, the state equation of VanderpolSystem is \n\nbeginarrayl\n dotx_1 = gamma (x_2) 025cm\n dotx_2 = gamma (mu (x_1^2 - 1) x_2 - x_1 )\nendarray\n\nwhere x is state. solver is used to solve the above differential equation. If input is not nothing, then the state eqaution is\n\nbeginarrayl\n dotx_1 = gamma (x_2) + sum_j = 1^3 theta_1j u_j 025cm\n dotx_2 = gamma (mu (x_1^2 - 1) x_2 - x_1) + sum_j = 1^3 theta_2j u_j \nendarray\n\nwhere Theta = theta_ij is cplmat and u = u_j is the value of the input. The output function is \n\n y = g(x u t)\n\nwhere t is time t, y is the value of the output and g is outputfunc.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.ForcedVanderpolSystem","page":"ODESystem","title":"Jusdl.ForcedVanderpolSystem","text":"ForcedVanderpolSystem()\n\nConstructs a Vanderpol system driven by its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/odesystem/#Jusdl.Integrator","page":"ODESystem","title":"Jusdl.Integrator","text":"Integrator(state=zeros(0), t=0., modelargs=(), solverargs=(); \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple(), numtaps=numtaps, callbacks=nothing, \n name=Symbol())\n\nConstructs an integrator whose input output relation is given by \n\nu(t) = ki * int_0^t u(tau) dtau\n\nwhere u(t) is the input, y(t) is the output and ki is the integration constant.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/printer/#Printer","page":"Printer","title":"Printer","text":"","category":"section"},{"location":"manual/components/sinks/printer/#Basic-Operation-of-Printers","page":"Printer","title":"Basic Operation of Printers","text":"","category":"section"},{"location":"manual/components/sinks/printer/","page":"Printer","title":"Printer","text":"See Basic Operation of Writers since the operation of Writer and that of Printer is very similar.","category":"page"},{"location":"manual/components/sinks/printer/#Full-API","page":"Printer","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/printer/","page":"Printer","title":"Printer","text":"Printer \nprint(printer::Printer, td, xd) \nopen(printer::Printer) \nclose(printer::Printer) ","category":"page"},{"location":"manual/components/sinks/printer/#Jusdl.Printer","page":"Printer","title":"Jusdl.Printer","text":"Printer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol()) where T Constructs a Printer with input bus input. buflen is the length of its internal buflen. plugin is data proccessing tool.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/printer/#Base.print-Tuple{Printer,Any,Any}","page":"Printer","title":"Base.print","text":"print(printer::Printer, td, xd)\n\nPrints xd corresponding to xd to the console.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/printer/#Base.open-Tuple{Printer}","page":"Printer","title":"Base.open","text":"open(printer::Printer)\n\nDoes nothing. Just a common interface function ot AbstractSink interface.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/printer/#Base.close-Tuple{Printer}","page":"Printer","title":"Base.close","text":"close(printer::Printer)\n\nDoes nothing. Just a common interface function ot AbstractSink interface.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#DDESystem","page":"DDESystem","title":"DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Construction-of-DDESystem","page":"DDESystem","title":"Construction of DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"A DDESystem is represented by the following state equation","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" dotx = f(x h u t) quad t geq t_0","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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 ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" x(t) = h(t) quad t leq t_0","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"and by the output equation","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" y = g(x u t) ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"where y is the value of the output. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"As an example, consider a system with the state equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":" beginarrayl\n dotx = -x(t - tau) quad t geq 0 \n x(t) = 1 -tau leq t leq 0 \n endarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"First, we define the history function histfunc,","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"using Jusdl # hide\nconst out = zeros(1)\nhistfunc(out, u, t) = (out .= 1.);","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that histfunc mutates a vector out. This mutation is for performance reasons. Next the state function can be defined","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"function statefunc(dx, x, h, u, t)\n h(out, u, t - tau) # Update out vector\n dx[1] = out[1] + x[1]\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"and let us take all the state variables as outputs. Thus, the output function is ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"outputfunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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, ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"tau = 1\nconslags = [tau]","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"At this point, we are ready to construct the system. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"ds = DDESystem(righthandside=statefunc, history=histfunc, readout=outputfunc, state=[1.], input=nothing, output=Outport(), constlags=conslags, depslags=nothing)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Basic-Operation-of-DDESystem","page":"DDESystem","title":"Basic Operation of DDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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,","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"iport, trg, hnd = Inport(), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"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).","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"We can continue to drive ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"When launched, we constructed a task whose state is running which implies that ds can be driven. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"As long as the state of the task is running, ds can be driven. To terminate task safely, we need to terminate the ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"put!(trg, NaN)","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that the state of task is done which implies that ds is not drivable any more. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"Note that the output values of ds is written to its output bus. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Full-API","page":"DDESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/ddesystem/","page":"DDESystem","title":"DDESystem","text":"@def_dde_system \nDDESystem \nDelayFeedbackSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Jusdl.@def_dde_system","page":"DDESystem","title":"Jusdl.@def_dde_system","text":"@def_dde_system ex\n\nwhere ex is the expression to define to define a new AbstractDDESystem component type. The usage is as follows:\n\n@def_dde_system mutable struct MyDDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDDESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n constlags::CL = constlags_default # mandatory field\n depslags::DL = depslags_default # mandatory field\n righthandside::RH = righthandside_function # mandatory field\n history::HST = history_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_defauult # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MyDDESystem has N parameters. MyDDESystem is represented by the righthandside and readout function. state, input and output is the state, input port and output port of MyDDESystem.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew DDE system must be a subtype of AbstractDDESystem to function properly.\n\nExample\n\njulia> _delay_feedback_system_cache = zeros(1)\n1-element Array{Float64,1}:\n 0.0\n\njulia> _delay_feedback_system_tau = 1.\n1.0\n\njulia> _delay_feedback_system_constlags = [1.]\n1-element Array{Float64,1}:\n 1.0\n\njulia> _delay_feedback_system_history(cache, u, t) = (cache .= 1.)\n_delay_feedback_system_history (generic function with 1 method)\n\njulia> function _delay_feedback_system_rhs(dx, x, h, u, t, \n cache=_delay_feedback_system_cache, τ=_delay_feedback_system_tau)\n h(cache, u, t - τ) # Update cache \n dx[1] = cache[1] + x[1]\n end\n_delay_feedback_system_rhs (generic function with 3 methods)\n\njulia> @def_dde_system mutable struct MyDDESystem{RH, HST, RO, IP, OP} <: AbstractDDESystem\n constlags::Vector{Float64} = _delay_feedback_system_constlags\n depslags::Nothing = nothing\n righthandside::RH = _delay_feedback_system_rhs\n history::HST = _delay_feedback_system_history\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(1)\n input::IP = nothing \n output::OP = Outport(1)\n end\n\njulia> ds = MyDDESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Jusdl.DDESystem","page":"DDESystem","title":"Jusdl.DDESystem","text":"DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)\n\nConstruct a generic DDE system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/ddesystem/#Jusdl.DelayFeedbackSystem","page":"DDESystem","title":"Jusdl.DelayFeedbackSystem","text":"DDESystem(; constantlags, depslags, righthandside, history, readout, state, input, output)\n\nConstructs DelayFeedbackSystem\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#SDESystem","page":"SDESystem","title":"SDESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Construction-of-SDESystems","page":"SDESystem","title":"Construction of SDESystems","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"A SDESystem is represented by the state function ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" dx = f(x u t) dt + h(x u t)dW ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"where t is the time, x in R^n is the value of state, u in R^p is the value of the input. W is the Wiener process of the system. The output function is defined by ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" y = g(x u t)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"where y is the value of output at time t. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"As an example consider a system with the following stochastic differential equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":" beginarrayl\n dx = -x dt - x dW\n endarray","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"and the following output equation ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"y = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The state function statefunc and the output function outputfunc is defined as follows.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"using Jusdl # hide \nf(dx, x, u, t) = (dx[1] = -x[1])\nh(dx, x, u, t) = (dx[1] = -x[1])","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The state function statefunc is the tuple of drift and diffusion functions","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"statefunc = (f, h)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The output function outputfunc is defined as,","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"g(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that the in drift function f and diffusion function g, the vector dx is mutated while in the output function g no mutation is done, but the output value is generated instead.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"From the definition of drift function f and the diffusion function g, it is seen that the system does not have any input, that is, the input of the system is nothing. Since all the state variables are taken as outputs, the system needs an output bus of length 1. Thus, ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"input = nothing \noutput = Outport(1)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"At this point, we are ready to construct the system ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"ds = SDESystem(righthandside=statefunc, readout=g, state=[1.], input=input, output=output)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Basic-Operation-of-SDESystems","page":"SDESystem","title":"Basic Operation of SDESystems","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"The basic operation of a SDESystem is the same as those of other dynamical systems. When triggered from its trigger link, a SDESystem reads its time t from its trigger link, reads its input value from its input, solves its state equation, which is a stochastic differential equation, computes its output and writes its computed output to its output bus. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"In this section, we continue with the system ds constructed in the previous section. To make ds drivable, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"iport, trg, hnd = Inport(1), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"When launched, ds can be driven. For this, either of the syntax put!(ds.trigger, t) or drive(ds, t) can be used. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"After this command, ds reads its time t from its trigger link, solves its state function and computes its output. The calculated output value is written to the buffer of output. To signal that, the step is takes with success, ds writes true to its handshake link. To further drive ds, this handshake link must be read. For this either of the syntax, take!(ds.handshake) or approve!(ds) can be used","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"hnd.link\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"At this point, we can further drive ds. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that during the evolution, the output of ds is written into the buffers of output bus.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"warning: Warning\nThe values of the output is written into buffers if the output of the systems is not nothing.","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"When we launched ds, we constructed a task whose state is running which implies that the ds can be drivable. As long as this task is running, ds can be drivable. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"warning: Warning\nThe state of the task is different from running in case an exception is thrown. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"To terminate the task securely, we need to terminate ds securely. To do that, can use terminate!(ds).","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"Note that the task is terminated without a hassle. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Full-API","page":"SDESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/sdesystem/","page":"SDESystem","title":"SDESystem","text":"@def_sde_system \nSDESystem \nNoisyLorenzSystem \nForcedNoisyLorenzSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Jusdl.@def_sde_system","page":"SDESystem","title":"Jusdl.@def_sde_system","text":"@def_sde_system ex\n\nwhere ex is the expression to define to define a new AbstractSDESystem component type. The usage is as follows:\n\n@def_sde_system mutable struct MySDESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractSDESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n drift::DR = drift_function # mandatory field\n diffusion::DF = diffusion_function # mandatory field\n readout::RO = readout_functtion # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MySDESystem has N parameters. MySDESystem is represented by the drift, diffusion and readout function. state, input and output is the initial state, input port and output port of MySDESystem.\n\nwarning: Warning\ndrift must have the signature function drift((dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx\nendand diffusion must have the signature function diffusion((dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx\nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew SDE system must be a subtype of AbstractSDESystem to function properly.\n\nExample\n\njulia> @def_sde_system mutable struct MySDESystem{DR, DF, RO, IP, OP} <: AbstractSDESystem\n η::Float64 = 1.\n drift::DR = (dx, x, u, t) -> (dx .= x)\n diffusion::DF = (dx, x, u, t, η=η) -> (dx .= η)\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(2) \n input::IP = nothing \n output::OP = Outport(2)\n end\n\njulia> ds = MySDESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Jusdl.SDESystem","page":"SDESystem","title":"Jusdl.SDESystem","text":"SDESystem(; drift, diffusion, readout, state, input, output)\n\nConstructs a SDE system. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Jusdl.NoisyLorenzSystem","page":"SDESystem","title":"Jusdl.NoisyLorenzSystem","text":"NoisyLorenzSystem()\n\nConstructs a noisy Lorenz system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/sdesystem/#Jusdl.ForcedNoisyLorenzSystem","page":"SDESystem","title":"Jusdl.ForcedNoisyLorenzSystem","text":"NoisyLorenzSystem()\n\nConstructs a noisy Lorenz system \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/sinks/#Sinks","page":"Sinks","title":"Sinks","text":"","category":"section"},{"location":"manual/components/sinks/sinks/","page":"Sinks","title":"Sinks","text":"Sinks are used to simulation data flowing through the connections of the model. The data processing is done online during the simulation. Sink type is a subtype of AbstractSink. An AbstractSink is also a subtype of AbstractComponent (see Components), so an AbstractSink instance has a trigger link to be triggered and a handshake link to signal that evolution is succeeded. In addition, an AbstractSink has an input buffer inbuf whose mode is Cyclic. When an AbstractSink instance is triggered through its trigger link, it basically reads its incoming data and writes to its input buffer inbuf. When its input buffer inbuf is full, the data in inbuf is processed according to the type of AbstractSink. Jusdl provides three concrete subtypes of AbstractSink which are Writer, Printer and Scope. As the operation of an AbstractSink just depends on incoming data, an AbstractSink does not have an output.","category":"page"},{"location":"manual/components/sinks/sinks/#Full-API","page":"Sinks","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/sinks/","page":"Sinks","title":"Sinks","text":"@def_sink","category":"page"},{"location":"manual/components/sinks/sinks/#Jusdl.@def_sink","page":"Sinks","title":"Jusdl.@def_sink","text":"@def_sink ex\n\nwhere ex is the expression to define to define a new AbstractSink component type. The usage is as follows:\n\n@def_sink struct MySink{T1,T2,T3,...,TN, A} <: AbstractSink\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n action::A = action_function # mandatory field\nend\n\nHere, MySink has N parameters and action function\n\nwarning: Warning\naction function must have a method action(sink::MySink, t, u) where t is the time data and u is the data flowing into the sink.\n\nwarning: Warning\nNew static system must be a subtype of AbstractSink to function properly.\n\nExample\n\njulia> @def_sink struct MySink{A} <: AbstractSink \n action::A = actionfunc\n end\n\njulia> actionfunc(sink::MySink, t, u) = println(t, u)\nactionfunc (generic function with 1 method)\n\njulia> sink = MySink();\n\njulia> sink.action(sink, ones(2), ones(2) * 2)\n[1.0, 1.0][2.0, 2.0]\n\n\n\n\n\n","category":"macro"},{"location":"manual/connections/link/#Links","page":"Links","title":"Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Links are built on top of Channels of Julia. They are used as communication primitives for Tasks of Julia. A Link basically includes a Channel and a Buffer. The mode of the buffer is Cyclic.(see Buffer Modes for information on buffer modes). Every item sent through a Link is sent through the channel of the Link and written to the Buffer so that all the data flowing through a Link is recorded.","category":"page"},{"location":"manual/connections/link/#Construction-of-Links","page":"Links","title":"Construction of Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The construction of a Link is very simple: just specify its buffer length and element type.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Jusdl # hide \nLink{Bool}(5)\nLink{Int}(10)\nLink(5) \nLink()","category":"page"},{"location":"manual/connections/link/#Data-Flow-through-Links","page":"Links","title":"Data Flow through Links","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The data can be read from and written into Links if active tasks are bound to them. Links can be thought of like a pipe. In order to write data to a Link from one of its ends, a task that reads written data from the other end must be bounded to the Link. Similarly, in order to read data from one of the Link from one of its end, a task that writes the read data must be bound to the Link. Reading from and writing to Link is carried out with take! and put! functions. For more clarity, let us see some examples. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Let us first construct a Link,","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Jusdl # hide\nl = Link(5)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l is a Link with a buffer length of 5 and element type of Float64. Not that the l is open, but it is not ready for data reading or writing. To write data, we must bound a task that reads the written data.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"function reader(link::Link) # Define job.\n while true\n val = take!(link)\n val === NaN && break # Poison-pill the tasks to terminate safely.\n end\nend\nt = @async reader(l)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The reader is defined such that the data written from one end of l is read until the data is NaN. Now, we have runnable a task t. This means the l is ready for data writing. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"put!(l, 1.)\nput!(l, 2.)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Note that the data flown through the l is written to its buffer. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l.buffer","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"To terminate the task, we must write NaN to l.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"put!(l, NaN) # Terminate the task \nt # Show that the `t` is terminated.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Whenever the bound task to the l is runnable, the data can be written to l. That is, the data length that can be written to l is not limited by the buffer length of l. But, beware that the buffer of Links is Cyclic. That means, when the buffer is full, its data is overwritten.","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"l = Link(5)\nt = @async reader(l)\nfor item in 1. : 10.\n put!(l, item)\n @show outbuf(l.buffer)\nend","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"The case is very similar to read data from l. Again, a runnable task is bound the l ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"using Jusdl # hide\nl = Link(5)\nfunction writer(link::Link, vals)\n for val in vals\n put!(link, val)\n end\nend\nt = @async writer(l, 1.:5.)\nbind(l, t)\ntake!(l)\ntake!(l)","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"It is possible to read data from l until t is active. To read all the data at once, collect can be used. ","category":"page"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"t \ncollect(l)\nt # Show that `t` is terminated.","category":"page"},{"location":"manual/connections/link/#Full-API","page":"Links","title":"Full API","text":"","category":"section"},{"location":"manual/connections/link/","page":"Links","title":"Links","text":"Modules = [Jusdl]\nPages = [\"link.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/link/#Jusdl.Link","page":"Links","title":"Jusdl.Link","text":"Link{T}(ln::Int=64) where {T}\n\nConstructs a Link with element type T and buffer length ln. The buffer element type is T and mode is Cyclic.\n\nLink(ln::Int=64)\n\nConstructs a Link with element type Float64 and buffer length ln. The buffer element type is Float64 and mode is Cyclic.\n\nExample\n\njulia> l = Link{Int}(5)\nLink(state:open, eltype:Int64, isreadable:false, iswritable:false)\n\njulia> l = Link{Bool}()\nLink(state:open, eltype:Bool, isreadable:false, iswritable:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/link/#Base.bind-Tuple{Link,Task}","page":"Links","title":"Base.bind","text":"bind(link::Link, task::Task)\n\nBinds task to link. When task is done link is closed.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.close-Tuple{Link}","page":"Links","title":"Base.close","text":"close(link)\n\nCloses link. All the task bound the link is also terminated safely. When closed, it is not possible to take and put element from the link. See also: take!(link::Link), put!(link::Link, val) ```\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.collect-Tuple{Link}","page":"Links","title":"Base.collect","text":"collect(link::Link)\n\nCollects all the available data on the link.\n\nwarning: Warning\nTo collect all available data from link, a task must be bounded to it.\n\nExample\n\njulia> l = Link(); # Construct a link.\n\njulia> t = @async for item in 1 : 5 # Construct a task\n put!(l, item)\n end;\n\njulia> bind(l, t); # Bind it to the link.\n\njulia> take!(l) # Take element from link.\n1.0\n\njulia> take!(l) # Take again ...\n2.0\n\njulia> collect(l) # Collect remaining data.\n3-element Array{Float64,1}:\n 3.0\n 4.0\n 5.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.eltype-Union{Tuple{Link{T}}, Tuple{T}} where T","page":"Links","title":"Base.eltype","text":"eltype(link::Link)\n\nReturns element type of link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.isopen-Tuple{Link}","page":"Links","title":"Base.isopen","text":"isopen(link::Link)\n\nReturns true if link is open. A link is open if its channel is open.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.isreadable-Tuple{Link}","page":"Links","title":"Base.isreadable","text":"isreadable(link::Link)\n\nReturns true if link is readable. When link is readable, data can be read from link with take function.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.iswritable-Tuple{Link}","page":"Links","title":"Base.iswritable","text":"writable(link::Link)\n\nReturns true if link is writable. When link is writable, data can be written into link with put function.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.put!-Tuple{Link,Any}","page":"Links","title":"Base.put!","text":"put!(link::Link, val)\n\nPuts val to link. val is handed over to the channel of link. val is also written in to the buffer of link.\n\nwarning: Warning\nlink must be writable to put val. That is, a runnable task that takes items from the link must be bounded to link.\n\nExample\n\njulia> l = Link();\n\njulia> t = @async while true \n item = take!(l)\n item === NaN && break \n println(\"Took \" * string(item))\n end;\n\njulia> bind(l, t);\n\njulia> put!(l, 1.)\nTook 1.0\n1.0\n\njulia> put!(l, 2.)\nTook 2.0\n2.0\n\njulia> put!(l, NaN)\nNaN\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Base.take!-Tuple{Link}","page":"Links","title":"Base.take!","text":"take!(link::Link)\n\nTake an element from link.\n\nwarning: Warning\nlink must be readable to take value. That is, a runnable task that puts items from the link must be bounded to link.\n\nExample\n\njulia> l = Link(5);\n\njulia> t = @async for item in 1. : 5.\n put!(l, item)\n end;\n\njulia> bind(l, t);\n\njulia> take!(l)\n1.0\n\njulia> take!(l)\n2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Jusdl.isfull-Tuple{Link}","page":"Links","title":"Jusdl.isfull","text":"isfull(link::Link)\n\nReturns true if the buffer of link is full.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Jusdl.launch-Tuple{Link,Any}","page":"Links","title":"Jusdl.launch","text":"launch(link:Link, valrange)\n\nConstructs a putter task and binds it to link. putter tasks puts the data in valrange.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Jusdl.launch-Tuple{Link}","page":"Links","title":"Jusdl.launch","text":"launch(link::Link)\n\nConstructs a taker task and binds it to link. The taker task reads the data and prints an info message until missing is read from the link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Jusdl.refresh!-Union{Tuple{Link{T}}, Tuple{T}} where T","page":"Links","title":"Jusdl.refresh!","text":"refresh!(link::Link)\n\nReconstructst the channel of link is its channel is closed.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/link/#Jusdl.snapshot-Tuple{Link}","page":"Links","title":"Jusdl.snapshot","text":"snapshot(link::Link)\n\nReturns all the data of the buffer of link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Pins","page":"Pins","title":"Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Pins are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin and Inpin. The data flows from inside of the components to its outside through Outpin while data flow from outside of the components to its inside through Inpin.","category":"page"},{"location":"manual/connections/pin/#Connection-and-Disconnection-of-Pins","page":"Pins","title":"Connection and Disconnection of Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"In Jusdl, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Jusdl). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Links. A Link connects Outpins to Inpins, and the data flow is from Outpin to Inpin.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"note: Note\nAs the data movement is from Outpin to Inpin, connection of an Inpin to an Outpin gives a MethodError.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"For example, let us construct and Outpin and Inpins and connect the together.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"using Jusdl # hide \nop = Outpin() \nip = Inpin() \nlink = connect!(op, ip)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note connect!(op, ip) connects op and ip through a Link can return the constructed link. The connection of pins can be monitored. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"isconnected(op, ip)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The constructed link can be accessed though the pins. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"op.links[1] === link \nip.link === link","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"note: Note\nIt is possible for an Outpin to have multiple Links bound to itself. On contract, an Inpin can have just one Link.","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The connected links Outpin and Inpin can be disconnected using disconnect! function. When disconnected, the data transfer from the Outpin to Inpin is not possible. ","category":"page"},{"location":"manual/connections/pin/#Data-Flow-Through-Pins","page":"Pins","title":"Data Flow Through Pins","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"The data flow from an Outpin to an Inpin. However for data flow through a pin, a running task must be bound the channel of the link of the pin. See the example below. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"t = @async while true \n take!(ip) === NaN && break \nend ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"As the task t is bound the channel of the link data can flow through op and ip. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"put!(op, 1.)\nput!(op, 2.) \nput!(op, 3.)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note that t is a taker job. As the taker job t takes data from op, we were able to put values into op. The converse is also possible. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"op2, ip2 = Outpin(), Inpin() \nlink2 = connect!(op2, ip2) \nt2 = @async for item in 1 : 5\n put!(op2, item)\nend\ntake!(ip2)\ntake!(ip2)","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Note that in both of the cases given above the data flow is always from an Outpin to an Inpin. ","category":"page"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"warning: Warning\nIt is not possible to take data from an Outpin and put into Inpin. Thus, take!(pin::Outpoin) and put!(pin::Inpin) throws a method error.","category":"page"},{"location":"manual/connections/pin/#Full-API","page":"Pins","title":"Full API","text":"","category":"section"},{"location":"manual/connections/pin/","page":"Pins","title":"Pins","text":"Modules = [Jusdl]\nPages = [\"pin.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/pin/#Jusdl.AbstractPin","page":"Pins","title":"Jusdl.AbstractPin","text":"AbstractPin{T}\n\nAbstract type of Outpin and Inpin. See also: Outpin, Inpin\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Jusdl.Inpin","page":"Pins","title":"Jusdl.Inpin","text":"Inpin{T}()\n\nConstructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Jusdl.Outpin","page":"Pins","title":"Jusdl.Outpin","text":"Outpin{T}()\n\nConstructs and OutPut pin. The data flow from Outpin is outwards from the pin i.e., data is written from OutPort to its links.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/pin/#Base.bind-Tuple{Link,Inpin}","page":"Pins","title":"Base.bind","text":"bind(link::Link, pin)\n\nBinds link to pin. When bound, data written into or read from pin is written into or read from link.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.eltype-Union{Tuple{AbstractPin{T}}, Tuple{T}} where T","page":"Pins","title":"Base.eltype","text":"eltype(pin::AbstractPin)\n\nReturns element typef of pin.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.put!-Tuple{Outpin,Any}","page":"Pins","title":"Base.put!","text":"put!(pin::Outpin, val)\n\nPuts val to pin. val is put into the links of pin.\n\nwarning: Warning\nTo take data from pin, a running task that puts data must be bound to link of pin.\n\nExample\n\njulia> op = Outpin();\n\njulia> l = Link();\n\njulia> bind(l, op);\n\njulia> t = @async while true \n val = take!(l) \n val === NaN && break\n println(\"Took \" * string(val))\n end;\n\njulia> put!(op, 1.)\nTook 1.0\n\njulia> put!(op, 3.)\nTook 3.0\n\njulia> put!(op, NaN)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Base.take!-Tuple{Inpin}","page":"Pins","title":"Base.take!","text":"take!(pin::Inpin)\n\nTakes data from pin. The data is taken from the links of pin.\n\nwarning: Warning\nTo take data from pin, a running task that puts data must be bound to link of pin.\n\nExample\n\njulia> ip = Inpin();\n\njulia> l = Link();\n\njulia> bind(l, ip);\n\njulia> t = @async for item in 1 : 5 \n put!(l, item)\n end;\n\njulia> take!(ip)\n1.0\n\njulia> take!(ip)\n2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Jusdl.connect!-Tuple{Outpin,Inpin}","page":"Pins","title":"Jusdl.connect!","text":"connect!(outpin::Link, inpin::Link)\n\nConnects outpin to inpin. When connected, any element that is put into outpin is also put into inpin. \n\nconnect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})\n\nConnects each link in outpin to each link in inpin one by one. See also: disconnect!\n\nExample\n\njulia> op, ip = Outpin(), Inpin();\n\njulia> l = connect!(op, ip)\nLink(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> l in op.links\ntrue\n\njulia> ip.link === l\ntrue\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Jusdl.disconnect!-Tuple{Outpin,Inpin}","page":"Pins","title":"Jusdl.disconnect!","text":"disconnect!(link1::Link, link2::Link)\n\nDisconnects link1 and link2. The order of arguments is not important. See also: connect!\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Jusdl.isbound-Tuple{Outpin}","page":"Pins","title":"Jusdl.isbound","text":"isbound(pin::AbstractPin)\n\nReturns true if pin is bound to other pins.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/pin/#Jusdl.isconnected-Tuple{Outpin,Inpin}","page":"Pins","title":"Jusdl.isconnected","text":"isconnected(link1, link2)\n\nReturns true if link1 is connected to link2. The order of the arguments are not important. See also connect!, disconnect!\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Callback","page":"Callback","title":"Callback","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Callbacks are used to monitor the existence of a specific event and if that specific event occurs, some other special jobs are invoked. Callbacks are intended to provide additional monitoring capability to any user-defined composite types. As such, Callbacks are generally fields of user defined composite types. When a Callback is called, if the Callback is enabled and its condition function returns true, then its action function is invoked. ","category":"page"},{"location":"manual/utilities/callback/#A-Simple-Example","page":"Callback","title":"A Simple Example","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Let's define a test object first that has a field named x of type Int and named callback of type Callback. ","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> mutable struct TestObject\n x::Int\n callback::Callback\n end","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"To construct an instance of TestObject, we need to construct a Callback. For that purpose, the condition and action function must be defined. For this example, condition checks whether the x field is positive, and action prints a simple message saying that the x field is positive.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> condition(testobject) = testobject.x > 0 \ncondition (generic function with 1 method)\n\njulia> action(testobject) = println(\"testobject.x is greater than zero\") \naction (generic function with 1 method)","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now a test object can be constructed","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject = TestObject(-1, Callback(condition, action)) \nTestObject(-1, Callback{typeof(condition),typeof(action)}(condition, action, true, \"dac6f9eb-6daa-4622-a8fa-623f0f88780c\"))","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"If the callback is called, no action is performed since the condition function returns false. Note the argument sent to the callback. The instance of the TestObject to which the callback is bound.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.callback(testobject) ","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now mutate the test object so that condition returns true.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.x = 3 \n3","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Now, if the callback is called, since the condition returns true and the callback is enabled, the action is invoked.","category":"page"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"julia> testobject.callback(testobject) \ntestobject.x is greater than zero","category":"page"},{"location":"manual/utilities/callback/#Full-API","page":"Callback","title":"Full API","text":"","category":"section"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Callback","category":"page"},{"location":"manual/utilities/callback/#Jusdl.Callback","page":"Callback","title":"Jusdl.Callback","text":"Callback(condition, action)\n\nConstructs a Callback from condition and action. The condition and action must be a single-argument function. The condition returns true if the condition it checks occurs, otherwise, it returns false. action performs the specific action for which the Callback is constructed. A Callback can be called by passing its single argument which is mostly bound to the Callback.\n\nExample\n\njulia> struct Object # Define a dummy type.\n x::Int \n clb::Callback \n end\n\njulia> cond(obj) = obj.x > 0; # Define callback condition.\n\njulia> action(obj) = println(\"obj.x = \", obj.x); # Define callback action.\n\njulia> obj = Object(1, Callback(condition=cond, action=action))\nObject(1, Callback(condition:cond, action:action))\n\njulia> obj.clb(obj) # Call the callback bound `obj`.\nobj.x = 1\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/callback/","page":"Callback","title":"Callback","text":"Modules = [Jusdl]\nPages = [\"callback.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/utilities/callback/#Jusdl.applycallbacks-Tuple{Any}","page":"Callback","title":"Jusdl.applycallbacks","text":"applycallbacks(obj)\n\nCalls the callbacks of obj if the callbacks are not nothing.\n\nExample\n\njulia> mutable struct MyType{CB}\n x::Int\n callbacks::CB\n end\n\njulia> obj = MyType(5, Callback(condition=obj -> obj.x > 0, action=obj -> println(\"x is positive\")));\n\njulia> applycallbacks(obj)\nx is positive\n\njulia> obj.x = -1\n-1\n\njulia> applycallbacks(obj)\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Jusdl.disable!-Tuple{Callback}","page":"Callback","title":"Jusdl.disable!","text":"disable!(clb::Callback)\n\nDisables clb.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Jusdl.enable!-Tuple{Callback}","page":"Callback","title":"Jusdl.enable!","text":"enable!(clb::Callback)\n\nEnables clb.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/callback/#Jusdl.isenabled-Tuple{Callback}","page":"Callback","title":"Jusdl.isenabled","text":"isenabled(clb::Callback)\n\nReturns true if clb is enabled. Otherwise, returns false.\n\n\n\n\n\n","category":"method"},{"location":"tutorials/defining_new_components/#Defining-New-Component-Types","page":"Extending Component Library","title":"Defining New Component Types","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Jusdl provides a library that includes some well-known components that are ready to be used. For example,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"FunctionGenerator, SinewaveGenerator, SquarewaveGenerator, RampGenerator, etc. as sources\nStaticSystem, Adder, Multiplier, Gain, etc. as static systems\nDiscreteSystem, DiscreteLinearSystem, HenonSystem, LogisticSystem, etc. as dynamical systems represented by discrete difference equations.\nODESystem, LorenzSystem, ChenSystem, ChuaSystem, etc. as dynamical systems represented by ODEs.\nDAESystem, RobertsonSystem, etc. as dynamical systems represented by dynamical systems represented by DAEs.\nRODESystem, MultiplicativeNoiseLinearSystem, etc. as dynamical systems represented by dynamical systems represented by RODEs.\nSDESystem, NoisyLorenzSystem, ForcedNoisyLorenzSystem, etc. as dynamical systems represented by dynamical systems represented by SDEs.\nDDESystem, DelayFeedbackSystem, etc. as dynamical systems represented by dynamical systems represented by DDEs.\nWriter, Printer, Scope, etc. as sinks.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"It is very natural that this library may lack some of the components that are wanted to be used by the user. In such a case, Jusdl provides the users with the flexibility to enrich this library. The users can define their new component types, including source, static system, dynamical system, sink and use them with ease. ","category":"page"},{"location":"tutorials/defining_new_components/#Defining-A-New-Source","page":"Extending Component Library","title":"Defining A New Source","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"New source types are defines using @def_source macro. Before embarking on defining new source, let us get the necessary information on how to use @def_source. This can be can be obtained through its docstrings. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"using Jusdl # hide \n@doc @def_source","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"From the docstring, its clear that new types of source can be defined as if we define a new Julia type. The difference is that the struct keyword is preceded by @def_source macro and the new component must be a subtype of AbstractSource. Also from the docstring is that the new type has some optional and mandatory fields. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"warning: Warning\nTo define a new source, mandatory fields must be defined. The optional fields are the parameters of the source.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"For example let us define a new source that generates waveforms of the form. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":" y(t) = \n beginbmatrix\n alpha sin(t) \n beta cos(t)\n endbmatrix","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Here alpha and beta is the system parameters. That is, while defining the new source component, alpha and beta are optional fields. readout and output are the mandatory field while defining a source. Note from above equation that the output of the new source has two pins. Thus, this new source component type, say MySource is defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_source struct MySource{RO, OP} <: AbstractSource \n α::Float64 = 1. \n β::Float64 = 2. \n readout::RO = (t, α=α, β=β) -> [α*sin(t), β*cos(t)]\n output::OP = Outport(2)\nend","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Note that the syntax is very similar to the case in which we define a normal Julia type. We start with struct keyword preceded with @def_source macro. In order for the MySource to work flawlessly, i.e. to be used a model component, it must a subtype of AbstractSource. The readout function of MySource is a function of t and the remaining parameters, i.e., alpha and beta, are passed into as optional arguments to avoid global variables. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"One other important point to note is that the MySource has additional fields that are required for it to work as a regular model component. Let us print all the field names of MySource, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"fieldnames(MySource)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"We know that we defined the fields α, β, readout, output, but, the fields trigger, callback, handshake, callbacks, name, id are defined automatically by @def_source macro. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Since the type MySource has been defined, any instance of it can be constructed. Let us see the constructors first.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"methods(MySource)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The constructor with the keyword arguments is very much easy to uses. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"gen1 = MySource()\ngen2 = MySource(α=4.)\ngen3 = MySource(α=4., β=5.)\ngen3 = MySource(α=4., β=5., name=:mygen)\ngen3.trigger \ngen3.id \ngen3.α\ngen3.β\ngen3.output","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"An instance works flawlessly as a model component, that is, it can be driven from its trigger pin and signalling cane be carried out from its handshake pin. To see this, let us construct required pins and ports to drive a MySource instance. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"gen = MySource() # `MySource` instance \ntrg = Outpin() # To trigger `gen`\nhnd = Inpin{Bool}() # To signalling with `gen`\niport = Inport(2) # To take values out of `gen` \nconnect!(trg, gen.trigger); \nconnect!(gen.handshake, hnd);\nconnect!(gen.output, iport);\nlaunch(gen) # Launch `gen,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Now gen can be driven through trg pin. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"put!(trg, 1.) # Drive `gen` for `t=1`.\ntake!(iport) # Read output of `gen` from `iport`\ntake!(hnd) # Approve `gen` has taken a step.","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Thus, by using @def_source macro, it is possible for the users to define any type of sources under AbstractSource type and user them without a hassle. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The procedure is again the same for any other component types. The table below lists the macros that are used to define new component types. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Macro Component Type Supertype Mandatory Field Names\n@def_source Source AbstractSource readout, output\n@def_static_system StaticSystem AbstractStaticSystem readout, output, input\n@def_discrete_system Discrete Dynamic System AbstractDiscreteSystem righthandside, readout, state, input, output\n@def_ode_system ODE Dynamic System AbstractODESystem righthandside, readout, state, input, output\n@def_dae_system DAE Dynamic System AbstractDAESystem righthandside, readout, state, stateder, diffvars, input, output\n@def_rode_system RODE Dynamic System AbstractRODESystem righthandside, readout, state, input, output\n@def_sde_system SDE Dynamic System AbstractSDESystem drift, diffusion, readout, state, input, output\n@def_dde_system DDE Dynamic System AbstractDDESystem constlags, depslags, righthandside, history, readout, state, input, output\n@def_sink Sink AbstractSink action","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The steps followed in the previous section are the same to define other component types: start with suitable macro given above, make the newly-defined type a subtype of the corresponding supertype, define the optional fields (if exist) ands define the mandatory fields of the new type (with the default values if necessary).","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-StaticSystem","page":"Extending Component Library","title":"Defining New StaticSystem","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Consider the following readout function of the static system to be defined ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"y = u_1 t + a cos(u_2)","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"where u = u_1 u_2 is the input, y is the output of the system and t is time. The system has two inputs and one output. This system can be defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_static_system struct MyStaticSystem{RO, IP, OP} <: AbstractStaticSystem\n a::Float64 = 1.\n readout::RO = (t, a = a) -> u[1] * t + a * cos(u[2])\n input::IP = Inport(2)\n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-Discrete-Dynamical-System","page":"Extending Component Library","title":"Defining New Discrete Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The discrete dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\nx_k + 1 = α x_k + u_k 025cm\ny_k = x_k\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_discrete_system struct MyDiscreteSystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-ODE-Dynamical-System","page":"Extending Component Library","title":"Defining New ODE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The ODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndotx = α x + u 025cm\ny = x\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_ode_system struct MyODESystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-New-DAE-Dynamical-System","page":"Extending Component Library","title":"Defining New DAE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The DAE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarray\ndx = x + 1 025cm\n0 = 2(x + 1) + 2\nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_dae_system mutable struct MyDAESystem{RH, RO, ST, IP, OP} <: AbstractDAESystem\n righthandside::RH = function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end \n readout::RO = (x,u,t) -> x \n state::ST = [1., -1]\n stateder::ST = [2., 0]\n diffvars::Vector{Bool} = [true, false]\n input::IP = nothing \n output::OP = Outport(1)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-RODE-Dynamical-System","page":"Extending Component Library","title":"Defining RODE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The RODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndotx = A x W 025cm\ny = x \nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"where ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"A = beginbmatrix\n 2 0 \n 0 -2\nendbmatrix","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as, ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_rode_system struct MyRODESystem{RH, RO, IP, OP} <: AbstractRODESystem\n A::Matrix{Float64} = [2. 0.; 0 -2]\n righthandside::RH = (dx, x, u, t, W) -> (dx .= A * x * W)\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(2) \n input::IP = nothing \n output::OP = Outport(2)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-SDE-Dynamical-System","page":"Extending Component Library","title":"Defining SDE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The RODE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"beginarrayl\ndx = -x dt + dW 025cm\ny = x \nendarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_sde_system mutable struct MySDESystem{DR, DF, RO, ST, IP, OP} <: AbstractSDESystem\n drift::DR = (dx, x, u, t) -> (dx .= -x)\n diffusion::DF = (dx, x, u, t) -> (dx .= 1)\n readout::RO = (x, u, t) -> x \n state::ST = [1.] \n input::IP = nothing\n output::OP = Outport(1)\nend ","category":"page"},{"location":"tutorials/defining_new_components/#Defining-DDE-Dynamical-System","page":"Extending Component Library","title":"Defining DDE Dynamical System","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"The DDE dynamical system given by ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":" beginarrayl\n dotx = -x(t - tau) quad t geq 0 \n x(t) = 1 -tau leq t leq 0 \n endarray","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"can be defined as,","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"_delay_feedback_system_cache = zeros(1)\n_delay_feedback_system_tau = 1.\n_delay_feedback_system_constlags = [1.]\n_delay_feedback_system_history(cache, u, t) = (cache .= 1.)\nfunction _delay_feedback_system_rhs(dx, x, h, u, t, \n cache=_delay_feedback_system_cache, τ=_delay_feedback_system_tau)\n h(cache, u, t - τ) # Update cache \n dx[1] = cache[1] + x[1]\nend\n@def_dde_system mutable struct DelayFeedbackSystem{RH, HST, RO, IP, OP} <: AbstractDDESystem\n constlags::Vector{Float64} = _delay_feedback_system_constlags\n depslags::Nothing = nothing\n righthandside::RH = _delay_feedback_system_rhs\n history::HST = _delay_feedback_system_history\n readout::RO = (x, u, t) -> x \n state::Vector{Float64} = rand(1)\n input::IP = nothing \n output::OP = Outport(1)\nend","category":"page"},{"location":"tutorials/defining_new_components/#Defining-Sinks","page":"Extending Component Library","title":"Defining Sinks","text":"","category":"section"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"Say we want a sink type that takes the data flowing through the connections of the model and prints it. This new sink type cane be defined as follows. ","category":"page"},{"location":"tutorials/defining_new_components/","page":"Extending Component Library","title":"Extending Component Library","text":"@def_sink struct MySink{A} <: AbstractSink\n action::A = actionfunc\nend\nactionfunc(sink::MySink, t, u) = println(t, u)","category":"page"},{"location":"manual/components/componentsbase/hierarchy/#Component-Type-Hierarchy","page":"Component Type Hierarchy","title":"Component Type Hierarchy","text":"","category":"section"},{"location":"manual/components/componentsbase/hierarchy/","page":"Component Type Hierarchy","title":"Component Type Hierarchy","text":"AbstractComponent \nAbstractSource \nAbstractSystem \nAbstractSink \nAbstractStaticSystem \nAbstractDynamicSystem \nAbstractSubSystem \nAbstractMemory \nAbstractDiscreteSystem\nAbstractODESystem\nAbstractRODESystem \nAbstractDAESystem \nAbstractSDESystem \nAbstractDDESystem ","category":"page"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractComponent","page":"Component Type Hierarchy","title":"Jusdl.AbstractComponent","text":"abstract type AbstractComponent\n\nAbstract type of all components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractSource","page":"Component Type Hierarchy","title":"Jusdl.AbstractSource","text":"abstract type AbstractSource <: AbstractComponent\n\nAbstract typeof all source components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractSystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractSystem","text":"abstract type AbstractSystem <: AbstractComponent\n\nAbstract type of all system components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractSink","page":"Component Type Hierarchy","title":"Jusdl.AbstractSink","text":"abstract type AbstractSink <: AbstractComponent\n\nAbstract type of all sink components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractStaticSystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractStaticSystem","text":"abstract type AbstractStaticSystem <: AbstractSystem\n\nAbstract type of all static systems\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractDynamicSystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractDynamicSystem","text":"abstract type AbstractDynamicSystem <: AbstractSystem\n\nAbstract type of all dynamic system components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractSubSystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractSubSystem","text":"abstract type AbstractSubSystem <: AbstractSystem\n\nAbstract type of all subsystem components \n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractMemory","page":"Component Type Hierarchy","title":"Jusdl.AbstractMemory","text":"abstract type AbstractMemory <: AbstractStaticSystem\n\nAbstract type of all memory components\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractDiscreteSystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractDiscreteSystem","text":"abstract type AbstractDiscreteSystem <: AbstractDynamicSystem\n\nAbstract type of all dynamic systems modelled by dicrete difference equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractODESystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractODESystem","text":"abstract type AbstractODESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by ordinary differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractRODESystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractRODESystem","text":"abstract type AbstractRODESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by random ordinary differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractDAESystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractDAESystem","text":"abstract type AbstractDAESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by differential algebraic equations\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractSDESystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractSDESystem","text":"abstract type AbstractSDESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modelled by stochastic differential equations.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/hierarchy/#Jusdl.AbstractDDESystem","page":"Component Type Hierarchy","title":"Jusdl.AbstractDDESystem","text":"abstract type AbstractDDESystem <: AbstractDynamicSystem\n\nAbstract type of all dynamical systems modlled by delay dynamical systems.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops","page":"Algebraic Loops","title":"Breaking Algebraic Loops","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"It this tutorial, we will simulate model consisting a closed loop feedback system. The model has an algebraic loop. ","category":"page"},{"location":"tutorials/algebraic_loops/#Algebraic-Loops","page":"Algebraic Loops","title":"Algebraic Loops","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. If algebraic loops exist in a model, the simulation gets stuck because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Jusdl provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops. ","category":"page"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops-Automatically","page":"Algebraic Loops","title":"Breaking Algebraic Loops Automatically","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Before initializing and running the simulation, Jusdl inspects the model first. See Simulation Stages for more information of simulation stages. In case the they exist in the model, all the algebraic loops are tried to be broken automatically without requiring a user intervention. Consider the following model ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"where ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"beginarrayl\n r(t) = t 025cm\n u(t) = r(t) - y(t) 025cm\n y(t) = u(t) \nendarray","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Note that there exist an algebraic loop consisting of adder and gain. Solving this algebraic loop, we have ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":" y(t) = u(t) = r(t) - y(t) quad Rightarrow quad y(t) = dfracr(t)2 = dfract2","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"The following script constructs and simulates the model. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Jusdl \n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nti, dt, tf = 0., 1. / 64., 1.\nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Read the simulation data and plot \nusing Plots\nt, y = read(getnode(model, :writerout).component)\nt, r = read(getnode(model, :writerin).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3)) \nplot!(t, y, label=\"y(t)\", marker=(:circle, 3)) \nsavefig(\"breaking_algebraic_loops_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: )","category":"page"},{"location":"tutorials/algebraic_loops/#Breaking-Algebraic-Loops-With-a-Memory","page":"Algebraic Loops","title":"Breaking Algebraic Loops With a Memory","text":"","category":"section"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"It is also possible to break algebraic loops by inserting a Memory component at some point the loop. For example, consider the model consider following the model which is the model in which a memory component is inserted in the feedback path. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"Note that the input to adder is not y(t), but instead is haty(t) which is one sample delayed form of y(t). That is, we have, haty(t) = y(t - dt) where dt is the step size of the simulation. If dt is small enough, haty(t) approx y(t).","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"The script given below simulates this case. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Jusdl \n\n# Simulation time settings.\nti, dt, tf = 0., 1. / 64., 1.\n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n mem = Memory(delay=dt, initial=zeros(1))\n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => mem[1]\n mem[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Plot the simulation data\nusing Plots\nt, r = read(getnode(model, :writerin).component)\nt, y = read(getnode(model, :writerout).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3))\nplot!(t, y, label=\"y(t)\", marker=(:circle, 3))\nsavefig(\"breaking_algebraic_loops_with_memory_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: ) The fluctuation in y(t) because of one-sample-time delay introduced by the mem component is apparent. The smaller the step size is, the smaller the amplitude of the fluctuation introduced by the mem component. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"One other important issue with using the memory component is that the initial value of mem directly affects the accuracy of the simulation. By solving the loop equation, we know that ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":" y(t) = dfracr(t)2 = dfract2 quad Rightarrow quad y(0) = 0","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"That is the memory should be initialized with an initial value of zero, which is the case in the script above. To observe that how incorrect initialization of a memory to break an algebraic loop, consider the following example in which memory is initialized randomly. ","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"using Jusdl \nusing Plots \n\n# Simulation time settings.\nti, dt, tf = 0., 1. / 64., 1.\n\n# Describe the model\n@defmodel model begin \n @nodes begin\n gen = RampGenerator()\n adder = Adder(signs=(+,-))\n gain = Gain()\n writerout = Writer() \n writerin = Writer() \n mem = Memory(delay=dt, initial=rand(1))\n end\n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => mem[1]\n mem[1] => adder[2]\n gen[1] => writerin[1]\n gain[1] => writerout[1]\n end\nend\n\n# Simulate the model \nsim = simulate!(model, ti, dt, tf, withbar=false)\n\n# Plot the results \nusing Plots\nt, r = read(getnode(model, :writerin).component)\nt, y = read(getnode(model, :writerout).component)\nplot(t, r, label=\"r(t)\", marker=(:circle, 3))\nplot!(t, y, label=\"y(t)\", marker=(:circle, 3))\nsavefig(\"breaking_algebraic_loops_with_memory_incorrect_plot1.svg\"); nothing # hide","category":"page"},{"location":"tutorials/algebraic_loops/","page":"Algebraic Loops","title":"Algebraic Loops","text":"(Image: )","category":"page"},{"location":"manual/components/sources/generators/#Generators","page":"Generators","title":"Generators","text":"","category":"section"},{"location":"manual/components/sources/generators/#Basic-Operation-AbstractSource","page":"Generators","title":"Basic Operation AbstractSource","text":"","category":"section"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"using Jusdl # hide \nf(t) = t * exp(t) + sin(t)\ngen = FunctionGenerator(readout=f)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"We constructed a FunctionGenerator which is an AbstractSource.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen isa AbstractSource","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"trg, hnd, iport = Outpin(), Inpin{Bool}(), Inport(length(gen.output))\nconnect!(gen.output, iport)\nconnect!(trg, gen.trigger) \nconnect!(gen.handshake, hnd)\nt = launch(gen)\ntout = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"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. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen.trigger.link\ngen.output[1].links[1]","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen is triggered by writing time t to trg","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"When triggered gen writes true to its handshake link gen.handshake which can be read from hnd.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"hnd.link","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"and to drive gen for another time hnd must be read. ","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"take!(hnd)","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"Now continue driving gen.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"for t in 2. : 10.\n put!(trg, t)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"When triggered, the output of gen is written to its output gen.output.","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"gen.output[1].links[1].buffer","category":"page"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"Jusdl provides some other function generators which are documented in the following section.","category":"page"},{"location":"manual/components/sources/generators/#Full-API","page":"Generators","title":"Full API","text":"","category":"section"},{"location":"manual/components/sources/generators/","page":"Generators","title":"Generators","text":"@def_source \nFunctionGenerator\nSinewaveGenerator \nDampedSinewaveGenerator \nSquarewaveGenerator \nTriangularwaveGenerator \nConstantGenerator \nRampGenerator \nStepGenerator \nExponentialGenerator \nDampedExponentialGenerator ","category":"page"},{"location":"manual/components/sources/generators/#Jusdl.@def_source","page":"Generators","title":"Jusdl.@def_source","text":"@def_source ex\n\nwhere ex is the expression to define to define a new AbstractSource component type. The usage is as follows:\n\n@def_source struct MySource{T1,T2,T3,...,TN,OP, RO} <: AbstractSource\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n output::OP = output_default # mandatory field \n readout::RO = readout_function # mandatory field\nend\n\nHere, MySource has N parameters, an output port and a readout function.\n\nwarning: Warning\noutput and readout are mandatory fields to define a new source. The rest of the fields are the parameters of the source.\n\nwarning: Warning\nreadout must be a single-argument function, i.e. a fucntion of time t.\n\nwarning: Warning\nNew source must be a subtype of AbstractSource to function properly.\n\nExample\n\njulia> @def_source struct MySource{OP, RO} <: AbstractSource\n a::Int = 1 \n b::Float64 = 2. \n output::OP = Outport() \n readout::RO = t -> (a + b) * sin(t)\n end\n\njulia> gen = MySource();\n\njulia> gen.a \n1\n\njulia> gen.output\n1-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/sources/generators/#Jusdl.FunctionGenerator","page":"Generators","title":"Jusdl.FunctionGenerator","text":"FunctionGenerator(; readout, output=Outport())\n\nConstructs a generic function generator with readout function and output port.\n\nExample\n\njulia> gen = FunctionGenerator(readout = t -> [t, 2t], output = Outport(2));\n\njulia> gen.readout(1.)\n2-element Array{Float64,1}:\n 1.0\n 2.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.SinewaveGenerator","page":"Generators","title":"Jusdl.SinewaveGenerator","text":"SinewaveGenerator(;amplitude=1., frequency=1., phase=0., delay=0., offset=0.)\n\nConstructs a SinewaveGenerator with output of the form\n\n x(t) = A sin(2 pi f (t - tau) + phi) + B\n\nwhere A is amplitude, f is frequency, tau is delay and phi is phase and B is offset.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.DampedSinewaveGenerator","page":"Generators","title":"Jusdl.DampedSinewaveGenerator","text":"DampedSinewaveGenerator(;amplitude=1., decay=-0.5, frequency=1., phase=0., delay=0., offset=0.)\n\nConstructs a DampedSinewaveGenerator which generates outputs of the form \n\n x(t) = A e^alpha t sin(2 pi f (t - tau) + phi) + B\n\nwhere A is amplitude, alpha is decay, f is frequency, phi is phase, tau is delay and B is offset.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.SquarewaveGenerator","page":"Generators","title":"Jusdl.SquarewaveGenerator","text":"SquarewaveGenerator(;level1=1., level2=0., period=1., duty=0.5, delay=0.)\n\nConstructs a SquarewaveGenerator with output of the form \n\n x(t) = leftbeginarraylr\n\tA_1 + B kT + tau leq t leq (k + alpha) T + tau \n\tA_2 + B (k + alpha) T + tau leq t leq (k + 1) T + tau\t\n\tendarray right quad k in Z\n\nwhere A_1, A_2 is level1 and level2, T is period, tau is delay alpha is duty. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.TriangularwaveGenerator","page":"Generators","title":"Jusdl.TriangularwaveGenerator","text":"TriangularwaveGenerator(;amplitude=1, period=1, duty=0.5, delay=0, offset=0)\n\nConstructs a TriangularwaveGenerator with output of the form\n\n x(t) = leftbeginarraylr\n\tdfracA talpha T + B kT + tau leq t leq (k + alpha) T + tau 025cm\n\tdfracA (T - t)T (1 - alpha) + B (k + alpha) T + tau leq t leq (k + 1) T + tau\t\n\tendarray right quad k in Z\n\nwhere A is amplitude, T is period, tau is delay alpha is duty. \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.ConstantGenerator","page":"Generators","title":"Jusdl.ConstantGenerator","text":"ConstantGenerator(;amplitude=1.)\n\nConstructs a ConstantGenerator with output of the form\n\n x(t) = A\n\nwhere A is `amplitude.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.RampGenerator","page":"Generators","title":"Jusdl.RampGenerator","text":"RampGenerator(;scale=1, delay=0.)\n\nConstructs a RampGenerator with output of the form\n\n x(t) = alpha (t - tau)\n\nwhere alpha is the scale and tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.StepGenerator","page":"Generators","title":"Jusdl.StepGenerator","text":"StepGenerator(;amplitude=1, delay=0, offset=0)\n\nConstructs a StepGenerator with output of the form \n\n x(t) = leftbeginarraylr\n\tB t leq tau \n\tA + B t tau\n\tendarray right\n\nwhere A is amplitude, B is the offset and tau is the delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.ExponentialGenerator","page":"Generators","title":"Jusdl.ExponentialGenerator","text":"ExponentialGenerator(;scale=1, decay=-1, delay=0.)\n\nConstructs an ExponentialGenerator with output of the form\n\n x(t) = A e^alpha (t - tau)\n\nwhere A is scale, alpha is decay and tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/generators/#Jusdl.DampedExponentialGenerator","page":"Generators","title":"Jusdl.DampedExponentialGenerator","text":"DampedExponentialGenerator(;scale=1, decay=-1, delay=0.)\n\nConstructs an DampedExponentialGenerator with outpsuts of the form \n\n x(t) = A (t - tau) e^alpha (t - tau)\n\nwhere A is scale, alpha is decay, tau is delay.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/taskmanager/#Task-Manager","page":"Task Manager","title":"Task Manager","text":"","category":"section"},{"location":"manual/models/taskmanager/","page":"Task Manager","title":"Task Manager","text":"A TaskManager is actually the pairs of components and the tasks constructed corresponding to those components. In Jusdl, models are simulated by individually evolving the components. This individual evolution of components is performed by defining components individually and constructing tasks for each components. The jobs that are defined in these tasks are defined to make the components evolve by reading its time, input, compute its output. During this evolution, the tasks may fail because any inconsistency. Right after the failure of a task, its not possible for the component corresponding to the task to evolve any more. As the data flows through the components that connects the components, model simulation gets stuck. To keep track of the task launched for each component, a TaskManager is used. Before starting to simulate a model, a TaskManager is constructed for the model components. During the initialization of simulation, tasks corresponding to the components of the model is launched and the pair of component and component task is recorded in the TaskManager of the model. During the run stage of the simulation, TaskManager keeps track of the component tasks. In case any failure in components tasks, the cause of the failure can be investigated with TaskManager.","category":"page"},{"location":"manual/models/taskmanager/#Full-API","page":"Task Manager","title":"Full API","text":"","category":"section"},{"location":"manual/models/taskmanager/","page":"Task Manager","title":"Task Manager","text":"Modules = [Jusdl]\nPages = [\"taskmanager.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/taskmanager/#Jusdl.TaskManager","page":"Task Manager","title":"Jusdl.TaskManager","text":"TaskManager(pairs)\n\nConstructs a TaskManager with pairs. pairs is a dictionary whose keys are components and values are component tasks. Component tasks are constructed correponding to the components. A TaskManager is used to keep track of the component task launched corresponding to components.\n\nTaskManager()\n\nConstructs a TaskManager with empty pairs. ```\n\n\n\n\n\n","category":"type"},{"location":"manual/models/taskmanager/#Jusdl.checktaskmanager-Tuple{TaskManager}","page":"Task Manager","title":"Jusdl.checktaskmanager","text":"checktaskmanager(tm::TaskManager)\n\nThrows an error if any of the component task of tm is failed. See also: TaskManager\n\n\n\n\n\n","category":"method"},{"location":"manual/models/taskmanager/#Jusdl.istaskrunning","page":"Task Manager","title":"Jusdl.istaskrunning","text":"istaskrunning(task::Task)\n\nReturns true is the state of task is runnable. \n\nistaskrunning(task::Nothing)\n\nReturns true\n\nistaskrunning(comptask::ComponentTask)\n\nReturns true if triggertask and outputtask of comptask is running. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Evolution-of-Components","page":"Evolution of Components","title":"Evolution of Components","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"In Jusdl, the simulation of a model is performed by individual evolution of components (see Modeling and Simulation for more information of modeling and simulation adopted in Jusdl). Basically, when triggered through its trigger pin, based on its type, a component takes a forward step as follows, ","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"The next clock time t is read from its trigger pin.\nThe next input value u(t) is read from from its input port, \nThe component evolves from its current time t - dt to the current clock time t\nUsing the state variable x(t) at time t, current clock time t and u(t), the next output value y(t) is computed. \nThe component writes true to its handshake pin to signal that taking step is performed with success.","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"or a backward step as follows. ","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"The next clock time t is read from its trigger pin.\nUsing the state variable x(t - dt) at time t - dt, current component time t - dt and u(t - dt), the next output value y(t) is computed. \nThe next input value u(t) is read from from its input port, \nThe component evolves from its current time t - dt to the current clock time t\nThe component writes true to its handshake pin to signal that taking step is performed with success.","category":"page"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"Here dt is the simulation step size. ","category":"page"},{"location":"manual/components/componentsbase/evolution/#Reading-Time","page":"Evolution of Components","title":"Reading Time","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readtime!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.readtime!","page":"Evolution of Components","title":"Jusdl.readtime!","text":"readtime!(comp::AbstractComponent)\n\nReturns current time of comp read from its trigger link.\n\nnote: Note\nTo read time of comp, comp must be launched. See also: launch(comp::AbstractComponent).\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Reading-State","page":"Evolution of Components","title":"Reading State","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readstate","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.readstate","page":"Evolution of Components","title":"Jusdl.readstate","text":"readstate(comp::AbstractComponent)\n\nReturns the state of comp if comp is AbstractDynamicSystem. Otherwise, returns nothing. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Reading-Input","page":"Evolution of Components","title":"Reading Input","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"readinput!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.readinput!","page":"Evolution of Components","title":"Jusdl.readinput!","text":"readinput!(comp::AbstractComponent)\n\nReturns the input value of comp if the input of comp is Inport. Otherwise, returns nothing.\n\nnote: Note\nTo read input value of comp, comp must be launched. See also: launch(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Writing-Output","page":"Evolution of Components","title":"Writing Output","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"writeoutput!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.writeoutput!","page":"Evolution of Components","title":"Jusdl.writeoutput!","text":"writeoutput!(comp::AbstractComponent, out)\n\nWrites out to the output of comp if the output of comp is Outport. Otherwise, does nothing.\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Computing-Output","page":"Evolution of Components","title":"Computing Output","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"computeoutput ","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.computeoutput","page":"Evolution of Components","title":"Jusdl.computeoutput","text":"computeoutput(comp, x, u, t)\n\nComputes the output of comp according to its readout if readout is not nothing. Otherwise, nothing is done. x is the state, u is the value of input, t is the time. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Evolve","page":"Evolution of Components","title":"Evolve","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"evolve!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.evolve!","page":"Evolution of Components","title":"Jusdl.evolve!","text":"evolve!(comp::AbstractSource, u, t)\n\nDoes nothing. u is the value of input and t is time.\n\nevolve!(comp::AbstractSink, u, t)\n\nWrites t to time buffer timebuf and u to databuf of comp. u is the value of input and t is time.\n\nevolve!(comp::AbstractStaticSystem, u, t)\n\nWrites u to buffer of comp if comp is an AbstractMemory. Otherwise, nothing is done. u is the value of input and t is time. \n\nevolve!(comp::AbstractDynamicSystem, u, t)\n\nSolves the differential equation of the system of comp for the time interval (comp.t, t) for the inital condition x where x is the current state of comp . u is the input function defined for (comp.t, t). The comp is updated with the computed state and time t. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Taking-Steps","page":"Evolution of Components","title":"Taking Steps","text":"","category":"section"},{"location":"manual/components/componentsbase/evolution/","page":"Evolution of Components","title":"Evolution of Components","text":"takestep!\nJusdl.forwardstep\nJusdl.backwardstep\nlaunch(comp::AbstractComponent)\nlaunch(comp::AbstractSubSystem)\ndrive!\napprove!\nterminate!","category":"page"},{"location":"manual/components/componentsbase/evolution/#Jusdl.takestep!","page":"Evolution of Components","title":"Jusdl.takestep!","text":"takestep!(comp::AbstractComponent)\n\nReads the time t from the trigger link of comp. If comp is an AbstractMemory, a backward step is taken. Otherwise, a forward step is taken. See also: forwardstep, backwardstep.\n\n\n\n\n\ntakestep!(comp::AbstractSubSystem)\n\nMakes comp to take a step by making each subcomponent of comp take a step. See also: takestep!(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Jusdl.forwardstep","page":"Evolution of Components","title":"Jusdl.forwardstep","text":"forwardstep(comp, t)\n\nMakes comp takes a forward step. The input value u and state x of comp are read. Using x, u and time t, comp is evolved. The output y of comp is computed and written into the output bus of comp. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Jusdl.backwardstep","page":"Evolution of Components","title":"Jusdl.backwardstep","text":"backwardstep(comp, t)\n\nReads the state x. Using the time t and x, computes and writes the ouput value y of comp. Then, the input value u is read and comp is evolved. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Jusdl.launch-Tuple{AbstractComponent}","page":"Evolution of Components","title":"Jusdl.launch","text":"launch(comp::AbstractComponent)\n\nReturns a tuple of tasks so that trigger link and output bus of comp is drivable. When launched, comp is ready to be driven from its trigger link. See also: drive!(comp::AbstractComponent, t)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/componentsbase/evolution/#Jusdl.launch-Tuple{AbstractSubSystem}","page":"Evolution of Components","title":"Jusdl.launch","text":"launch(comp::AbstractSubSystem)\n\nLaunches all subcomponents of comp. See also: launch(comp::AbstractComponent)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/componentsbase/evolution/#Jusdl.drive!","page":"Evolution of Components","title":"Jusdl.drive!","text":"drive!(comp::AbstractComponent, t)\n\nWrites t to the trigger link of comp. When driven, comp takes a step. See also: takestep!(comp::AbstractComponent)\n\n\n\n\n\ndrive!(comp::AbstractSubSystem, t)\n\nDrives comp by driving each subcomponent of comp. See also: drive!(comp::AbstractComponent, t)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Jusdl.approve!","page":"Evolution of Components","title":"Jusdl.approve!","text":"approve!(comp::AbstractComponent)\n\nRead handshake link of comp. When not approved or false is read from the handshake link, the task launched for the trigger link of comp gets stuck during comp is taking step.\n\n\n\n\n\napprove!(comp::AbstractSubSystem)\n\nApproves comp by approving each subcomponent of comp. See also: approve!(comp::AbstractComponent)\n\n\n\n\n\n","category":"function"},{"location":"manual/components/componentsbase/evolution/#Jusdl.terminate!","page":"Evolution of Components","title":"Jusdl.terminate!","text":"terminate!(comp::AbstractComponent)\n\nCloses the trigger link and output bus of comp.\n\n\n\n\n\nterminate!(comp::AbstractSubSystem)\n\nTerminates comp by terminating each subcomponent of comp. See also: terminate!(comp::AbstractComponent)\n\n\n\n\n\nterminate!(model::Model)\n\nTerminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.\n\n\n\n\n\n","category":"function"},{"location":"manual/plugins/plugins/#Plugins","page":"Plugins","title":"Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Plugins are extensions that are used to process online the data flowing through the connections of the model during the simulation. These tools are specialized tools that are used for specialized data processing. In addition to the plugins that are provided by Jusdl, it is also possible to write new plugins that focus on different specialized data processing. The fundamental importance of Plugins is that they make the online simulation data processing possible. ","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"The Plugins are mostly used with Sinks. In Jusdl, the Sinks are used to sink simulation data flowing through the connections of the model. When a Sink is equipped with a proper Plugin according to the data processing desired, then the data flowing into the Sink is processed. For example, consider that a Writer is equipped with a Lyapunov plugin. During the simulation, data flowing into the Writer is processed to compute the maximum Lyapunov exponent, and these computed maximum Lyapunov exponents are recorded in the file of the Writer. Similarly, if a Printer is equipped with an Fft plugin, then Fast Fourier transform of the data flowing into the Printer is printed on the console.","category":"page"},{"location":"manual/plugins/plugins/#Data-processing-via-Plugins","page":"Plugins","title":"Data processing via Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Each Plugin must have a process function which does the data processing. The first argument of the process function is the Plugin and the second argument is the data to be processed. Here are some of the methods of process function","category":"page"},{"location":"manual/plugins/plugins/#Defining-New-Plugins","page":"Plugins","title":"Defining New Plugins","text":"","category":"section"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"New plugins can be defined in Jusdl and having they are defined properly they can work just expected. To define a new plugin, we must first define the plugin type ","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"using Jusdl # hide \nstruct NewPlugin <: AbstractPlugin\n # Parameters of NewPlugin\nend","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"warning: Warning\nNote that to the NewPlugin is defined to be a subtype of AbstractPlugin. This is important for the NewPlugin to work as expected.","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"Since each plugin must have implement a process method, and for that Jusdl.process function must be imported.","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"import Jusdl.process\nfunction process(plg::NewPlugin, x)\n # Define the process according to plg\nend","category":"page"},{"location":"manual/plugins/plugins/","page":"Plugins","title":"Plugins","text":"At this point, NewPlugin is ready to be used. ","category":"page"},{"location":"manual/models/simulation/#Simulation","page":"Simulation","title":"Simulation","text":"","category":"section"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"During the simulation of a model, a Simulation object is constructed. The field names of the Simulation object is ","category":"page"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"model::Model: The model for which the Simulation is constructed. \npath::String: The path of the directory into which all simulation-related files (log, data files etc.) are saved.\nlogger::AbstractLogger: The logger of the simulation constructed to log each stage of the Simulation . \nstate::Symbol: The state of the Simulation. The state may be :running if the simulation is running, :halted is the simulation is terminated without being completed, :done if it is terminated.\nretcode::Symbol: The return code of the simulation. The retcode may be :success if the simulation is completed without errors, :failed if the an error occurs during the simulation. ","category":"page"},{"location":"manual/models/simulation/#Full-API","page":"Simulation","title":"Full API","text":"","category":"section"},{"location":"manual/models/simulation/","page":"Simulation","title":"Simulation","text":"Modules = [Jusdl]\nPages = [\"simulation.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/simulation/#Jusdl.Simulation","page":"Simulation","title":"Jusdl.Simulation","text":"Simulation(model; simdir=tempdir(), simname=string(uuid4()), simprefix=\"Simulation-\", logger=SimpleLogger())\n\nConstructs a Simulation object for the simulation of model. The Simulation object is used to monitor the state of the simulation of the model. simdir is the path of the directory into which the simulation files(log, data files etc.) are recorded. simname is the name of the Simulation and simprefix is the prefix of the name of the Simulation. logger is used to log the simulation steps of the model. See also: Model, Logging\n\n\n\n\n\n","category":"type"},{"location":"manual/models/simulation/#Jusdl.SimulationError","page":"Simulation","title":"Jusdl.SimulationError","text":"SimulationError(msg::String)\n\nThrown when an error occurs during a simulation.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/simulation/#Jusdl.closelogger","page":"Simulation","title":"Jusdl.closelogger","text":"closelogger(logger=global_logger())\n\nCloses the logger the file of the loggger. See also: setlogger\n\n\n\n\n\n","category":"function"},{"location":"manual/models/simulation/#Jusdl.report-Tuple{Simulation}","page":"Simulation","title":"Jusdl.report","text":"report(simulation::Simulation)\n\nRecords the state of the simulation by writing all its fields into a data file. All the fields of the simulation is written into file. When the file is read back, the simulation object is constructed back. The data file is written under the path of the simulation.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/simulation/#Jusdl.setlogger-Tuple{AbstractString,AbstractString}","page":"Simulation","title":"Jusdl.setlogger","text":"setlogger(path, name; setglobal::Bool=true)\n\nReturns a logger. path is the path and name is the name of the file of the logger. If setglobal is true, the returned logger is a global logger.\n\nExample\n\njulia> logger = setlogger(tempdir(), \"mylogger\", setglobal=true)\nBase.CoreLogging.SimpleLogger(IOStream(), Info, Dict{Any,Int64}())\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Scope","page":"Scope","title":"Scope","text":"","category":"section"},{"location":"manual/components/sinks/scope/#Basic-Operation-of-Scopes","page":"Scope","title":"Basic Operation of Scopes","text":"","category":"section"},{"location":"manual/components/sinks/scope/","page":"Scope","title":"Scope","text":"See Basic Operation of Writers since the operation of Writer and that of Scope is very similar.","category":"page"},{"location":"manual/components/sinks/scope/#Full-API","page":"Scope","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/scope/","page":"Scope","title":"Scope","text":"Scope \nupdate!(s::Scope, x, yi)\nclose(sink::Scope)\nopen(sink::Scope)","category":"page"},{"location":"manual/components/sinks/scope/#Jusdl.Scope","page":"Scope","title":"Jusdl.Scope","text":"Scope(input=Inport(), args...; buflen::Int=64, plugin=nothing, callbacks=nothing, name=Symbol(), kwargs...)\n\nConstructs a Scope with input bus input. buflen is the length of the internal buffer of Scope. plugin is the additional data processing tool. args,kwargs are passed into plots(args...; kwargs...)). See (https://github.com/JuliaPlots/Plots.jl) for more information.\n\nwarning: Warning\nWhen initialized, the plot of Scope is closed. See open(sink::Scope) and close(sink::Scope).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/scope/#Jusdl.update!-Tuple{Scope,Any,Any}","page":"Scope","title":"Jusdl.update!","text":"update!(s::Scope, x, yi)\n\nUpdates the series of the plot windows of s with x and yi.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Base.close-Tuple{Scope}","page":"Scope","title":"Base.close","text":"close(sink::Scope)\n\nCloses the plot window of the plot of sink.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/scope/#Base.open-Tuple{Scope}","page":"Scope","title":"Base.open","text":"open(sink::Scope)\n\nOpens the plot window for the plots of sink.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#DiscreteSystem","page":"DiscreteSystem","title":"DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Construction-of-DiscreteSystem","page":"DiscreteSystem","title":"Construction of DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"DiscreteSystems evolve by the following discrete time difference equation.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":" x_k + 1 = f(x_k u_k k) \n y_k = g(x_k u_k k)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Basic-Construction-of-DiscreteSystem","page":"DiscreteSystem","title":"Basic Construction of DiscreteSystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We first define state function sfunc and output function ofunc of the system,","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"using Jusdl # hide \nsfunc(dx, x, u, t) = (dx .= -0.5x)\nofunc(x, u, t) = x","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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 ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"input = nothing \noutput = Outport(1)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We also need to specify the initial condition and time of the system","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"x0 = [1.]\nt = 0.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We are now ready to construct the system ds.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"ds = DiscreteSystem(righthandside=sfunc, readout=ofunc, state=x0, input=input, output=output)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"To drive ds, we need to launch it.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"iport, trg, hnd = Inport(1), Outpin(), Inpin{Bool}()\nconnect!(ds.output, iport) \nconnect!(trg, ds.trigger) \nconnect!(ds.handshake, hnd)\ntask = launch(ds)\ntask2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"At this point, ds is ready to be driven. To drive ds, we can either use drive(ds, t) or put!(ds.trigger, t). ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"hnd.link # `handshake` link is readable\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We continue to drive ds,","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"for i in 2. : 10. \n put!(trg, i)\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"Note that all the output values of ds is written to its output bus.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"When we launched ds, we constructed a task which is still running.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"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. ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"put!(trg, NaN)\nput!(ds.output, [NaN])","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"We can confirm that the task is not running and its state is done.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"task\ntask2","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"Since the task is not running any more, ds cannot be drivable any more. However to drive ds again, we need launch ds again.","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Full-API","page":"DiscreteSystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/discretesystem/","page":"DiscreteSystem","title":"DiscreteSystem","text":"@def_discrete_system \nDiscreteSystem \nDiscreteLinearSystem \nHenonSystem \nLoziSystem \nBogdanovSystem \nGingerbreadmanSystem\nLogisticSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.@def_discrete_system","page":"DiscreteSystem","title":"Jusdl.@def_discrete_system","text":"@def_discrete_system ex\n\nwhere ex is the expression to define to define a new AbstractDiscreteSystem component type. The usage is as follows:\n\n@def_discrete_system mutable struct MyDiscreteSystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDiscreteSystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \nend\n\nHere, 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.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(dx, x, u, t, args...; kwargs...)\n dx .= .... # update dx \nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew discrete system must be a subtype of AbstractDiscreteSystem to function properly.\n\nExample\n\njulia> @def_discrete_system mutable struct MyDiscreteSystem{RH, RO, IP, OP} <: AbstractDiscreteSystem \n α::Float64 = 1. \n β::Float64 = 2. \n righthandside::RH = (dx, x, u, t, α=α) -> (dx[1] = α * x[1] + u[1](t))\n state::Vector{Float64} = [1.]\n readout::RO = (x, u, t) -> x\n input::IP = Inport(1) \n output::OP = Outport(1) \n end\n\njulia> ds = MyDiscreteSystem();\n\njulia> ds.input \n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.DiscreteSystem","page":"DiscreteSystem","title":"Jusdl.DiscreteSystem","text":"DiscreteSystem(; righthandside, readout, state, input, output)\n\nConstructs a generic discrete system \n\nExample\n\njulia> sfuncdiscrete(dx,x,u,t) = (dx .= 0.5x);\n\njulia> ofuncdiscrete(x, u, t) = x;\n\njulia> DiscreteSystem(righthandside=sfuncdiscrete, readout=ofuncdiscrete, state=[1.], input=nothing, output=Outport())\nDiscreteSystem(righthandside:sfuncdiscrete, readout:ofuncdiscrete, state:[1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.DiscreteLinearSystem","page":"DiscreteSystem","title":"Jusdl.DiscreteLinearSystem","text":"DiscreteLinearSystem(input, output, modelargs=(), solverargs=(); \n A=fill(-1, 1, 1), B=fill(0, 1, 1), C=fill(1, 1, 1), D=fill(0, 1, 1), state=rand(size(A,1)), t=0., \n alg=ODEAlg, modelkwargs=NamedTuple(), solverkwargs=NamedTuple())\n\nConstructs 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.\n\nThe DiscreteLinearSystem is represented by the following state and output equations.\n\nbeginarrayl\n dotx = A x + B u 025cm\n y = C x + D u \nendarray\n\nwhere x is state. solver is used to solve the above differential equation.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.HenonSystem","page":"DiscreteSystem","title":"Jusdl.HenonSystem","text":"Henon()\n\nConstructs a Henon system evolving with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - alpha (x_1^2) + x_2 025cm\n dotx_2 = beta x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.LoziSystem","page":"DiscreteSystem","title":"Jusdl.LoziSystem","text":"LoziSystem()\n\nConstructs a Lozi system evolving with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - alpha x_1 + x_2 025cm\n dotx_2 = beta x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.BogdanovSystem","page":"DiscreteSystem","title":"Jusdl.BogdanovSystem","text":"BogdanovSystem()\n\nConstructs a Bogdanov system with equations\n\nbeginarrayl\n dotx_1 = x_1 + dotx_2 025cm\n dotx_2 = x_2 + epsilon + x_2 + k x_1 (x_1 - 1) + mu x_1 x_2\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.GingerbreadmanSystem","page":"DiscreteSystem","title":"Jusdl.GingerbreadmanSystem","text":"GingerbreadmanSystem()\n\nConstructs a GingerbreadmanSystem with the dynamics \n\nbeginarrayl\n dotx_1 = 1 - x_2 + x_1025cm\n dotx_2 = x_1\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/discretesystem/#Jusdl.LogisticSystem","page":"DiscreteSystem","title":"Jusdl.LogisticSystem","text":"LogisticSystem()\n\nConstructs a LogisticSystem with the dynamics \n\nbeginarrayl\n dotx = r x (1 - x)\nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Buffer","page":"Buffer","title":"Buffer","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"A Buffer is a used to buffer the data flowing the connections of a model. Data can be read from and written into a buffer. The mode of the buffer determines the way to read from and write into the buffers. ","category":"page"},{"location":"manual/utilities/buffers/#Buffer-Modes","page":"Buffer","title":"Buffer Modes","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"BufferMode determines the way the data is read from and written into a Buffer. Basically, there are four buffer modes: Normal, Cyclic, Fifo and Lifo. Normal, Fifo and Lifo are subtypes of LinearMode and Cyclic is a subtype of CyclicMode.","category":"page"},{"location":"manual/utilities/buffers/#Buffer-Constructors","page":"Buffer","title":"Buffer Constructors","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"The Buffer construction is very similar to the construction of arrays in Julia. Just specify the mode, element type and length of the buffer. Here are some examples: ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Jusdl # hide \nBuffer{Fifo}(2, 5)\nBuffer{Cyclic}(2, 10)\nBuffer{Lifo}(Bool, 2, 5)\nBuffer(5)","category":"page"},{"location":"manual/utilities/buffers/#Writing-Data-into-Buffers","page":"Buffer","title":"Writing Data into Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Writing data into a Buffer is done with write! function. Recall that when the buffer is full, no more data can be written into the buffer if the buffer mode is of type LinearMode. ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Jusdl # hide\nnormalbuf = Buffer{Normal}(3)\nforeach(item -> write!(normalbuf, item), 1:3)\nnormalbuf\nwrite!(normalbuf, 4.)","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"This situation is the same for Lifo and Fifo buffers, but not the case for Cyclic buffer. ","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Jusdl # hide\ncyclicbuf = Buffer{Cyclic}(3)\nforeach(item -> write!(cyclicbuf, item), 1:3)\ncyclicbuf\nwrite!(cyclicbuf, 3.)\nwrite!(cyclicbuf, 4.)","category":"page"},{"location":"manual/utilities/buffers/#Reading-Data-from-Buffers","page":"Buffer","title":"Reading Data from Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Reading data from a Buffer is done with read function.","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Jusdl # hide \nnbuf, cbuf, fbuf, lbuf = Buffer{Normal}(5), Buffer{Cyclic}(5), Buffer{Lifo}(5), Buffer{Fifo}(5)\nforeach(buf -> foreach(item -> write!(buf, item), 1 : 5), [nbuf, cbuf, fbuf, lbuf])\nfor buf in [nbuf, cbuf, fbuf, lbuf]\n @show buf \n for i in 1 : 5 \n @show read(buf)\n end\nend","category":"page"},{"location":"manual/utilities/buffers/#AbstractArray-Interface-of-Buffers","page":"Buffer","title":"AbstractArray Interface of Buffers","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"A Buffer can be indexed using the similar syntax of arrays in Julia. That is, getindex and setindex! methods can be used with known Julia syntax. i.e. getindex(buf, idx) is equal to buf[idx] and setindex(buf, val, idx) is equal to buf[idx] = val.","category":"page"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"using Jusdl # hide\nbuf = Buffer(5)\nsize(buf)\nlength(buf)\nfor val in 1 : 5 \n write!(buf, 2val)\nend \nbuf[1]\nbuf[3:4]\nbuf[[3, 5]]\nbuf[end]\nbuf[1] = 5 \nbuf[3:5] = [7, 8, 9]","category":"page"},{"location":"manual/utilities/buffers/#Full-API","page":"Buffer","title":"Full API","text":"","category":"section"},{"location":"manual/utilities/buffers/","page":"Buffer","title":"Buffer","text":"Modules = [Jusdl]\nPages = [\"buffer.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/utilities/buffers/#Jusdl.Buffer","page":"Buffer","title":"Jusdl.Buffer","text":"Buffer{M}(dtype::Type{T}, sz::Int...) where {M, T}\n\nConstructs a Buffer of size sz with element type of T. M is the mode of the Buffer that determines how data is to read from and written into the Buffer. There exists for different buffer modes: \n\nNormal: See Normal\nCyclic: See Cyclic\nLifo: See Lifo\nFifo: See Fifo\n\nThe default mode for Buffer is Cyclic and default element type is Float64.\n\nBuffer{M}(sz::Int...) where {M, T}\n\nConstructs a Buffer of size sz and with element type of T and mode M.\n\nBuffer(dtype::Type{T}, sz::Int...) where T\n\nConstructs a Buffer of size sz and element type T. The mode of buffer is Cyclic.\n\nBuffer(sz::Int...)\n\nConstructs a Buffer of size sz with mode Cyclic and element type of Float64.\n\nBuffer{M}(data::AbstractVecOrMat{T}) where {M, T<:Real}\n\nConstructs a Buffer with data.\n\nExample\n\njulia> buf = Buffer(5)\n5-element Buffer{Cyclic,Float64,1}\n\njulia> buf = Buffer{Fifo}(2, 5)\n2×5 Buffer{Fifo,Float64,2}\n\njulia> buf = Buffer{Lifo}(collect(reshape(1:8, 2, 4)))\n2×4 Buffer{Lifo,Int64,2}\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.BufferMode","page":"Buffer","title":"Jusdl.BufferMode","text":"BufferMode\n\nAbstract type for buffer mode. Subtypes of BufferMode is CyclicMode and LinearMode.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.Cyclic","page":"Buffer","title":"Jusdl.Cyclic","text":"Cyclic <: CyclicMode\n\nCyclic buffer mode. The data is written to buffer until the buffer is full. When the buffer is full, new data is written by overwriting the data available in the buffer starting from the beginning of the buffer. When the buffer is read, the element written last is returned and the returned element is not deleted from the buffer.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.CyclicMode","page":"Buffer","title":"Jusdl.CyclicMode","text":"CyclicMode <: BufferMode\n\nAbstract type of cyclic buffer modes. See Cyclic\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.Fifo","page":"Buffer","title":"Jusdl.Fifo","text":"Fifo <: LinearMode\n\nFifo (First-in-last-out) buffer mode. This type of buffer is a first-in-first-out buffer. The data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the first element written into the buffer is returned. The returned element is deleted from the buffer. \n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.Lifo","page":"Buffer","title":"Jusdl.Lifo","text":"Lifo <: LinearMode\n\nLifo (Last-in-first-out) buffer mode. This type of buffer is a last-in-first-out buffer. Data is written to the buffer until the buffer is full. When the buffer is full, no more element can be written into the buffer. When read, the last element written into buffer is returned. The returned element is deleted from the buffer.\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.LinearMode","page":"Buffer","title":"Jusdl.LinearMode","text":"LinearMode <: BufferMode\n\nAbstract type of linear buffer modes. See Normal, Lifo, Fifo\n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Jusdl.Normal","page":"Buffer","title":"Jusdl.Normal","text":"Normal <: LinearMode\n\nLinearMode buffer mode. The data is written to buffer until the buffer is full. When it is full, no more data is written to the buffer. When read, the data written last is returned and the returned data is not deleted from the internal container of the buffer. \n\n\n\n\n\n","category":"type"},{"location":"manual/utilities/buffers/#Base.getindex-Union{Tuple{N}, Tuple{Buffer,Vararg{Int64,N}}} where N","page":"Buffer","title":"Base.getindex","text":"getindex(buf::Buffer, idx::Vararg{Int, N})\n\nReturns an element from buf at index idx. Same as buf[idx]\n\nExample\n\njulia> buf = Buffer(2, 5); # Construct a buffer.\n\njulia> write!(buf, reshape(2 : 2 : 20, 2, 5)) # Write data into buffer.\n\njulia> buf[1]\n18.0\n\njulia> buf[1, 2]\n14.0\n\njulia> buf[1, end]\n2.0\n\njulia> buf[:, 2]\n2-element Array{Float64,1}:\n 14.0\n 16.0\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.isempty-Tuple{Buffer}","page":"Buffer","title":"Base.isempty","text":"isempty(buf::Buffer)\n\nReturns true if the index of buf is 1.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.read-Tuple{Buffer}","page":"Buffer","title":"Base.read","text":"read(buf::Buffer)\n\nReads an element from buf. Reading is performed according to the mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\nExample\n\njulia> buf = Buffer(3)\n3-element Buffer{Cyclic,Float64,1}\n\njulia> write!(buf, [2, 4, 6])\n\njulia> for i = 1 : 3 \n @show (read(buf), buf.internals)\n end\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[6.0, 4.0, 2.0], [4.0, 2.0, 0.0]])\n\njulia> buf = Buffer{Fifo}(5)\n5-element Buffer{Fifo,Float64,1}\n\njulia> write!(buf, [2, 4, 6])\n\njulia> for i = 1 : 3 \n @show (read(buf), buf.internals)\n end\n(read(buf), buf.internals) = (2.0, [[6.0, 4.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n(read(buf), buf.internals) = (4.0, [[6.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n(read(buf), buf.internals) = (6.0, [[0.0, 0.0, 0.0, 0.0, 0.0], [4.0, 2.0, 0.0, 0.0, 0.0]])\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.setindex!-Union{Tuple{N}, Tuple{Buffer,Any,Vararg{Int64,N}}} where N","page":"Buffer","title":"Base.setindex!","text":"setindex!(buf::Buffer, val, idx)\n\nSets val to buf at index idx. Same as buf[idx] = val.\n\nExample\n\njulia> buf = Buffer(2, 5);\n\njulia> buf[1] = 1\n1\n\njulia> buf[:, 2] = [1, 1]\n2-element Array{Int64,1}:\n 1\n 1\n\njulia> buf[end] = 10\n10\n\njulia> buf.internals\n2-element Array{Array{Float64,2},1}:\n [1.0 1.0 … 0.0 0.0; 0.0 1.0 … 0.0 10.0]\n [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Base.size-Tuple{Buffer}","page":"Buffer","title":"Base.size","text":"size(buf::Buffer)\n\nReturns the size of buf.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.content-Tuple{Buffer}","page":"Buffer","title":"Jusdl.content","text":"content(buf, [flip=true])\n\nReturns the current data of buf. If flip is true, the data to be returned is flipped. See also snapshot\n\nExample\n\njulia> buf = Buffer(5);\n\njulia> write!(buf, 1:3)\n\njulia> content(buf, flip=false)\n3-element Array{Float64,1}:\n 3.0\n 2.0\n 1.0\n\njulia> buf = Buffer(2, 5);\n\njulia> write!(buf, reshape(1:10, 2, 5))\n\njulia> content(buf)\n2×5 Array{Float64,2}:\n 1.0 3.0 5.0 7.0 9.0\n 2.0 4.0 6.0 8.0 10.0\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.datalength-Union{Tuple{Buffer{M,T,N}}, Tuple{N}, Tuple{T}, Tuple{M}} where N where T where M","page":"Buffer","title":"Jusdl.datalength","text":"datalength(buf::Buffer)\n\nReturns the maximum number of data that can be hold in buf.\n\nExample\n\njulia> buf = Buffer(5);\n\njulia> datalength(buf)\n5\n\njulia> buf2 = Buffer(2, 10);\n\njulia> datalength(buf2)\n10\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.inbuf-Tuple{Buffer}","page":"Buffer","title":"Jusdl.inbuf","text":"inbuf(buf::Buffer)\n\nReturns the element of internals of buf that is used to input data to buf. See also [outbuf][@ref)\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.isfull-Tuple{Buffer}","page":"Buffer","title":"Jusdl.isfull","text":"isfull(buf::Buffer)\n\nReturns true if the index of buf is equal to the length of buf.\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.ishit-Tuple{Buffer}","page":"Buffer","title":"Jusdl.ishit","text":"ishit(buf::Buffer)\n\nReturns true when buf index is an integer multiple of datalength of buf. \n\nExample\n\njulia> buf = Buffer(3);\n\njulia> for val in 1 : 7\n write!(buf, val)\n @show ishit(buf)\n end\nishit(buf) = false\nishit(buf) = false\nishit(buf) = true\nishit(buf) = false\nishit(buf) = false\nishit(buf) = true\nishit(buf) = false\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.mode-Union{Tuple{Buffer{M,T,N}}, Tuple{N}, Tuple{T}, Tuple{M}} where N where T where M","page":"Buffer","title":"Jusdl.mode","text":"mode(buf::Buffer)\n\nReturns buffer mode of buf. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.outbuf-Tuple{Buffer}","page":"Buffer","title":"Jusdl.outbuf","text":"outbuf(buf::Buffer)\n\nReturns the element of intervals of buf that is used to take data out of buf. See also: inbuf\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.snapshot-Tuple{Buffer}","page":"Buffer","title":"Jusdl.snapshot","text":"snapshot(buf::Buffer)\n\nReturns all elements in buf. See also: content\n\n\n\n\n\n","category":"method"},{"location":"manual/utilities/buffers/#Jusdl.write!-Tuple{Buffer,Any}","page":"Buffer","title":"Jusdl.write!","text":"write!(buf::Buffer{M, <:Real, 1}, val::Real) where {M}\n\nWrites val into buf.\n\nwrite!(buf::Buffer{M, <:Real, 2}, val::AbstractVector{<:Real}) where {M}\n\nWrites val into buf.\n\nwrite!(buf::Buffer{M, <:Real, 1}, vals::AbstractVector{<:Real}) where {M}\n\nWrites each element of vals into buf.\n\nwrite!(buf::Buffer{M, <:Real, 2}, vals::AbstractMatrix{<:Real}) where {M}\n\nWrites each column of vals into buf.\n\nwarning: Warning\nBuffer mode determines how data is written into buffers. See also: Normal, Cyclic, Lifo, Fifo for buffer modes. \n\nExample\n\njulia> buf = Buffer(5)\n5-element Buffer{Cyclic,Float64,1}\n\njulia> write!(buf, 1.)\n1.0\n\njulia> write!(buf, [2, 3])\n\njulia> buf.internals\n2-element Array{Array{Float64,1},1}:\n [3.0, 2.0, 1.0, 0.0, 0.0]\n [2.0, 1.0, 0.0, 0.0, 0.0]\n\njulia> buf = Buffer(2,5)\n2×5 Buffer{Cyclic,Float64,2}\n\njulia> write!(buf, [1, 1])\n2-element Array{Int64,1}:\n 1\n 1\n\njulia> write!(buf, [2 3; 2 3])\n\njulia> buf.internals\n2-element Array{Array{Float64,2},1}:\n [3.0 2.0 … 0.0 0.0; 3.0 2.0 … 0.0 0.0]\n [2.0 1.0 … 0.0 0.0; 2.0 1.0 … 0.0 0.0]\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Clock","page":"Clock","title":"Clock","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Jusdl is a clocked simulation environment. That is, model components are evolved in different time intervals, called the sampling interval. During the simulation, model components are triggered by these generated time pulses. A Clock instance is used to to generate those time pulses. The simulation time settings–the simulation start time, stop time, sampling interval–are configured through the Clock.","category":"page"},{"location":"manual/components/sources/clock/#Construction-of-Clock","page":"Clock","title":"Construction of Clock","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Construction of Clock is done by specifying its start time and final time and the simulation sampling period. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Jusdl # hide \nClock(0., 1, 10.)\nClock{Int}(1, 1, 10)","category":"page"},{"location":"manual/components/sources/clock/#Basic-Usage-of-Clocks","page":"Clock","title":"Basic Usage of Clocks","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"A Clock has a Callback list so that a Callback can be constructed to trigger specific events configured with the time settings. See the following case study. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Let us consider a Clock with initial time of 0, sampling interval of 1 and final time of 10.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Jusdl # hide \nclk = Clock(0., 1., 10.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Notice that clk is not running, since it is not set. Now, let us set it","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"set!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"clk is ready to run, i.e., to be iterated. The following commands generated clock ticks and shows it on the console.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"for t in clk \n @show t \nend","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"At this point, clk is out of time. The current time of clk does not advance any more. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"take!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"But, clk can be reset again.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"set!(clk, 0., 1., 10.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Consider that we want to configure an alarm. For this, let us consider that when the time of clk is greater than 5 an alarm message is printed on the console. To this end, we need to construct a Callback and add it to the callbacks of clk. (When constructed callback list of clk is empty.)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"condition(clk) = clk.t > 5\naction(clk) = println(\"Clock time = \", clk.t)\nclk = Clock(0., 1., 10., callbacks=Callback(condition=condition, action=action))\nset!(clk)","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Now, let us run clk by iterating it. ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"for t in clk \n @show t \nend ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Note that we, constructed a simple callback. It is of course possible to construct more complex callbacks.","category":"page"},{"location":"manual/components/sources/clock/#Usage-of-Clocks-with-ProgressMeter","page":"Clock","title":"Usage of Clocks with ProgressMeter","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"It also possible to iterate the Clocks by using a progress meter. See ProgressMeter for further information for progress meter.","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"using Jusdl\nusing ProgressMeter\nclk = Clock(0., 0.01, 1.)\nset!(clk)\n@showprogress for t in clk \nend ","category":"page"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Note that clk is just iterated.","category":"page"},{"location":"manual/components/sources/clock/#Full-API","page":"Clock","title":"Full API","text":"","category":"section"},{"location":"manual/components/sources/clock/","page":"Clock","title":"Clock","text":"Modules = [Jusdl]\nPages = [\"clock.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/components/sources/clock/#Jusdl.Clock","page":"Clock","title":"Jusdl.Clock","text":"Clock(t::Real, dt::Real, tf::Real)\n\nConstructs a Clock with starting time t, final time tf and sampling inteval dt. When iterated, the Clock returns its current time. \n\nwarning: Warning\nWhen constructed, Clock is not running. To take clock ticks from Clock, the Clock must be setted. See take!(clk::Clock) and set! \n\n\n\n\n\n","category":"type"},{"location":"manual/components/sources/clock/#Base.iterate","page":"Clock","title":"Base.iterate","text":"iterate(clk::Clock[, t=clk.t)\n\nIterationk interface for clk. clk can be iterated in a loop.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.3);\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.3, paused:false, isrunning:true)\n\njulia> for t in clk \n @show t\n end\nt = 0.0\nt = 0.1\nt = 0.2\nt = 0.3\n\n\n\n\n\n","category":"function"},{"location":"manual/components/sources/clock/#Base.take!-Tuple{Clock}","page":"Clock","title":"Base.take!","text":"take!(clk::Clock)\n\nTakes a values from clk.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:true)\n\njulia> for i in 0 : 5\n @show take!(clk)\n end\ntake!(clk) = 0.0\ntake!(clk) = 0.1\ntake!(clk) = 0.2\ntake!(clk) = 0.3\ntake!(clk) = 0.4\ntake!(clk) = 0.5\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Jusdl.isoutoftime-Tuple{Clock}","page":"Clock","title":"Jusdl.isoutoftime","text":"isoutoftime(clk::Clock)\n\nReturns true if clk is out of time, i.e., the current time of clk exceeds its final time. \n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Jusdl.ispaused-Tuple{Clock}","page":"Clock","title":"Jusdl.ispaused","text":"ispaused(clk::Clock)\n\nReturns true if clk is paused. When paused, the currnent time of clk is not advanced. See also pause!(clk::Clock)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Jusdl.isrunning-Tuple{Clock}","page":"Clock","title":"Jusdl.isrunning","text":"isrunning(clk::Clock)\n\nReturns true if clk if clk is running.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Jusdl.pause!-Tuple{Clock}","page":"Clock","title":"Jusdl.pause!","text":"pause!(clk::Clock)\n\nPauses clk. When paused, the current time of clk does not advance.\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5);\n\njulia> set!(clk);\n\njulia> for i = 1 : 5\n i > 3 && pause!(clk)\n @show take!(clk)\n end\ntake!(clk) = 0.0\ntake!(clk) = 0.1\ntake!(clk) = 0.2\n┌ Warning: Clock is paused.\n└ @ Jusdl ~/.julia/dev/Jusdl/src/components/sources/clock.jl:61\ntake!(clk) = 0.2\n┌ Warning: Clock is paused.\n└ @ Jusdl ~/.julia/dev/Jusdl/src/components/sources/clock.jl:61\ntake!(clk) = 0.2\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sources/clock/#Jusdl.set!","page":"Clock","title":"Jusdl.set!","text":"set(clk::Clock, t::Real, dt::Real, tf::Real)\n\nSets clk for current clock time t, sampling time dt and final time tf. After the set, it is possible to take clock tick from clk. See also take!(clk::Clock)\n\nExample\n\njulia> clk = Clock(0., 0.1, 0.5)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:false)\n\njulia> set!(clk)\nClock(t:0.0, dt:0.1, tf:0.5, paused:false, isrunning:true)\n\njulia> take!(clk)\n0.0\n\n\n\n\n\n","category":"function"},{"location":"manual/components/sources/clock/#Jusdl.stop!-Tuple{Clock}","page":"Clock","title":"Jusdl.stop!","text":"stop!(clk::Clock)\n\nUnsets clk. After the stpp, it is possible to take clock ticks from clk. See also take!(clk::Clock)\n\n\n\n\n\n","category":"method"},{"location":"modeling_and_simulation/simulation/#section","page":"Simulation","title":"Simulation","text":"","category":"section"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"A model to be simulated consists of components connected to each other and a time reference. The time reference is used to sample the continuous-time signals flowing through the connections of the model and to trigger the components. The simulation is performed by triggering the components with pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs, and writes them to their output ports.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"The simulation stages are shown in the flow chart in the figure above. Performing, inspecting, and reporting of all the stages of the simulation is carried out automatically without requiring any user intervention.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"In the first stage, the model is inspected to see if there are connections having any unconnected terminals. If a connection having an unconnected terminal is detected, the simulation is terminated at this stage. Another case where the model is not suitable for simulation is when algebraic loops exist. For example, almost every feedback system model includes algebraic loops. An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. The simulation does not continue because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Jusdl provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops. ","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"In case the inspection phase results positive, the putter and taker tasks are launched in order to ensure the data flow through the model connections. At this point, a putter and a taker task are bound to each connection. For example, in the figure below(on the left) is given an example model section consisting of components B1, B and the connections L1, L2, L3. When triggered, the B1 reads data from L1 calculates its output and writes to L2. Similarly, when triggered B2 reads data from the L2, calculates its output, and writes to the L3. The tasks that are bounded to L1, L2, and L3 corresponding to B1 and B2 are shown in the figure below(on the right). Since B1 reads the data from L1 and writes data to L2, a taker task is bounded to L1 and a putter task is bounded L2. Similarly, since B2 reads the data from L2 and writes data to L3, a taker task is bounded to L2 and a putter task is bounded L3. Since both a putter and a taker task are bound to the L2, data can flow from B1 to B2 through L2. A task manager is constructed to check whether the tasks launched during the initialization stage are active or not throughout the simulation and to report the error in case an error occurs.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"\n \n\n\n\n
\n
\n \"components\"\n
\n
\n \"tasks\"\n
\n
\n","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"The initialization stage is followed by the run the stage. The tasks that are launched corresponding to the components during the initialization stage expect the components to be triggered through their trigger pins. These triggers are generated in the sampling intervals of the simulation by the model clock during the run stage. It is possible to sample the signals of flowing through the connections at equal or independent time intervals. The generated triggers are put into the trigger pins of the components. The task corresponding to a triggered component is defined as reading data from the input of the component, calculating the output of the component, and writing to the output port. ","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"When the run stage is completed, the tasks launched at the initialization stage are closed and the simulation is ended.","category":"page"},{"location":"modeling_and_simulation/simulation/","page":"Simulation","title":"Simulation","text":"note: Note\nIn some simulation environments, a unified mathematical equation representing the model as a whole is obtained and solved in just a single shot for the entire simulation duration, even if the model is thought to consist of components]. In Jusdl, a model is, again, thought to consist of components, but is not represented by a unified mathematical equation. Instead, the model is evolved by evolving the components individually by solving their own mathematical equations. The components do not evolve in one shot, but instead, they evolve in parallel during the time intervals between subsequent sampling instants. Here, it worths noting that the type of the mathematical equations of the components of a model does not have to be the same. Thus, Jusdl allows the simulation of the models consisting of components represented by different types of mathematical equations.","category":"page"},{"location":"manual/components/sinks/writer/#Writer","page":"Writer","title":"Writer","text":"","category":"section"},{"location":"manual/components/sinks/writer/#Basic-Operation-of-Writers","page":"Writer","title":"Basic Operation of Writers","text":"","category":"section"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Having launched, a Writer is triggered through its trigger pin. When triggered, a Writer reads its input and then writes it to its internal buffer databuf. When databuf is full, the data in databuf is processed. Thus, the length of the data that is to be processed by the Writer is determined by the length of their internal buffer databuf. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us construct a Writer. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"using Jusdl # hide \nw = Writer(input=Inport(), buflen=5)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"The file of w is closed and the trigger pin of w is not writable. That is, it is not possible to trigger w from its trigger pin.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file \nw.trigger","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"To trigger w, we need to open and launch it, ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"oport, trg, hnd = Outport(), Outpin(), Inpin{Bool}()\nconnect!(oport, w.input)\nconnect!(trg, w.trigger)\nconnect!(w.handshake, hnd)\nopen(w)\nt = launch(w)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now, the internal file of w is opened in read/write mode and its trigger pin is writable. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file\nw.trigger.link","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us now trigger w. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"The input of w is now readable and handshake pin is not readable since w have not signaled that its triggering is succeeded yet. To do that, we need to put a value to the input of w","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(oport, [10.])","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now, w signalled that its step is succeeded. It read the data from its input and written it into is databuf. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"hnd.link\ntake!(hnd)\nw.databuf","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Since the databuf is not full nothing is written to the file of w. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Let us continue triggering w until the databuf of w is full.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"for t in 2. : 5.\n put!(trg, t)\n put!(oport, [t * 10])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Now check that the content of the file of w.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Note that the content of databuf is written to the file of w. The operation of w can be terminated. ","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"put!(trg, NaN)","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"When terminated, the file of w is closed.","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"w.file","category":"page"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"note: Note\nIn this example, w does not have a plugin so nothing has been derived or computed from the data in databuf. The data in databuf is just written to file of w. To further data processing, see Plugins","category":"page"},{"location":"manual/components/sinks/writer/#Full-API","page":"Writer","title":"Full API","text":"","category":"section"},{"location":"manual/components/sinks/writer/","page":"Writer","title":"Writer","text":"Writer \nwrite!(writer::Writer, td, xd)\nread(writer::Writer; flatten=true)\nfread \nmv(writer::Writer, dst; force::Bool=false)\ncp(writer::Writer, dst; force=false, follow_symlinks=false)\nopen(writer::Writer)\nclose(writer::Writer)","category":"page"},{"location":"manual/components/sinks/writer/#Jusdl.Writer","page":"Writer","title":"Jusdl.Writer","text":"Writer(input=Inport(); buflen=64, plugin=nothing, callbacks=nothing, name=Symbol(uuid4()), \n path=joinpath(tempdir(), string(name)))\n\nConstructs a Writer whose input bus is input. buflen is the length of the internal buffer of Writer. If not nothing, plugin is used to processes the incomming data. path determines the path of the file of Writer.\n\nnote: Note\nThe type of file of Writer is JLD2. \n\nwarning: Warning\nWhen initialized, the file of Writer is closed. See open(writer::Writer) and close(writer::Writer).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/sinks/writer/#Jusdl.write!-Tuple{Writer,Any,Any}","page":"Writer","title":"Jusdl.write!","text":"write!(writer, td, xd)\n\nWrites xd corresponding to xd to the file of writer.\n\nExample\n\njulia> w = Writer(Inport(1))\nWriter(path:/tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2, nin:1)\n\njulia> open(w)\nWriter(path:/tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2, nin:1)\n\njulia> write!(w, 0., 10.)\n10.0\n\njulia> write!(w, 1., 20.)\n20.0\n\njulia> w.file\nJLDFile /tmp/e907d6ad-8db2-4c4a-9959-5b8d33d32156.jld2 (read/write)\n ├─🔢 0.0\n └─🔢 1.0\n\njulia> w.file[string(0.)]\n10.0\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.read-Tuple{Writer}","page":"Writer","title":"Base.read","text":"read(writer::Writer, flatten=false)\n\nRead the contents of the file of writer and returns the sorted content of the file. If flatten is true, the content is also flattened.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Jusdl.fread","page":"Writer","title":"Jusdl.fread","text":"fread(path::String)\n\nReads the content of jld2 file and returns the sorted file content. \n\n\n\n\n\n","category":"function"},{"location":"manual/components/sinks/writer/#Base.Filesystem.mv-Tuple{Writer,Any}","page":"Writer","title":"Base.Filesystem.mv","text":"mv(writer::Writer, dst; force::Bool=false)\n\nMoves the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed.\n\nExample\n\njulia> mkdir(joinpath(tempdir(), \"testdir1\"))\n\"/tmp/testdir1\"\n\njulia> mkdir(joinpath(tempdir(), \"testdir2\"))\n\"/tmp/testdir2\"\n\njulia> w = Writer(Inport(), path=\"/tmp/testdir1/myfile.jld2\")\nWriter(path:/tmp/testdir1/myfile.jld2, nin:1)\n\njulia> mv(w, \"/tmp/testdir2\")\nWriter(path:/tmp/testdir2/myfile.jld2, nin:1)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.Filesystem.cp-Tuple{Writer,Any}","page":"Writer","title":"Base.Filesystem.cp","text":"cp(writer::Writer, dst; force=false, follow_symlinks=false)\n\nCopies the file of writer to dst. If force is true, the if dst is not a valid path, it is forced to be constructed. If follow_symlinks is true, symbolinks are followed.\n\nExample\n\njulia> mkdir(joinpath(tempdir(), \"testdir1\"))\n\"/tmp/testdir1\"\n\njulia> mkdir(joinpath(tempdir(), \"testdir2\"))\n\"/tmp/testdir2\"\n\njulia> w = Writer(Inport(), path=\"/tmp/testdir1\")\nWriter(path:/tmp/testdir1.jld2, nin:1)\n\njulia> cp(w, \"/tmp/testdir2\")\nWriter(path:/tmp/testdir2/1e72bad1-9800-4ca0-bccd-702afe75e555, nin:1)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.open-Tuple{Writer}","page":"Writer","title":"Base.open","text":"open(writer::Writer)\n\nOpens writer by opening the its file in read/write mode. When writer is not openned, it is not possible to write data in writer. See also close(writer::Writer)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/sinks/writer/#Base.close-Tuple{Writer}","page":"Writer","title":"Base.close","text":"close(writer::Writer)\n\nCloses writer by closing its file. When writer is closed, it is not possible to write data in writer. See also open(writer::Writer)\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/staticsystems/subsystem/#Subsystem","page":"Subsystem","title":"Subsystem","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/#Construction-of-SubSystems","page":"Subsystem","title":"Construction of SubSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"A SubSystem consists of connected components. Thus, to construct a SubSystem, we first construct components, connect them and specify the input and output of SubSystem.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/#Basic-Operation-of-SubSystems","page":"Subsystem","title":"Basic Operation of SubSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"The operation of a SubSystem is very similar to that of a StaticSystem. The only difference is that when a SubSystem is triggered through its trigger pin, it distributes the trigger to the trigger pins of its components. Then, each of the components of the SubSystem takes steps individually.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Let us construct a subsystem consisting of a generator and an adder. ","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"using Jusdl # hide \ngen = ConstantGenerator()\nadder = Adder((+,+))","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Connect the generator and adder.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"connect!(gen.output, adder.input[1])","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"We are ready to construct a SubSystem.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub = SubSystem([gen, adder], [adder.input[2]], adder.output)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"To trigger the sub, we need to launch it. For that purpose, we construct ports and pins for input-output and signaling.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"oport, iport, trg, hnd = Outport(length(sub.input)), Inport(length(sub.output)), Outpin(), Inpin{Bool}()\nconnect!(oport, sub.input)\nconnect!(sub.output, iport)\nconnect!(trg, sub.trigger)\nconnect!(sub.handshake, hnd)\nt = launch(sub)\nt2 = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub is ready to be triggered,","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Put some data to the input of sub via oport (since oport is connected to sub.input)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"put!(oport, [1.])","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"The step needs to be approved.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"take!(hnd)","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Now print the data written to the outputs of the components of sub.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"sub.components[1].output[1].links[1].buffer[1]\nsub.components[2].output[1].links[1].buffer[1]","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Note that when sub is triggered, sub transfer the trigger to all its internal components.","category":"page"},{"location":"manual/components/systems/staticsystems/subsystem/","page":"Subsystem","title":"Subsystem","text":"Modules = [Jusdl]\nPages = [\"subsystem.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/model/#Model","page":"Model","title":"Model","text":"","category":"section"},{"location":"manual/models/model/#Signal-Flow-Approach-in-Modelling","page":"Model","title":"Signal-Flow Approach in Modelling","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Jusdl adopts signal-flow approach in systems modelling. In signal-flow approach, a Model consists of connected components. The components are data processing units and the behavior, i.e, the mathematical model, of the component determines how the data is processed. Connections connects the components each other and the data is transferred between components by means of connections. The data flow through the connections is unidirectional, i.e., a component is driven by other components that write data to its input bus. ","category":"page"},{"location":"manual/models/model/#Construction-of-Models","page":"Model","title":"Construction of Models","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"A Model consists of connected components. The components of are defined first and the Model consisting of these components can be constructed. Or, an empty model can be constructed. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Let us continue with some examples. We will construct very simple Model consisting of a SinewaveGenerator and a Writer. We construct an empty Model first, then we add nodes and branches as desired.","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"using Jusdl # hide \nmodel = Model() \naddnode!(model, SinewaveGenerator(), label=:gen)\naddnode!(model, Writer(Inport()), label=:writer)\naddbranch!(model, :gen => :writer, 1 => 1)","category":"page"},{"location":"manual/models/model/#Simulation-of-Models","page":"Model","title":"Simulation of Models","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"A Model to to be simulated consists of components connected to each other an a time reference.","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"model.nodes # Model components \nmodel.branches # Model components \nmodel.clock # Model time reference","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The time reference is used to sample the continuous time signals flowing through the busses of the model and to rigger the components. The simulation is performed by triggering the components with the pulses generated by the time reference at simulation sampling time intervals. Having been triggered, the components evolve themselves, compute their outputs and writes them to their outputs.","category":"page"},{"location":"manual/models/model/#Simulation-Stages","page":"Model","title":"Simulation Stages","text":"","category":"section"},{"location":"manual/models/model/#Inspection","page":"Model","title":"Inspection","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The inspection stage is the first stage of the simulation process. In this stag,e the model is first inspected in terms of whether it is ready for simulation. This inspection is carried out to see whether the model has some inconsistencies such as unterminated busses or presence of algebraic loops. If the model has unterminated busses, the data that is supposed to flow those unterminated busses cannot flow through those busses and the simulation gets stuck. An algebraic is the subset of model components whose output depends directly on their inputs. In such a case, none of the components can produce outputs to break the loop which leads again the obstruction of simulation. Thus, to continue the simulation, the model must not contain any of those inconsistencies. The model inspection is done with inspect! function.","category":"page"},{"location":"manual/models/model/#Initialization","page":"Model","title":"Initialization","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"If the inspection stage results positive, the initialization stage comes next. In this stage, the tasks required for the busses of the model to be both readable and writable are activated and bound the busses. To this end, a reader and writer task are activated and bound to both sides of each bus. To initialize the model, initialize! function is used. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"When the model is initialized, the pairs of components and component tasks are recorded into the task manager of the model. During the rest of the simulation, task manager keeps track of the tasks. Any exception or error that is thrown during the run stage of the simulation can be observed by means of the task manager of the model.","category":"page"},{"location":"manual/models/model/#Run","page":"Model","title":"Run","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"The run stage follows the initialization stage. The tasks activated in the initialization stage wait for the components to be triggered by the model time reference. During the run stage, time reference, that is the model clock, triggers the components by writing pulses that are generated in the intervals of the sampling period of the simulation to their trigger links. The job defined in a task is to read input dat a from the its input bus, to calculate its next state, if any, and output, and write its calculated output to its output bus. The run stage, starts at the initial time of the time reference and continues until the end time of the time reference. run! function is used to run the models, ","category":"page"},{"location":"manual/models/model/#Termination","page":"Model","title":"Termination","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"After the run stage, the tasks opened in the initialization stage are closed and the simulation is terminated. terminate! function is used to terminate the model ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Models are constructed to simulate! them. During the simulation, components of the Model process data and the data is transferred between the components via connection. Thus, to simulate the Models, the components must be connected. In our model, the writer is used to record the output of gen. Thus, the flows from gen to writer. Thus, we connect gen output to writer input. ","category":"page"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"note: Note\nDuring the Model construction, the order of addition of nodes to the model is not important. The nodes can be given in any order.","category":"page"},{"location":"manual/models/model/#Full-API","page":"Model","title":"Full API","text":"","category":"section"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"Modules = [Jusdl]\nPages = [\"model.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/models/model/#Jusdl.Branch","page":"Model","title":"Jusdl.Branch","text":"Branch(nodepair, indexpair, links)\n\nConstructs a Branch connecting the first and second element of nodepair with links. indexpair determines the subindices by which the elements of nodepair are connected.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Jusdl.Model","page":"Model","title":"Jusdl.Model","text":"Model(components::AbstractVector)\n\nConstructs a Model whose with components components which are of type AbstractComponent.\n\nModel()\n\nConstructs a Model with empty components. After the construction, components can be added to Model.\n\nwarning: Warning\nModels are units that can be simulated. As the data flows through the branches i.e. input output busses of the components, its is important that the components must be connected to each other. See also: simulate!\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Jusdl.Node","page":"Model","title":"Jusdl.Node","text":"Node(component, idx, label)\n\nConstructs a model Node with component. idx is the index and label is label of Node.\n\n\n\n\n\n","category":"type"},{"location":"manual/models/model/#Jusdl.addbranch!","page":"Model","title":"Jusdl.addbranch!","text":"addbranch!(model::Model, branch::Branch)\n\nAdds branch to branched of model.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Jusdl.addnode!-Tuple{Model,AbstractComponent}","page":"Model","title":"Jusdl.addnode!","text":"addnode!(model, component; label=nothing)\n\nAdds a node to model. Component is component and label is label the label of node. Returns added node.\n\nExample\n\njulia> model = Model()\nModel(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))\n\njulia> addnode!(model, SinewaveGenerator(), label=:gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.breakloop!","page":"Model","title":"Jusdl.breakloop!","text":"breakloop!(model, loop, breakpoint=length(loop))\n\nBreaks the algebraic loop of model. The loop of the model is broken by inserting a Memory at the breakpoint of loop.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Jusdl.deletebranch!-Tuple{Model,Pair{Int64,Int64}}","page":"Model","title":"Jusdl.deletebranch!","text":"deletebranch!(model::Model, branch::Branch)\n\nDeletes branch from branched of model.\n\ndeletebranch!(model::Model, srcnode::Node, dstnode::Node)\n\nDeletes branch between srcnode and dstnode of the model.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.getloops-Tuple{Model}","page":"Model","title":"Jusdl.getloops","text":"getloops(model)\n\nReturns idx of nodes that constructs algrebraic loops.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.getnode-Tuple{Model,Int64}","page":"Model","title":"Jusdl.getnode","text":"getnode(model, idx::Int)\n\nReturns node of model whose index is idx.\n\ngetnode(model, label)\n\nReturns node of model whose label is label.\n\nExample\n\njulia> model = Model()\nModel(numnodes:0, numedges:0, timesettings=(0.0, 0.01, 1.0))\n\njulia> addnode!(model, SinewaveGenerator(), label=:gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\njulia> addnode!(model, Gain(), label=:gain)\nNode(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)\n\njulia> getnode(model, :gen)\nNode(component:SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0.0, delay:0.0), idx:1, label:gen)\n\njulia> getnode(model, 2)\nNode(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:2, label:gain)\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.initialize!-Tuple{Model}","page":"Model","title":"Jusdl.initialize!","text":"initialize!(model::Model)\n\nInitializes model by launching component task for each of the component of model. The pairs component and component tasks are recordedin the task manager of the model. The model clock is set! and the files of Writer are openned.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.inspect!","page":"Model","title":"Jusdl.inspect!","text":"inspect!(model::Model)\n\nInspects the model. If model has some inconsistencies such as including algebraic loops or unterminated busses and error is thrown.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Jusdl.run!","page":"Model","title":"Jusdl.run!","text":"run!(model::Model, withbar::Bool=true)\n\nRuns the model by triggering the components of the model. This triggering is done by generating clock tick using the model clock model.clock. Triggering starts with initial time of model clock, goes on with a step size of the sampling period of the model clock, and finishes at the finishing time of the model clock. If withbar is true, a progress bar indicating the simulation status is displayed on the console.\n\nwarning: Warning\nThe model must first be initialized to be run. See also: initialize!.\n\n\n\n\n\n","category":"function"},{"location":"manual/models/model/#Jusdl.signalflow-Tuple{Model,Vararg{Any,N} where N}","page":"Model","title":"Jusdl.signalflow","text":"signalflow(model, args...; kwargs...)\n\nPlots the signal flow of model. args and kwargs are passed into gplot function.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.simulate!-Tuple{Model,Real,Real,Real}","page":"Model","title":"Jusdl.simulate!","text":"simulate!(model::Model, t0::Real, dt::Real, tf::Real; kwargs...)\n\nSimulates the model starting from the initial time t0 until the final time tf with the sampling interval of tf. For kwargs are \n\nlogtofile::Bool: If true, a log file is contructed logging each step of the simulation. \nreportsim::Bool: If true, model components are written files after the simulation. When this file is read back, the model components can be consructed back with their status at the end of the simulation.\nsimdir::String: The path of the directory in which simulation file are recorded. \n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.simulate!-Tuple{Model}","page":"Model","title":"Jusdl.simulate!","text":"simulate!(model::Model; simdir::String=tempdir(), simprefix::String=\"Simulation-\", simname=string(uuid4()),\n logtofile::Bool=false, loglevel::LogLevel=Logging.Info, reportsim::Bool=false, withbar::Bool=true)\n\nSimulates model. simdir is the path of the directory into which simulation files are saved. simprefix is the prefix of the simulation name simname. If logtofile is true, a log file for the simulation is constructed. loglevel determines the logging level. If reportsim is true, model components are saved into files. If withbar is true, a progress bar indicating the simualation status is displayed on the console.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.terminate!-Tuple{Model}","page":"Model","title":"Jusdl.terminate!","text":"terminate!(model::Model)\n\nTerminates model by terminating all the components of the model, i.e., the components tasks in the task manager of the model is terminated.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/#Jusdl.troubleshoot-Tuple{Model}","page":"Model","title":"Jusdl.troubleshoot","text":"troubleshoot(model)\n\nPrints the exceptions of the tasks that are failed during the simulation of model.\n\n\n\n\n\n","category":"method"},{"location":"manual/models/model/","page":"Model","title":"Model","text":"@defmodel","category":"page"},{"location":"manual/models/model/#Jusdl.@defmodel","page":"Model","title":"Jusdl.@defmodel","text":"@defmodel name ex\n\nConstruts a model. The expected syntax is. \n\n @defmodel mymodel begin \n @nodes begin \n label1 = Component1()\n label2 = Component1()\n ⋮\n end\n @branches begin \n src1 => dst1 \n src2 => dst2 \n ⋮\n end\n end\n\nHere @nodes and @branches blocks adefine the nodes and branches of the model, respectively. \n\n\n\n\n\n","category":"macro"},{"location":"manual/components/componentsbase/interpolation/#Interpolation","page":"Interpolation","title":"Interpolation","text":"","category":"section"},{"location":"manual/components/componentsbase/interpolation/#Full-API","page":"Interpolation","title":"Full API","text":"","category":"section"},{"location":"manual/components/componentsbase/interpolation/","page":"Interpolation","title":"Interpolation","text":"Modules = [Jusdl]\nPages = [\"interpolant.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/components/componentsbase/interpolation/#Jusdl.Interpolant","page":"Interpolation","title":"Jusdl.Interpolant","text":"Interpolant(tinit, tfinal, coefinit, coeffinal)\n\nConstructs a linnear interpolant that interpolates between the poinsts (tinit, coefinit) and (tfinal, coeffinal).\n\n\n\n\n\n","category":"type"},{"location":"manual/components/componentsbase/interpolation/#Jusdl.update!-Union{Tuple{Interpolant{T1,var\"#s36\",T2} where var\"#s36\"<:(AbstractArray{T,1} where T)}, Tuple{T2}, Tuple{T1}} where T2 where T1","page":"Interpolation","title":"Jusdl.update!","text":"update!(intepolant)\n\nUpdates interpolant using the data in timebuf and databuf of interpolant.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Ports","page":"Ports","title":"Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"A Port is actually is a bunch of pins (See Pins for mor information on pins.). As such, the connection, disconnection and data transfer are very similar to those of pins. Basically, there are two type of port: Outport and Inport. The data flows from outside of a component to its inside through an Inport while data flows from inside of the component to its outside through an Outport.","category":"page"},{"location":"manual/connections/port/#Construction-of-Ports","page":"Ports","title":"Construction of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"A port (both Inport and Outport) is constructed by specifying its element type T, the number of pins npins and the buffer length of its pins.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"using Jusdl # hide\nOutport{Bool}(5)\nOutport{Int}(2) \nOutport(3) \nOutport() \nInport{Bool}(5)\nInport{Int}(2) \nInport(3) \nInport() ","category":"page"},{"location":"manual/connections/port/#Connection-and-Disconnection-of-Ports","page":"Ports","title":"Connection and Disconnection of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The ports can be connected to and disconnected from each other. See the following example.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Let us construct and Outport and an Inport and connect them together.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op1 = Outport(2) \nip1 = Inport(2) \nls = connect!(op1, ip1)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Note that we connected all pins of op to ip. We cannot connect the ports partially. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op2, ip21, ip22 = Outport(5), Inport(2), Inport(3) \nls1 = connect!(op2[1:2], ip21)\nls2 = connect!(op2[3:5], ip22)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The connectedness of ports can be checked. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"isconnected(op2[1], ip21[1])\nisconnected(op2[1], ip21[2])\nisconnected(op2[1:2], ip21)\nisconnected(op2[3:5], ip22)\nisconnected(op2[5], ip22[3])","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Connected ports can be disconnected.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"disconnect!(op2[1], ip21[1])\ndisconnect!(op2[2], ip21[2])\ndisconnect!(op2[3:5], ip22)","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Now check again the connectedness,","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"isconnected(op2[1], ip21[1])\nisconnected(op2[1], ip21[2])\nisconnected(op2[1:2], ip21)\nisconnected(op2[3:5], ip22)\nisconnected(op2[5], ip22[3])","category":"page"},{"location":"manual/connections/port/#Data-Flow-Through-Ports","page":"Ports","title":"Data Flow Through Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Data flow through the ports is very similar to the case in pins(see Data Flow Through Pins for information about data flow through pins). Running tasks must be bound to the links of pins of the ports for data flow through the ports.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Let us construct an Outport and an Inport, connect them together with links and perform data transfer from the Outport to the Inport through the links. ","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op3, ip3 = Outport(2), Inport(2)\nls = connect!(op3, ip3)\nt = @async while true\n val = take!(ip3)\n all(val .=== NaN) && break\n println(\"Took \" * string(val))\nend\nput!(op3, 1.);\nip3[1].link.buffer","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Note that the data flowing through the links are also written into the buffers of links.","category":"page"},{"location":"manual/connections/port/#Indexing-and-Iteration-of-Ports","page":"Ports","title":"Indexing and Iteration of Ports","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Ports can be indexed similarly to the arrays in Julia. When indexed, the corresponding pin of the port is returned.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"op4 = Outport(3) \nop4[1]\nop4[end] \nop4[:]\nop4[1] = Outpin()\nop4[1:2] = [Outpin(), Outpin()]","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"The iteration of Ports in a loop is also possible. When iterated, the pins of the Port is returned.","category":"page"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"ip5 = Inport(3)\nfor pin in ip5\n @show pin\nend","category":"page"},{"location":"manual/connections/port/#Full-API","page":"Ports","title":"Full API","text":"","category":"section"},{"location":"manual/connections/port/","page":"Ports","title":"Ports","text":"Modules = [Jusdl]\nPages = [\"port.jl\"]\nOrder = [:type, :function]","category":"page"},{"location":"manual/connections/port/#Jusdl.AbstractPort","page":"Ports","title":"Jusdl.AbstractPort","text":"AbstractPort{P}\n\nAbstract type of Outport and Inport. See also: Outport, Inport.\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Jusdl.Inport","page":"Ports","title":"Jusdl.Inport","text":"Inport{T}(numpins=1)\n\nConstructs an Inport with numpins Inpin.\n\nwarning: Warning\nElement type of an Inport must be Inpin. See also Inpin\n\nExample\n\njulia> Inport{Int}(2)\n2-element Inport{Inpin{Int64}}:\n Inpin(eltype:Int64, isbound:false)\n Inpin(eltype:Int64, isbound:false)\n\njulia> Inport()\n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Jusdl.Outport","page":"Ports","title":"Jusdl.Outport","text":"Outport{T}(numpins=1)\n\nConstructs an Outport with numpins Outpin.\n\nwarning: Warning\nElement type of an Outport must be Outpin. See also Outpin\n\nExample\n\njulia> Outport{Int}(2)\n2-element Outport{Outpin{Int64}}:\n Outpin(eltype:Int64, isbound:false)\n Outpin(eltype:Int64, isbound:false)\n\njulia> Outport()\n1-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"type"},{"location":"manual/connections/port/#Base.getindex-Union{Tuple{N}, Tuple{AbstractPort,Vararg{Int64,N}}} where N","page":"Ports","title":"Base.getindex","text":"getindex(port::AbstractPort, idx::Vararg{Int, N}) where N\n\nReturns elements from port at index idx. Same as port[idx].\n\nExample\n\njulia> op = Outport(3)\n3-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\njulia> op[1]\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[end]\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[:]\n3-element Array{Outpin{Float64},1}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.put!-Tuple{Outport,Any}","page":"Ports","title":"Base.put!","text":"put!(outport::Outport, vals)\n\nPuts vals to outport. Each item in vals is putted to the links of the outport.\n\nwarning: Warning\nThe outport must be writable to be read. That is, there must be a runnable tasks bound to links of the outport that reads data from outport.\n\nExample\n\njulia> op, ip = Outport(), Inport() \n(Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))\n\njulia> ls = connect!(op, ip)\n1-element Array{Link{Float64},1}:\n Link(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> t = @async while true \n val = take!(ip)\n all(val .=== NaN) && break \n println(\"Took \" * string(val))\n end;\n\njulia> put!(op, [1.])\nTook [1.0]\n1-element Array{Float64,1}:\n 1.0\n\njulia> put!(op, [NaN])\n1-element Array{Float64,1}:\n NaN\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.setindex!-Union{Tuple{N}, Tuple{AbstractPort,Any,Vararg{Int64,N}}} where N","page":"Ports","title":"Base.setindex!","text":"setindex!(port::AbstractPort, item, idx::Vararg{Int, N}) where N\n\nSets item to port at index idx. Same as port[idx] = item.\n\nExample\n\njulia> op = Outport(3)\n3-element Outport{Outpin{Float64}}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\njulia> op[1] = Outpin()\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[end] = Outpin()\nOutpin(eltype:Float64, isbound:false)\n\njulia> op[1:2] = [Outpin(), Outpin()]\n2-element Array{Outpin{Float64},1}:\n Outpin(eltype:Float64, isbound:false)\n Outpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.size-Tuple{AbstractPort}","page":"Ports","title":"Base.size","text":"size(port::AbstractPort)\n\nRetruns size of port.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Base.take!-Tuple{Inport}","page":"Ports","title":"Base.take!","text":"take!(inport::Inport)\n\nTakes an element from inport. Each link of the inport is a read and a vector containing the results is returned.\n\nwarning: Warning\nThe inport must be readable to be read. That is, there must be a runnable tasks bound to links of the inport that writes data to inport.\n\nExample\n\njulia> op, ip = Outport(), Inport()\n(Outport(numpins:1, eltype:Outpin{Float64}), Inport(numpins:1, eltype:Inpin{Float64}))\n\njulia> ls = connect!(op, ip)\n1-element Array{Link{Float64},1}:\n Link(state:open, eltype:Float64, isreadable:false, iswritable:false)\n\njulia> t = @async for val in 1 : 5 \n put!(op, [val])\n end;\n\njulia> take!(ip)\n1-element Array{Float64,1}:\n 1.0\n\njulia> take!(ip)\n1-element Array{Float64,1}:\n 2.0\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Jusdl.datatype-Union{Tuple{AbstractPort{var\"#s36\"} where var\"#s36\"<:AbstractPin{T}}, Tuple{T}} where T","page":"Ports","title":"Jusdl.datatype","text":"datatype(port::AbstractPort)\n\nReturns the data type of port.\n\n\n\n\n\n","category":"method"},{"location":"manual/connections/port/#Jusdl.similar-Union{Tuple{Outport{P}}, Tuple{P}, Tuple{T}, Tuple{Outport{P},Int64}} where P<:Outpin{T} where T","page":"Ports","title":"Jusdl.similar","text":"similar(port, numpins::Int=length(outport)) where {P<:Outpin{T}} where {T}\n\nReturns a new port that is similar to port with the same element type. The number of links in the new port is nlinks and data buffer length is ln.\n\n\n\n\n\n","category":"method"},{"location":"manual/components/systems/staticsystems/staticsystems/#StaticSystems","page":"StaticSystems","title":"StaticSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/#Basic-Operation-of-StaticSystems","page":"StaticSystems","title":"Basic Operation of StaticSystems","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"A static system is a system whose output y at time t depends on the current time t and the value of its input u. The input-output relation of a static systems is represented by its output function outputfunc which is of the form ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":" y = g(u t)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"where g is the output function outputfunc. Note that outputfunc is expected to have two inputs, the value u of the input and the current time t. The simulation in Jusdl is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t. Therefore, for example, the system modeled by","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"y(t) = g(u(t)t)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"is actually sampled at clock ticks t which is generated by a Clock. Therefore the sampled system corresponds to","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"yk = g(u_k t_k)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"where k is k_i T_s where k_i is an integer number, T_s is the sampling interval. T_s corresponds to sampling time dt of Clock. Thus, the system given above is coded like ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"function g(u, t)\n # Define the relation `y = g(u, t)`\nend","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"For further clarity, let us continue with a case study. Consider the following static system,","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":" y(t) = g(u(t) t) = left\n beginarrayl\n t u_1(t) \n sin(u_1(t)) \n cos(u_2(t))\n endarray\n right","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note that the number of inputs is 2 and the number of outputs of is 3. To define such a system, the output function is written as","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"using Jusdl # hide\ng(u, t) = [t * u[1], sin(u[1]), cos(u[2])]","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note that the function g is defined in such a way that the input value u is sampled, which implies u is not a vector of function but is a vector of real. Having defined output function outputfunc, the system can be constructed. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss = StaticSystem(readout=g, input=Inport(2), output=Outport(3))","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Note the construction of input bus Inport(2) and output bus Outport(3) by recalling that the number of input is 2 and the number of output is 3.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"A StaticSystem evolves by being triggered through its trigger pin. When triggered from its trigger pin, a StaticSystem reads the current time t from its trigger pin and computes its output y according to its output function outputfunc and writes its output y(t) to its output port (if output port exists since output port may be nothing depending on the relation defined by outputfunc). When constructed, a StaticSystem is not ready to be triggered since its trigger pin is not writeable. To make ss drivable, we need to construct the ports and pins for input-output and signaling. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"oport, iport, trg, hnd = Outport(length(ss.input)), Inport(length(ss.output)), Outpin(), Inpin{Bool}()\nconnect!(oport, ss.input) \nconnect!(ss.output, iport) \nconnect!(trg, ss.trigger)\nconnect!(ss.handshake, hnd)\ntask = launch(ss)\ntaskout = @async while true \n all(take!(iport) .=== NaN) && break \n end","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Now, ss is drivable from its trg pin. ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss.trigger.link","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Now let us drive ss.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"put!(trg, 1.)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"As this point ss wait for its to be written. Let us write some data to oport.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"put!(oport, [10., 10.])","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"ss read the value u of its input(since ss.input is connected to oport), read the current time t, and computed its output value y and wrote it its output port. To signal that it succeeded to be take the step, it put a true to its handshake which needs to be taken.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"hnd.link\ntake!(hnd)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"We can see the current data in the output of ss through iport (since iport is connected to ss.output)","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"Let us further drive ss.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"for t in 2. : 10.\n put!(trg, t)\n put!(oport, [10 * t, 20 * t])\n take!(hnd)\nend","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"The data written to the output of ss is also written to the internal buffers of output.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"iport[1].link.buffer","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"In addition to the generic StaticSystem, Jusdl provides some well-known static systems given in the next section.","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/#Full-API","page":"StaticSystems","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/staticsystems/staticsystems/","page":"StaticSystems","title":"StaticSystems","text":"@def_static_system \nStaticSystem \nAdder \nMultiplier \nGain \nTerminator \nMemory \nCoupler \nDifferentiator ","category":"page"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.@def_static_system","page":"StaticSystems","title":"Jusdl.@def_static_system","text":"@def_static_system ex\n\nwhere ex is the expression to define to define a new AbstractStaticSystem component type. The usage is as follows:\n\n@def_source struct MyStaticSystem{T1,T2,T3,...,TN,OP, RO} <: AbstractStaticSystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field \n readout::RO = readout_function # mandatory field\nend\n\nHere, MyStaticSystem has N parameters, an output port, an input port and a readout function.\n\nwarning: Warning\ninput, output and readout are mandatory fields to define a new static system. The rest of the fields are the parameters of the system.\n\nwarning: Warning\nreadout must be a two-argument function, i.e. a function of time t and input value u.\n\nwarning: Warning\nNew static system must be a subtype of AbstractStaticSystem to function properly.\n\nExample\n\njulia> @def_static_system struct MyStaticSystem{IP, OP, RO} <: AbstractStaticSystem \n α::Float64 = 1. \n β::Float64 = 2. \n input::IP = Inport() \n output::OP = Outport() \n readout::RO = (t,u) -> α * u[1] + β * u[2]\n end\n\njulia> sys = MyStaticSystem(); \n\njulia> sys.α\n1.0\n\njulia> sys.input\n1-element Inport{Inpin{Float64}}:\n Inpin(eltype:Float64, isbound:false)\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.StaticSystem","page":"StaticSystems","title":"Jusdl.StaticSystem","text":"StaticSystem(; readout, input, output)\n\nConsructs a generic static system with readout function, input port and output port.\n\nExample\n\njulia> ss = StaticSystem(readout = (t,u) -> u[1] + u[2], input=Inport(2), output=Outport(1));\n\njulia> ss.readout(0., ones(2))\n2.0\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Adder","page":"StaticSystems","title":"Jusdl.Adder","text":"Adder(signs=(+,+))\n\nConstruts an Adder with input bus input and signs signs. signs is a tuplle of + and/or -. The output function g of Adder is of the form,\n\n y = g(u t) = sum_j = 1^n s_k u_k\n\nwhere n is the length of the input, s_k is the kth element of signs, u_k is the kth value of input and y is the value of output. The default value of signs is all +.\n\nExample\n\njulia> adder = Adder(signs=(+, +, -));\n\njulia> adder.readout([3, 4, 5], 0.) == 3 + 4 - 5\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Multiplier","page":"StaticSystems","title":"Jusdl.Multiplier","text":"Multiplier(ops=(*,*))\n\nConstruts an Multiplier with input bus input and signs signs. signs is a tuplle of * and/or /. The output function g of Multiplier is of the form,\n\n y = g(u t) = prod_j = 1^n s_k u_k\n\nwhere n is the length of the input, s_k is the kth element of signs, u_k is the kth value of input and y is the value of the output. The default value of signs is all *.\n\nExample\n\njulia> mlt = Multiplier(ops=(*, *, /));\n\njulia> mlt.readout([3, 4, 5], 0.) == 3 * 4 / 5\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Gain","page":"StaticSystems","title":"Jusdl.Gain","text":"Gain(input; gain=1.)\n\nConstructs a Gain whose output function g is of the form \n\n y = g(u t) = K u\n\nwhere K is gain, u is the value of input and y is the value of output.\n\nExample\n\njulia> K = [1. 2.; 3. 4.];\n\njulia> sfunc = Gain(input=Inport(2), gain=K);\n\njulia> sfunc.readout([1., 2.], 0.) == K * [1., 2.]\ntrue\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Terminator","page":"StaticSystems","title":"Jusdl.Terminator","text":"Terminator(input::Inport)\n\nConstructs a Terminator with input bus input. The output function g is eqaul to nothing. A Terminator is used just to sink the incomming data flowing from its input.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Memory","page":"StaticSystems","title":"Jusdl.Memory","text":"Memory(delay=1.; initial::AbstractVector{T}=zeros(1), numtaps::Int=5, t0=0., dt=0.01, callbacks=nothing, \n name=Symbol()) where T\n\nConstructs a 'Memorywith input businput. A 'Memory delays the values of input by an amount of numdelay. initial determines the transient output from the Memory, that is, until the internal buffer of Memory is full, the values from initial is returned.\n\nExample\n\njulia> Memory(delay=0.1)\nMemory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))\n\njulia> Memory(delay=0.1, numtaps=5)\nMemory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Coupler","page":"StaticSystems","title":"Jusdl.Coupler","text":"Coupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)\n\nConstructs a coupler from connection matrix conmat of size n times n and coupling matrix cplmat of size d times d. The output function g of Coupler is of the form \n\n y = g(u t) = (E otimes P) u\n\nwhere otimes is the Kronecker product, E is conmat and P is cplmat, u is the value of input and y is the value of output.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/staticsystems/staticsystems/#Jusdl.Differentiator","page":"StaticSystems","title":"Jusdl.Differentiator","text":"Differentiator(kd=1; callbacks=nothing, name=Symbol())\n\nConsructs a Differentiator whose input output relation is of the form \n\n y(t) = k_d dotu(t)\n\nwhere u(t) is the input and y(t) is the output and kd is the differentiation constant.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/model_construction/#page_header","page":"Model Construction","title":"Model Construction","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"This tutorial illustrates model construction and the relation between models and graphs. A model consists of components and connections. These components and connections can be associated with a signal-flow graph signifying the topology of the model. In the realm of graph theory, components and connections of a model are associated with nodes and branches of the signal-flow graph. As the model is modified by adding or deleting components or connections, the signal-flow graph of the model is modified accordingly to keep track of topological modifications. By associating a signal-flow graph to a model, any graph-theoretical analysis can be performed. An example to such an analysis is the determination and braking of algebraic loops. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"In Jusdl, a model can be constructed either by describing it in one-shot or by gradually modifying it by adding new nodes and branches. To show the relation between models and graphs, we start with the latter.","category":"page"},{"location":"tutorials/model_construction/#section_header","page":"Model Construction","title":"Modifying Models","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"In this tutorial, we construct the model with the following block diagram","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"and with the following signal-flow graph ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Let's start with an empty Model.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using Jusdl # hide \nmodel = Model()","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"We constructed an empty model, i.e., the model has no components and connections. To modify the model, we need to add components and connections to the model. As the model is grown by adding components and connections, the components and connections are added into the model as nodes and branches (see Node, Branch). Let's add our first component, a SinewaveGenerator to the model.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, SinewaveGenerator(), label=:gen)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"To add components to the model, we use addnode! function. As seen, our node consists of a component, an index, and a label. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"node1 = model.nodes[1]\nnode1.component\nnode1.idx \nnode1.label ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Let us add another component, a Adder, to the model, ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, Adder(signs=(+,-)), label=:adder)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"and investigate our new node.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"node2 = model.nodes[2] \nnode2.component \nnode2.idx\nnode2.label","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note that as new nodes are added to the model, they are given an index idx and a label label. The label is not mandatory, if not specified explicitly, nothing is assigned as label. The reason to add components as nodes is to access them through their node index idx or labels. For instance, we can access our first node by using its node index idx or node label label. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"getnode(model, :gen) # Access by label\ngetnode(model, 1) # Access by index","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"At this point, we have two nodes in our model. Let's add two more nodes, a Gain and a Writer","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addnode!(model, Gain(), label=:gain)\naddnode!(model, Writer(), label=:writer)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"As the nodes are added to the model, its graph is modified accordingly.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model.graph","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model has no connections. Let's add our first connection by connecting the first pin of the output port of the node 1 (which is labelled as :gen) to the first input pin of input port of node 2 (which is labelled as :adder). ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addbranch!(model, :gen => :adder, 1 => 1)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The node labelled with :gen has an output port having one pin, and the node labelled with :adder has an input port of two pins. In our first connection, we connected the first(and the only) pin of the output port of the node labelled with :gen to the first pin of the input port of the node labelled with :adder. The connections are added to model as branches, ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"model.branches","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"A branch between any pair of nodes can be accessed through the indexes or labels of nodes. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"br = getbranch(model, :gen => :adder)\nbr.nodepair \nbr.indexpair \nbr.links","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note the branch br has one link(see Link). This is because we connected one pin to another pin. The branch that connects n pins to each other has n links. Let us complete the construction of the model by adding other connections. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"addbranch!(model, :adder => :gain, 1 => 1)\naddbranch!(model, :gain => :adder, 1 => 2)\naddbranch!(model, :gain => :writer, 1 => 1)","category":"page"},{"location":"tutorials/model_construction/#Describing-Models","page":"Model Construction","title":"Describing Models","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The second approach is to describe the whole model. In this approach the model is constructed in single-shot. The syntax here is ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"@defmodel modelname begin \n @nodes begin \n label1 = Component1(args...; kwargs...) # Node 1\n label2 = Component2(args...; kwargs...) # Node 2\n ⋮ ⋮\n \n labelN = ComponentN(args...; kwargs...) # Node N\n end \n @branches begin \n src_label1[src_index1] = dst_label1[dst_index1] # Branch 1\n src_label2[src_index2] = dst_label1[dst_index2] # Branch 2 \n ⋮ ⋮\n src_labelM[src_indexM] = dst_labelM[dst_indexM] # Branch M\n end\nend ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"Note that modelname is the name of the model to be compiled. The nodes of the model is defined in @nodes begin ... end block and the branches of the model is defined in @branches begin ... end. The syntax src_label1[src_index1] = dst_label1[dst_index1] means that there is a branch between the node labelled with src_label1 and the node labelled with dst_label1.And, this branch connects the pins indexed by src_index1 of the output port of src_label1 to the pins indexed by dst_index1 of the input port of dst_label1. The indexing of the pins here is just like any one dimensional array indexing. That is src_index1( or dst_index1) may be integer, vector of integers, vector of booleans, range, etc.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For example, the model given above can also be constructed as follows ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using Jusdl # hide \n\n@defmodel model begin \n @nodes begin \n gen = SinewaveGenerator() \n adder = Adder(signs=(+,-))\n gain = Gain() \n writer = Writer() \n end \n @branches begin \n gen[1] => adder[1]\n adder[1] => gain[1]\n gain[1] => adder[2]\n gain[1] => writer[1]\n end\nend","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"This macro is expanded to construct the model.","category":"page"},{"location":"tutorials/model_construction/#Usage-of-Signal-Flow-Graph","page":"Model Construction","title":"Usage of Signal-Flow Graph","text":"","category":"section"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"The signal-flow graph constructed alongside of the construction of the model can be used to perform any topological analysis. An example to such an analysis is the detection of algebraic loops. For instance, our model in this tutorial has an algebraic loop consisting of the nodes labelled with :gen and gain. This loop can be detected using the signal-flow graph of the node ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"loops = getloops(model)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"We have one loop consisting the nodes with indexes 2 and 3. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For further analysis on model graph, we use LightGraphs package.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"using LightGraphs \ngraph = model.graph ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"For example, the adjacency matrix of model graph can be obtained. ","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"adjacency_matrix(model.graph)","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"or inneighbors or outneighbors of a node can be obtained.","category":"page"},{"location":"tutorials/model_construction/","page":"Model Construction","title":"Model Construction","text":"inneighbors(model.graph, getnode(model, :adder).idx)\noutneighbors(model.graph, getnode(model, :adder).idx)","category":"page"},{"location":"manual/components/systems/dynamicsystems/daesystem/#DAESystem","page":"DAESystem","title":"DAESystem","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Full-API","page":"DAESystem","title":"Full API","text":"","category":"section"},{"location":"manual/components/systems/dynamicsystems/daesystem/","page":"DAESystem","title":"DAESystem","text":"@def_dae_system \nDAESystem \nRobertsonSystem \nPendulumSystem\nRLCSystem ","category":"page"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Jusdl.@def_dae_system","page":"DAESystem","title":"Jusdl.@def_dae_system","text":"@def_dae_system ex\n\nwhere ex is the expression to define to define a new AbstractDAESystem component type. The usage is as follows:\n\n@def_dae_system mutable struct MyDAESystem{T1,T2,T3,...,TN,OP,RH,RO,ST,IP,OP} <: AbstractDAESystem\n param1::T1 = param1_default # optional field \n param2::T2 = param2_default # optional field \n param3::T3 = param3_default # optional field\n ⋮\n paramN::TN = paramN_default # optional field \n righthandside::RH = righthandside_function # mandatory field\n readout::RO = readout_function # mandatory field\n state::ST = state_default # mandatory field\n stateder::ST = stateder_default # mandatory field\n diffvars::Vector{Bool} = diffvars_default # mandatory field\n input::IP = input_default # mandatory field\n output::OP = output_default # mandatory field\nend\n\nHere, MyDAESystem has N parameters. MyDAESystem is represented by the righthandside and readout function. state, 'stateder,diffvars,inputandoutputis the initial state, initial value of differential variables, vector signifing differetial variables, input port and output port ofMyDAESystem`.\n\nwarning: Warning\nrighthandside must have the signature function righthandside(out, dx, x, u, t, args...; kwargs...)\n out .= .... # update out\nendand readout must have the signature function readout(x, u, t)\n y = ...\n return y\nend\n\nwarning: Warning\nNew DAE system must be a subtype of AbstractDAESystem to function properly.\n\nExample\n\njulia> @def_dae_system mutable struct MyDAESystem{RH, RO, ST, IP, OP} <: AbstractDAESystem\n righthandside::RH = function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end \n readout::RO = (x,u,t) -> x \n state::ST = [1., -1]\n stateder::ST = [2., 0]\n diffvars::Vector{Bool} = [true, false]\n input::IP = nothing \n output::OP = Outport(1)\n end\n\njulia> ds = MyDAESystem();\n\n\n\n\n\n","category":"macro"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Jusdl.DAESystem","page":"DAESystem","title":"Jusdl.DAESystem","text":"DAESystem(; righthandside, readout, state, stateder, diffvars, input, output)\n\nConstructs a generic DAE system.\n\nExample\n\njulia> function sfuncdae(out, dx, x, u, t)\n out[1] = x[1] + 1 - dx[1]\n out[2] = (x[1] + 1) * x[2] + 2\n end;\n\njulia> ofuncdae(x, u, t) = x;\n\njulia> x0 = [1., -1];\n\njulia> dx0 = [2., 0.];\n\njulia> DAESystem(righthandside=sfuncdae, readout=ofuncdae, state=x0, input=nothing, output=Outport(1), diffvars=[true, false], stateder=dx0)\nDAESystem(righthandside:sfuncdae, readout:ofuncdae, state:[1.0, -1.0], t:0.0, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Jusdl.RobertsonSystem","page":"DAESystem","title":"Jusdl.RobertsonSystem","text":"RobertsonSystem()\n\nConstructs a Robertson systme with the dynamcis \n\nbeginarrayl\n dotx_1 = -k_1 x_1 + k_3 x_2 x_3 025cm\n dotx_2 = k_1 x_1 - k_2 x_2^2 - k_3 x_2 x_3 025cm\n 1 = x_1 + x_2 + x_3 \nendarray\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Jusdl.PendulumSystem","page":"DAESystem","title":"Jusdl.PendulumSystem","text":"PendulumSystem()\n\nConstructs a Pendulum systme with the dynamics\n\nbeginarrayl\n dotx_1 = x_3 025cm\n dotx_2 = x_4 025cm\n dotx_3 = -dfracFm l x_1 025cm\n dotx_4 = g dfracFl x_2 025cm\n 0 = x_1^2 + x_2^2 - l^2 \nendarray\n\nwhere F is the external force, l is the length, m is the mass and g is the accelaration of gravity.\n\n\n\n\n\n","category":"type"},{"location":"manual/components/systems/dynamicsystems/daesystem/#Jusdl.RLCSystem","page":"DAESystem","title":"Jusdl.RLCSystem","text":"RLCSystem()\n\nConstrusts a RLC system with the dynamics\n\nbeginarrayl\n dotx_1 = x_3 025cm\n dotx_2 = x_4 025cm\n dotx_3 = -dfracFm l x_1 025cm\n dotx_4 = g dfracFl x_2 025cm\n 0 = x_1^2 + x_2^2 - l^2 \nendarray\n\nwhere F is the external force, l is the length, m is the mass and g is the accelaration of gravity.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/model_simulation/#Construction-and-Simulation-of-a-Simple-Model","page":"Model Simulation","title":"Construction and Simulation of a Simple Model","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_simulation/#Model-Simulation","page":"Model Simulation","title":"Model Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"Let us construct the model first. See Model Construction for more detailed information about model construction.","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using Jusdl \n\n# Describe the model \n@defmodel model begin \n @nodes begin \n gen = SinewaveGenerator() \n writer = Writer() \n end \n @branches begin \n gen => writer\n end\nend\nnothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"In this simple model, we have a single output sinusoidal wave generator gen and a writer. In the script above, we constructed the components, connected them together and constructed the model.","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"We can specify simulation settings such as whether a simulation log file is be to constructed, model components are to be saved in a file, etc. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"simdir = \"/tmp\" \nlogtofile = true\nreportsim = true\nnothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"At this point, the model is ready for simulation. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"t0 = 0. # Start time \ndt = 0.01 # Sampling interval\ntf = 10. # Final time\nsim = simulate!(model, t0, dt, tf, simdir=simdir, logtofile=logtofile, reportsim=reportsim)","category":"page"},{"location":"tutorials/model_simulation/#Investigation-of-Simulation","page":"Model Simulation","title":"Investigation of Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"foreach(println, readlines(`ls -al $(sim.path)`))","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"The simulation directory includes a log file simlog.log which helps the user monitor simulation steps. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"# Print the contents of log file \nopen(joinpath(sim.path, \"simlog.log\"), \"r\") do file \n for line in readlines(file)\n println(line)\n end\nend","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"report.jld2 file, which includes the information about the simulation and model components, can be read back after the simulation. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using FileIO, JLD2 \nfilecontent = load(joinpath(sim.path, \"report.jld2\"))\nclock = filecontent[\"model/clock\"]","category":"page"},{"location":"tutorials/model_simulation/#Analysis-of-Simulation-Data","page":"Model Simulation","title":"Analysis of Simulation Data","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"After the simulation, the data saved in simulation data files, i.e. in the files of writers, can be read back any offline data analysis can be performed. ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"# Read the simulation data\nt, x = read(getnode(model, :writer).component) \n\n# Plot the data\nusing Plots\nplot(t, x, xlabel=\"t\", ylabel=\"x\", label=\"\")\nsavefig(\"simple_model_plot.svg\"); nothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"(Image: )","category":"page"},{"location":"tutorials/model_simulation/#A-Larger-Model-Simulation","page":"Model Simulation","title":"A Larger Model Simulation","text":"","category":"section"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"Consider a larger model whose block diagram is given below","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"
\n \"model\"\n
","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"The script below illustrates the construction and simulation of this model ","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"using Jusdl \nusing Plots\n\n# Construct the model \n@defmodel model begin \n @nodes begin \n gen1 = SinewaveGenerator(frequency=2.)\n gain1 = Gain()\n adder1 = Adder(signs=(+,+))\n gen2 = SinewaveGenerator(frequency=3.)\n adder2 = Adder(signs=(+,+,-))\n gain2 = Gain()\n writer = Writer() \n gain3 = Gain()\n end \n @branches begin \n gen1[1] => gain1[1] \n gain1[1] => adder1[1]\n adder1[1] => adder2[1]\n gen2[1] => adder1[2]\n gen2[1] => adder2[2]\n adder2[1] => gain2[1]\n gain2[1] => writer[1]\n gain2[1] => gain3[1]\n gain3[1] => adder2[3]\n end\nend\n\n# Simulation of the model \nsimulate!(model, withbar=false)\n\n# Reading and plotting the simulation data\nt, x = read(getnode(model, :writer).component)\nplot(t, x)\nsavefig(\"larger_model_plot.svg\"); nothing # hide","category":"page"},{"location":"tutorials/model_simulation/","page":"Model Simulation","title":"Model Simulation","text":"(Image: )","category":"page"},{"location":"#Jusdl","page":"Home","title":"Jusdl","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Jusdl enables fast and effective systems simulations together with online and offline data analysis. In Jusdl, it is possible to simulate discrete-time and continuous-time, static or dynamical systems. In particular, it is possible to simulate dynamical systems modeled by different types of differential equations such as ODE (Ordinary Differential Equation), Random Ordinary Differential Equation (RODE), SDE (Stochastic Differential Equation), DDE (Delay Differential Equation) and DAE (Differential Algebraic Equation), and discrete difference equations. During the simulation, the data flowing through the links of the model can be processed online and offline and specialized analyzes can be performed. These analyses can also be enriched with plugins that can easily be defined using the standard Julia library or various Julia packages. The simulation is performed by evolving the components individually and in parallel during sampling time intervals. The individual evolution of the components allows the simulation of the models that include components represented by different kinds of mathematical equations.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Installation of Jusdl is the similar to any other registered Julia package. Start a Julia session and type ","category":"page"},{"location":"","page":"Home","title":"Home","text":"] add Jusdl","category":"page"}] ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 } diff --git a/docs/build/tutorials/algebraic_loops/index.html b/docs/build/tutorials/algebraic_loops/index.html index 268fcdc6..3ad6575e 100644 --- a/docs/build/tutorials/algebraic_loops/index.html +++ b/docs/build/tutorials/algebraic_loops/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Algebraic Loops · Causal

Breaking Algebraic Loops

It this tutorial, we will simulate model consisting a closed loop feedback system. The model has an algebraic loop.

Algebraic Loops

An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. If algebraic loops exist in a model, the simulation gets stuck because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Causal provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops.

Breaking Algebraic Loops Automatically

Before initializing and running the simulation, Causal inspects the model first. See Simulation Stages for more information of simulation stages. In case the they exist in the model, all the algebraic loops are tried to be broken automatically without requiring a user intervention. Consider the following model

-======= -Algebraic Loops · Jusdl

Breaking Algebraic Loops

It this tutorial, we will simulate model consisting a closed loop feedback system. The model has an algebraic loop.

Algebraic Loops

An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. If algebraic loops exist in a model, the simulation gets stuck because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Jusdl provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops.

Breaking Algebraic Loops Automatically

Before initializing and running the simulation, Jusdl inspects the model first. See Simulation Stages for more information of simulation stages. In case the they exist in the model, all the algebraic loops are tried to be broken automatically without requiring a user intervention. Consider the following model

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Algebraic Loops · Causal

Breaking Algebraic Loops

It this tutorial, we will simulate model consisting a closed loop feedback system. The model has an algebraic loop.

Algebraic Loops

An algebraic loop is a closed-loop consisting of one or more components whose outputs are directly dependent on their inputs. If algebraic loops exist in a model, the simulation gets stuck because none of the components in the loop can generate output to break the loop. Such a problem can be broken by rearranging the model without algebraic loops, solving the feed-forward algebraic equation of the loop, or inserting a memory component with a certain initial condition anywhere in the loop. Causal provides all these loop-breaking solutions. During the inspection stage, in case they are detected, all the loops are broken. Otherwise, a report is printed to notify the user to insert memory components to break the loops.

Breaking Algebraic Loops Automatically

Before initializing and running the simulation, Causal inspects the model first. See Simulation Stages for more information of simulation stages. In case the they exist in the model, all the algebraic loops are tried to be broken automatically without requiring a user intervention. Consider the following model

model

where

\[\begin{array}{l} r(t) = t \\[0.25cm] @@ -38,44 +34,25 @@ t, y = read(getnode(model, :writerout).component) t, r = read(getnode(model, :writerin).component) plot(t, r, label="r(t)", marker=(:circle, 3)) -<<<<<<< HEAD -plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:01:00.577 Started simulation...
-[ Info: 2020-08-22T12:01:00.627 Inspecting model...
+plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-24T10:43:36.709 Started simulation...
+[ Info: 2020-08-24T10:43:36.759 Inspecting model...
 ┌ Info: 	The model has algrebraic loops:[[2, 3]]
 └ 		Trying to break these loops...
 [ Info: 	Loop [2, 3] is broken
-[ Info: 2020-08-22T12:01:01.585 Done.
-[ Info: 2020-08-22T12:01:01.585 Initializing the model...
-[ Info: 2020-08-22T12:01:01.903 Done...
-[ Info: 2020-08-22T12:01:02.154 Running the simulation...
-[ Info: 2020-08-22T12:01:07.678 Done...
-[ Info: 2020-08-22T12:01:07.678 Terminating the simulation...
-[ Info: 2020-08-22T12:01:07.952 Done.
-=======
-plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:30:33.084 Started simulation...
-[ Info: 2020-08-22T12:30:33.163 Inspecting model...
-┌ Info: 	The model has algrebraic loops:[[2, 3]]
-└ 		Trying to break these loops...
-[ Info: 	Loop [2, 3] is broken
-[ Info: 2020-08-22T12:30:34.255 Done.
-[ Info: 2020-08-22T12:30:34.255 Initializing the model...
-[ Info: 2020-08-22T12:30:34.561 Done...
-[ Info: 2020-08-22T12:30:34.862 Running the simulation...
-[ Info: 2020-08-22T12:30:41.081 Done...
-[ Info: 2020-08-22T12:30:41.081 Terminating the simulation...
-[ Info: 2020-08-22T12:30:41.47 Done.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+[ Info: 2020-08-24T10:43:37.622 Done.
+[ Info: 2020-08-24T10:43:37.622 Initializing the model...
+[ Info: 2020-08-24T10:43:37.965 Done...
+[ Info: 2020-08-24T10:43:38.219 Running the simulation...
+[ Info: 2020-08-24T10:43:44.051 Done...
+[ Info: 2020-08-24T10:43:44.051 Terminating the simulation...
+[ Info: 2020-08-24T10:43:44.272 Done.
 qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
 connect: Connection refused
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
-<<<<<<< HEAD
 GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

Breaking Algebraic Loops With a Memory

It is also possible to break algebraic loops by inserting a Memory component at some point the loop. For example, consider the model consider following the model which is the model in which a memory component is inserted in the feedback path.

-======= -GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

Breaking Algebraic Loops With a Memory

It is also possible to break algebraic loops by inserting a Memory component at some point the loop. For example, consider the model consider following the model which is the model in which a memory component is inserted in the feedback path.

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 model

Note that the input to adder is not $y(t)$, but instead is $\hat{y}(t)$ which is one sample delayed form of $y(t)$. That is, we have, $\hat{y}(t) = y(t - dt)$ where $dt$ is the step size of the simulation. If $dt$ is small enough, $\hat{y}(t) \approx y(t)$.

The script given below simulates this case.

using Causal
 
@@ -110,44 +87,25 @@
 t, r = read(getnode(model, :writerin).component)
 t, y = read(getnode(model, :writerout).component)
 plot(t, r, label="r(t)", marker=(:circle, 3))
-<<<<<<< HEAD
-plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:01:29.739 Started simulation...
-[ Info: 2020-08-22T12:01:29.739 Inspecting model...
+plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-24T10:44:04.659 Started simulation...
+[ Info: 2020-08-24T10:44:04.659 Inspecting model...
 ┌ Info: 	The model has algrebraic loops:[[2, 3, 6]]
 └ 		Trying to break these loops...
 [ Info: 	Loop [2, 3, 6] has a Memory component.  The loops is broken
-[ Info: 2020-08-22T12:01:29.757 Done.
-[ Info: 2020-08-22T12:01:29.757 Initializing the model...
-[ Info: 2020-08-22T12:01:29.796 Done...
-[ Info: 2020-08-22T12:01:29.894 Running the simulation...
-[ Info: 2020-08-22T12:01:29.903 Done...
-[ Info: 2020-08-22T12:01:29.903 Terminating the simulation...
-[ Info: 2020-08-22T12:01:30.131 Done.
+[ Info: 2020-08-24T10:44:04.674 Done.
+[ Info: 2020-08-24T10:44:04.674 Initializing the model...
+[ Info: 2020-08-24T10:44:04.707 Done...
+[ Info: 2020-08-24T10:44:04.794 Running the simulation...
+[ Info: 2020-08-24T10:44:04.799 Done...
+[ Info: 2020-08-24T10:44:04.799 Terminating the simulation...
+[ Info: 2020-08-24T10:44:04.91 Done.
 qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
-=======
-plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:31:05.809 Started simulation...
-[ Info: 2020-08-22T12:31:05.809 Inspecting model...
-┌ Info: 	The model has algrebraic loops:[[2, 3, 6]]
-└ 		Trying to break these loops...
-[ Info: 	Loop [2, 3, 6] has a Memory component.  The loops is broken
-[ Info: 2020-08-22T12:31:05.825 Done.
-[ Info: 2020-08-22T12:31:05.825 Initializing the model...
-[ Info: 2020-08-22T12:31:05.861 Done...
-[ Info: 2020-08-22T12:31:05.976 Running the simulation...
-[ Info: 2020-08-22T12:31:05.983 Done...
-[ Info: 2020-08-22T12:31:05.983 Terminating the simulation...
-[ Info: 2020-08-22T12:31:06.143 Done.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 connect: Connection refused
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
-<<<<<<< HEAD
 GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

The fluctuation in $y(t)$ because of one-sample-time delay introduced by the mem component is apparent. The smaller the step size is, the smaller the amplitude of the fluctuation introduced by the mem component.

One other important issue with using the memory component is that the initial value of mem directly affects the accuracy of the simulation. By solving the loop equation, we know that

\[ y(t) = \dfrac{r(t)}{2} = \dfrac{t}{2} \quad \Rightarrow \quad y(0) = 0\]

That is the memory should be initialized with an initial value of zero, which is the case in the script above. To observe that how incorrect initialization of a memory to break an algebraic loop, consider the following example in which memory is initialized randomly.

using Causal
-=======
-GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

The fluctuation in $y(t)$ because of one-sample-time delay introduced by the mem component is apparent. The smaller the step size is, the smaller the amplitude of the fluctuation introduced by the mem component.

One other important issue with using the memory component is that the initial value of mem directly affects the accuracy of the simulation. By solving the loop equation, we know that

\[ y(t) = \dfrac{r(t)}{2} = \dfrac{t}{2} \quad \Rightarrow \quad y(0) = 0\]

That is the memory should be initialized with an initial value of zero, which is the case in the script above. To observe that how incorrect initialization of a memory to break an algebraic loop, consider the following example in which memory is initialized randomly.

using Jusdl
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 using Plots
 
 # Simulation time settings.
@@ -181,44 +139,22 @@
 t, r = read(getnode(model, :writerin).component)
 t, y = read(getnode(model, :writerout).component)
 plot(t, r, label="r(t)", marker=(:circle, 3))
-<<<<<<< HEAD
-plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:01:33.677 Started simulation...
-[ Info: 2020-08-22T12:01:33.677 Inspecting model...
+plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-24T10:44:08.289 Started simulation...
+[ Info: 2020-08-24T10:44:08.289 Inspecting model...
 ┌ Info: 	The model has algrebraic loops:[[2, 3, 6]]
 └ 		Trying to break these loops...
 [ Info: 	Loop [2, 3, 6] has a Memory component.  The loops is broken
-[ Info: 2020-08-22T12:01:33.677 Done.
-[ Info: 2020-08-22T12:01:33.677 Initializing the model...
-[ Info: 2020-08-22T12:01:33.677 Done...
-[ Info: 2020-08-22T12:01:33.677 Running the simulation...
-[ Info: 2020-08-22T12:01:33.682 Done...
-[ Info: 2020-08-22T12:01:33.682 Terminating the simulation...
-[ Info: 2020-08-22T12:01:33.832 Done.
+[ Info: 2020-08-24T10:44:08.289 Done.
+[ Info: 2020-08-24T10:44:08.289 Initializing the model...
+[ Info: 2020-08-24T10:44:08.289 Done...
+[ Info: 2020-08-24T10:44:08.289 Running the simulation...
+[ Info: 2020-08-24T10:44:08.295 Done...
+[ Info: 2020-08-24T10:44:08.295 Terminating the simulation...
+[ Info: 2020-08-24T10:44:08.403 Done.
 qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
 connect: Connection refused
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
-GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

-======= -plot!(t, y, label="y(t)", marker=(:circle, 3))
[ Info: 2020-08-22T12:31:09.98 Started simulation...
-[ Info: 2020-08-22T12:31:09.98 Inspecting model...
-┌ Info: 	The model has algrebraic loops:[[2, 3, 6]]
-└ 		Trying to break these loops...
-[ Info: 	Loop [2, 3, 6] has a Memory component.  The loops is broken
-[ Info: 2020-08-22T12:31:09.981 Done.
-[ Info: 2020-08-22T12:31:09.981 Initializing the model...
-[ Info: 2020-08-22T12:31:09.982 Done...
-[ Info: 2020-08-22T12:31:09.982 Running the simulation...
-[ Info: 2020-08-22T12:31:09.994 Done...
-[ Info: 2020-08-22T12:31:09.994 Terminating the simulation...
-[ Info: 2020-08-22T12:31:10.311 Done.
-connect: Connection refused
-qt.qpa.screen: QXcbConnection: Could not connect to display
-Could not connect to any X display.
-GKS: can't connect to GKS socket application
-
-GKS: Open failed in routine OPEN_WS
-GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

diff --git a/docs/build/tutorials/breaking_algebraic_loops_plot1.svg b/docs/build/tutorials/breaking_algebraic_loops_plot1.svg index c43abb4f..9c26c9be 100644 --- a/docs/build/tutorials/breaking_algebraic_loops_plot1.svg +++ b/docs/build/tutorials/breaking_algebraic_loops_plot1.svg @@ -1,183 +1,93 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -<<<<<<< HEAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/build/tutorials/breaking_algebraic_loops_with_memory_incorrect_plot1.svg b/docs/build/tutorials/breaking_algebraic_loops_with_memory_incorrect_plot1.svg index ed17e389..b3781a4e 100644 --- a/docs/build/tutorials/breaking_algebraic_loops_with_memory_incorrect_plot1.svg +++ b/docs/build/tutorials/breaking_algebraic_loops_with_memory_incorrect_plot1.svg @@ -1,764 +1,376 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/build/tutorials/breaking_algebraic_loops_with_memory_plot1.svg b/docs/build/tutorials/breaking_algebraic_loops_with_memory_plot1.svg index d83d7303..e8eaea76 100644 --- a/docs/build/tutorials/breaking_algebraic_loops_with_memory_plot1.svg +++ b/docs/build/tutorials/breaking_algebraic_loops_with_memory_plot1.svg @@ -1,183 +1,93 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -<<<<<<< HEAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/build/tutorials/coupled_systems/index.html b/docs/build/tutorials/coupled_systems/index.html index aec36719..fc5eb58d 100644 --- a/docs/build/tutorials/coupled_systems/index.html +++ b/docs/build/tutorials/coupled_systems/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Coupled Systems · Causal

Coupled Systems

Consider two coupled LorenzSystems. The first system evolves by

\[\begin{array}{l} -======= -Coupled Systems · Jusdl

Coupled Systems

Consider two coupled LorenzSystems. The first system evolves by

\[\begin{array}{l} ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Coupled Systems · Causal

Coupled Systems

Consider two coupled LorenzSystems. The first system evolves by

\[\begin{array}{l} \dot{x}_{1,1} = \sigma (x_{1,2} - x_{1,1}) + \epsilon (x_{2,1} - x_{1,1}) \\[0.25cm] \dot{x}_{1,2} = x_{1,1} (\rho - x_{1,3}) - x_{1,2} \\[0.25cm] \dot{x}_{1,3} = x_{1,1} x_{1,2} - \beta x_{1,3} @@ -64,42 +60,23 @@ p1 = plot(x[:, 1], x[:, 2], label="ds1") p2 = plot(x[:, 4], x[:, 5], label="ds2") p3 = plot(t, err, label="err") -<<<<<<< HEAD -plot(p1, p2, p3, layout=(3, 1))
[ Info: 2020-08-22T12:01:39.66 Started simulation...
-[ Info: 2020-08-22T12:01:39.66 Inspecting model...
-=======
-plot(p1, p2, p3, layout=(3, 1))
[ Info: 2020-08-22T12:31:16.854 Started simulation...
-[ Info: 2020-08-22T12:31:16.854 Inspecting model...
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+plot(p1, p2, p3, layout=(3, 1))
[ Info: 2020-08-24T10:44:14.09 Started simulation...
+[ Info: 2020-08-24T10:44:14.09 Inspecting model...
 ┌ Info: 	The model has algrebraic loops:[[1, 3], [3, 2]]
 └ 		Trying to break these loops...
 [ Info: 	Loop [1, 3] is broken
 [ Info: 	Loop [2, 3] is broken
-<<<<<<< HEAD
-[ Info: 2020-08-22T12:01:39.932 Done.
-[ Info: 2020-08-22T12:01:39.932 Initializing the model...
-[ Info: 2020-08-22T12:01:40.032 Done...
-[ Info: 2020-08-22T12:01:41.151 Running the simulation...
-[ Info: 2020-08-22T12:01:43.092 Done...
-[ Info: 2020-08-22T12:01:43.092 Terminating the simulation...
-[ Info: 2020-08-22T12:01:43.152 Done.
+[ Info: 2020-08-24T10:44:14.401 Done.
+[ Info: 2020-08-24T10:44:14.401 Initializing the model...
+[ Info: 2020-08-24T10:44:14.501 Done...
+[ Info: 2020-08-24T10:44:15.545 Running the simulation...
+[ Info: 2020-08-24T10:44:17.509 Done...
+[ Info: 2020-08-24T10:44:17.509 Terminating the simulation...
+[ Info: 2020-08-24T10:44:17.555 Done.
 qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
-=======
-[ Info: 2020-08-22T12:31:17.159 Done.
-[ Info: 2020-08-22T12:31:17.159 Initializing the model...
-[ Info: 2020-08-22T12:31:17.282 Done...
-[ Info: 2020-08-22T12:31:18.439 Running the simulation...
-[ Info: 2020-08-22T12:31:20.553 Done...
-[ Info: 2020-08-22T12:31:20.553 Terminating the simulation...
-[ Info: 2020-08-22T12:31:20.796 Done.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 connect: Connection refused
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
-<<<<<<< HEAD
-GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

-======= -GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

diff --git a/docs/build/tutorials/coupled_systems_plot.svg b/docs/build/tutorials/coupled_systems_plot.svg index 0dfb5925..d50eeba4 100644 --- a/docs/build/tutorials/coupled_systems_plot.svg +++ b/docs/build/tutorials/coupled_systems_plot.svg @@ -1,6518 +1,3256 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + diff --git a/docs/build/tutorials/defining_new_components/index.html b/docs/build/tutorials/defining_new_components/index.html index 366bc11e..ff2a1db5 100644 --- a/docs/build/tutorials/defining_new_components/index.html +++ b/docs/build/tutorials/defining_new_components/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Extending Component Library · Causal

Defining New Component Types

Causal provides a library that includes some well-known components that are ready to be used. For example,

It is very natural that this library may lack some of the components that are wanted to be used by the user. In such a case, Causal provides the users with the flexibility to enrich this library. The users can define their new component types, including source, static system, dynamical system, sink and use them with ease.

Defining A New Source

New source types are defines using @def_source macro. Before embarking on defining new source, let us get the necessary information on how to use @def_source. This can be can be obtained through its docstrings.

julia> using Causal # hide
-=======
-Extending Component Library · Jusdl

Defining New Component Types

Jusdl provides a library that includes some well-known components that are ready to be used. For example,

It is very natural that this library may lack some of the components that are wanted to be used by the user. In such a case, Jusdl provides the users with the flexibility to enrich this library. The users can define their new component types, including source, static system, dynamical system, sink and use them with ease.

Defining A New Source

New source types are defines using @def_source macro. Before embarking on defining new source, let us get the necessary information on how to use @def_source. This can be can be obtained through its docstrings.

julia> using Jusdl # hide
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Extending Component Library · Causal

Defining New Component Types

Causal provides a library that includes some well-known components that are ready to be used. For example,

It is very natural that this library may lack some of the components that are wanted to be used by the user. In such a case, Causal provides the users with the flexibility to enrich this library. The users can define their new component types, including source, static system, dynamical system, sink and use them with ease.

Defining A New Source

New source types are defines using @def_source macro. Before embarking on defining new source, let us get the necessary information on how to use @def_source. This can be can be obtained through its docstrings.

julia> using Causal # hide
 
 julia> @doc @def_source
   @def_source ex
@@ -69,39 +65,22 @@
 # 2 methods for type constructor:
 [1] (::Type{Main.ex-defining_new_components_ex.MySource})(; α, β, readout, output, trigger, handshake, callbacks, name, id) in Main.ex-defining_new_components_ex at /home/sari/.julia/dev/Causal/src/components/componentsbase/macros.jl:55
 [2] (::Type{Main.ex-defining_new_components_ex.MySource})(α::Float64, β::Float64, readout::RO, output::OP, trigger::var"##386", handshake::var"##387", callbacks::var"##388", name::Symbol, id::var"##389") where {RO, OP, var"##386", var"##387", var"##388", var"##389"} in Main.ex-defining_new_components_ex at none:2

The constructor with the keyword arguments is very much easy to uses.

julia> gen1 = MySource()
-<<<<<<< HEAD
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("ff016a61-0ca8-42ed-8a84-520a87ef8c76"))
+Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("43e7d6aa-c7af-4380-82e0-28623e605e0d"))
 
 julia> gen2 = MySource(α=4.)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 2.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("81248156-adfc-4417-aad5-0f340a969262"))
+Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 2.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("c3b504f7-cfb6-428e-989d-1865792bb555"))
 
 julia> gen3 = MySource(α=4., β=5.)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("5dce9fd5-9866-43e6-ac86-4e530113daef"))
+Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("803adffd-b962-4a4e-a038-c37c916ba350"))
 
 julia> gen3 = MySource(α=4., β=5., name=:mygen)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, :mygen, UUID("63c7bce2-dd15-49c0-943d-cb8b393c12d5"))
-=======
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("a9163b95-5ab3-4662-a34e-ce79e5e03785"))
-
-julia> gen2 = MySource(α=4.)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 2.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("9b76d6b6-46cd-4b51-b5f4-2bb9843c5567"))
-
-julia> gen3 = MySource(α=4., β=5.)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("3af2d469-2541-4bc5-b48c-4b918bab4bf4"))
-
-julia> gen3 = MySource(α=4., β=5., name=:mygen)
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, :mygen, UUID("7893e4b6-b819-4384-ae26-75d9af2832ff"))
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(4.0, 5.0, Main.ex-defining_new_components_ex.var"#3#8"{Float64,Float64}(4.0, 5.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, :mygen, UUID("df74ed51-9994-4db1-a333-1b93876ce075"))
 
 julia> gen3.trigger
 Inpin(eltype:Float64, isbound:false)
 
 julia> gen3.id
-<<<<<<< HEAD
-UUID("63c7bce2-dd15-49c0-943d-cb8b393c12d5")
-=======
-UUID("7893e4b6-b819-4384-ae26-75d9af2832ff")
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+UUID("df74ed51-9994-4db1-a333-1b93876ce075")
 
 julia> gen3.α
 4.0
@@ -113,11 +92,7 @@
 2-element Outport{Outpin{Float64}}:
  Outpin(eltype:Float64, isbound:false)
  Outpin(eltype:Float64, isbound:false)

An instance works flawlessly as a model component, that is, it can be driven from its trigger pin and signalling cane be carried out from its handshake pin. To see this, let us construct required pins and ports to drive a MySource instance.

julia> gen = MySource()                # `MySource` instance
-<<<<<<< HEAD
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("82ba5cb9-c6ef-4885-a7b5-83941128b793"))
-=======
-Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("c2df5001-d067-42b3-85d7-b43809dce7d8"))
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Main.ex-defining_new_components_ex.MySource{Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64},Outport{Outpin{Float64}},Inpin{Float64},Outpin{Bool},Nothing,Base.UUID}(1.0, 2.0, Main.ex-defining_new_components_ex.var"#2#7"{Float64,Float64}(1.0, 2.0), Outport(numpins:2, eltype:Outpin{Float64}), Inpin(eltype:Float64, isbound:false), Outpin(eltype:Bool, isbound:false), nothing, Symbol(""), UUID("68608a01-76b8-4ab7-8425-28e69e3e6df5"))
 
 julia> trg = Outpin()                  # To trigger `gen`
 Outpin(eltype:Float64, isbound:false)
@@ -137,11 +112,7 @@
 julia> connect!(gen.output, iport);
 
 julia> launch(gen)                 # Launch `gen,
-<<<<<<< HEAD
-Task (runnable) @0x00007f5125b79fc0

Now gen can be driven through trg pin.

julia> put!(trg, 1.)       # Drive `gen` for `t=1`.
-=======
-Task (runnable) @0x00007f163d10d870

Now gen can be driven through trg pin.

julia> put!(trg, 1.)       # Drive `gen` for `t=1`.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Task (runnable) @0x00007fdad1a689d0

Now gen can be driven through trg pin.

julia> put!(trg, 1.)       # Drive `gen` for `t=1`.
 
 julia> take!(iport)        # Read output of `gen` from `iport`
 2-element Array{Float64,1}:
@@ -149,11 +120,7 @@
  1.0806046117362795
 
 julia> take!(hnd)          # Approve `gen` has taken a step.
-<<<<<<< HEAD
 true

Thus, by using @def_source macro, it is possible for the users to define any type of sources under AbstractSource type and user them without a hassle.

The procedure is again the same for any other component types. The table below lists the macros that are used to define new component types.

MacroComponent TypeSupertypeMandatory Field Names
@def_sourceSourceAbstractSourcereadout, output
@def_static_systemStaticSystemAbstractStaticSystemreadout, output, input
@def_discrete_systemDiscrete Dynamic SystemAbstractDiscreteSystemrighthandside, readout, state, input, output
@def_ode_systemODE Dynamic SystemAbstractODESystemrighthandside, readout, state, input, output
@def_dae_systemDAE Dynamic SystemAbstractDAESystemrighthandside, readout, state, stateder, diffvars, input, output
@def_rode_systemRODE Dynamic SystemAbstractRODESystemrighthandside, readout, state, input, output
@def_sde_systemSDE Dynamic SystemAbstractSDESystemdrift, diffusion, readout, state, input, output
@def_dde_systemDDE Dynamic SystemAbstractDDESystemconstlags, depslags, righthandside, history, readout, state, input, output
@def_sinkSinkAbstractSinkaction

The steps followed in the previous section are the same to define other component types: start with suitable macro given above, make the newly-defined type a subtype of the corresponding supertype, define the optional fields (if exist) ands define the mandatory fields of the new type (with the default values if necessary).

Defining New StaticSystem

Consider the following readout function of the static system to be defined

\[y = u_1 t + a cos(u_2)\]

where $u = [u_1, u_2]$ is the input, $y$ is the output of the system and $t$ is time. The system has two inputs and one output. This system can be defined as follows.

julia> @def_static_system struct MyStaticSystem{RO, IP, OP} <: AbstractStaticSystem
-=======
-true

Thus, by using @def_source macro, it is possible for the users to define any type of sources under AbstractSource type and user them without a hassle.

The procedure is again the same for any other component types. The table below lists the macros that are used to define new component types.

MacroComponent TypeSupertypeMandatory Field Names
@def_sourceSourceAbstractSourcereadout, output
@def_static_systemStaticSystemAbstractStaticSystemreadout, output, input
@def_discrete_systemDiscrete Dynamic SystemAbstractDiscreteSystemrighthandside, readout, state, input, output
@def_ode_systemODE Dynamic SystemAbstractODESystemrighthandside, readout, state, input, output
@def_dae_systemDAE Dynamic SystemAbstractDAESystemrighthandside, readout, state, stateder, diffvars, input, output
@def_rode_systemRODE Dynamic SystemAbstractRODESystemrighthandside, readout, state, input, output
@def_sde_systemSDE Dynamic SystemAbstractSDESystemdrift, diffusion, readout, state, input, output
@def_dde_systemDDE Dynamic SystemAbstractDDESystemconstlags, depslags, righthandside, history, readout, state, input, output
@def_sinkSinkAbstractSinkaction

The steps followed in the previous section are the same to define other component types: start with suitable macro given above, make the newly-defined type a subtype of the corresponding supertype, define the optional fields (if exist) ands define the mandatory fields of the new type (with the default values if necessary).

Defining New StaticSystem

Consider the following readout function of the static system to be defined

\[y = u_1 t + a cos(u_2)\]

where $u = [u_1, u_2]$ is the input, $y$ is the output of the system and $t$ is time. The system has two inputs and one output. This system can be defined as follows.

julia> @def_static_system struct MyStaticSystem{RO, IP, OP} <: AbstractStaticSystem
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
            a::Float64 = 1.
            readout::RO = (t, a = a) -> u[1] * t + a * cos(u[2])
            input::IP = Inport(2)
@@ -319,8 +286,4 @@
        end
 
 julia> actionfunc(sink::MySink, t, u) = println(t, u)
-<<<<<<< HEAD
-actionfunc (generic function with 1 method)
-======= -actionfunc (generic function with 1 method)
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +actionfunc (generic function with 1 method)
diff --git a/docs/build/tutorials/larger_model_plot.svg b/docs/build/tutorials/larger_model_plot.svg index d1609436..a4ca10e9 100644 --- a/docs/build/tutorials/larger_model_plot.svg +++ b/docs/build/tutorials/larger_model_plot.svg @@ -1,219 +1,111 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD - - - - -======= - - - - ->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + diff --git a/docs/build/tutorials/model_construction/index.html b/docs/build/tutorials/model_construction/index.html index d102a74b..972cfad9 100644 --- a/docs/build/tutorials/model_construction/index.html +++ b/docs/build/tutorials/model_construction/index.html @@ -1,9 +1,5 @@ -<<<<<<< HEAD -Model Construction · Causal

Model Construction

This tutorial illustrates model construction and the relation between models and graphs. A model consists of components and connections. These components and connections can be associated with a signal-flow graph signifying the topology of the model. In the realm of graph theory, components and connections of a model are associated with nodes and branches of the signal-flow graph. As the model is modified by adding or deleting components or connections, the signal-flow graph of the model is modified accordingly to keep track of topological modifications. By associating a signal-flow graph to a model, any graph-theoretical analysis can be performed. An example to such an analysis is the determination and braking of algebraic loops.

In Causal, a model can be constructed either by describing it in one-shot or by gradually modifying it by adding new nodes and branches. To show the relation between models and graphs, we start with the latter.

Modifying Models

In this tutorial, we construct the model with the following block diagram

-======= -Model Construction · Jusdl

Model Construction

This tutorial illustrates model construction and the relation between models and graphs. A model consists of components and connections. These components and connections can be associated with a signal-flow graph signifying the topology of the model. In the realm of graph theory, components and connections of a model are associated with nodes and branches of the signal-flow graph. As the model is modified by adding or deleting components or connections, the signal-flow graph of the model is modified accordingly to keep track of topological modifications. By associating a signal-flow graph to a model, any graph-theoretical analysis can be performed. An example to such an analysis is the determination and braking of algebraic loops.

In Jusdl, a model can be constructed either by describing it in one-shot or by gradually modifying it by adding new nodes and branches. To show the relation between models and graphs, we start with the latter.

Modifying Models

In this tutorial, we construct the model with the following block diagram

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +Model Construction · Causal

Model Construction

This tutorial illustrates model construction and the relation between models and graphs. A model consists of components and connections. These components and connections can be associated with a signal-flow graph signifying the topology of the model. In the realm of graph theory, components and connections of a model are associated with nodes and branches of the signal-flow graph. As the model is modified by adding or deleting components or connections, the signal-flow graph of the model is modified accordingly to keep track of topological modifications. By associating a signal-flow graph to a model, any graph-theoretical analysis can be performed. An example to such an analysis is the determination and braking of algebraic loops.

In Causal, a model can be constructed either by describing it in one-shot or by gradually modifying it by adding new nodes and branches. To show the relation between models and graphs, we start with the latter.

Modifying Models

In this tutorial, we construct the model with the following block diagram

model

and with the following signal-flow graph

model @@ -40,11 +36,7 @@ Node(component:Gain(gain:1.0, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64})), idx:3, label:gain) julia> addnode!(model, Writer(), label=:writer) -<<<<<<< HEAD -Node(component:Writer(path:/tmp/1567f818-2f3e-484b-9e44-3e676da57aee, nin:1), idx:4, label:writer)

As the nodes are added to the model, its graph is modified accordingly.

julia> model.graph
-=======
-Node(component:Writer(path:/tmp/eb6aaa1a-07af-4205-a6ca-d897b3fce30c, nin:1), idx:4, label:writer)

As the nodes are added to the model, its graph is modified accordingly.

julia> model.graph
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+Node(component:Writer(path:/tmp/69ebf431-3242-4cba-903d-be7125379e15, nin:1), idx:4, label:writer)

As the nodes are added to the model, its graph is modified accordingly.

julia> model.graph
 {4, 0} directed simple Int64 graph

model has no connections. Let's add our first connection by connecting the first pin of the output port of the node 1 (which is labelled as :gen) to the first input pin of input port of node 2 (which is labelled as :adder).

julia> addbranch!(model, :gen => :adder, 1 => 1)
 Branch(nodepair:1 => 2, indexpair:1 => 1, links:Link{Float64}[Link(state:open, eltype:Float64, isreadable:false, iswritable:false)])

The node labelled with :gen has an output port having one pin, and the node labelled with :adder has an input port of two pins. In our first connection, we connected the first(and the only) pin of the output port of the node labelled with :gen to the first pin of the input port of the node labelled with :adder. The connections are added to model as branches,

julia> model.branches
 1-element Array{Any,1}:
@@ -112,8 +104,4 @@
 
 julia> outneighbors(model.graph, getnode(model, :adder).idx)
 1-element Array{Int64,1}:
-<<<<<<< HEAD
- 3
-======= - 3
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 + 3
diff --git a/docs/build/tutorials/model_simulation/index.html b/docs/build/tutorials/model_simulation/index.html index 3bddb3f6..2553256b 100644 --- a/docs/build/tutorials/model_simulation/index.html +++ b/docs/build/tutorials/model_simulation/index.html @@ -1,13 +1,7 @@ -<<<<<<< HEAD -Model Simulation · Causal

Construction and Simulation of a Simple Model

In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below.

+Model Simulation · Causal

Construction and Simulation of a Simple Model

In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below.

model

Model Simulation

Let us construct the model first. See Model Construction for more detailed information about model construction.

using Causal
-=======
-Model Simulation · Jusdl

Construction and Simulation of a Simple Model

In this tutorial, we will simulate a very simple model consisting of a generator and a writer as shown in the block diagram shown below.

- model -

Model Simulation

Let us construct the model first. See Model Construction for more detailed information about model construction.

using Jusdl
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 
 # Describe the model
 @defmodel model begin
@@ -23,85 +17,45 @@
 reportsim = true

At this point, the model is ready for simulation.

t0 = 0.     # Start time
 dt = 0.01   # Sampling interval
 tf = 10.    # Final time
-<<<<<<< HEAD
-sim = simulate!(model, t0, dt, tf, simdir=simdir, logtofile=logtofile, reportsim=reportsim)
Simulation(state:done, retcode:success, path:/tmp/Simulation-ef0dbbd6-2ae0-4134-b114-c4e71ce87197)

Investigation of Simulation

First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved.

foreach(println, readlines(`ls -al $(sim.path)`))
total 128
-drwxr-xr-x  2 sari sari  4096 Aug 22 12:01 .
-drwxrwxrwt 73 root root 77824 Aug 22 12:02 ..
--rw-r--r--  1 sari sari 15236 Aug 22 12:01 9c602f03-32a5-4b4b-b184-513e36e2a115
--rw-r--r--  1 sari sari 22051 Aug 22 12:02 report.jld2
--rw-r--r--  1 sari sari  1061 Aug 22 12:02 simlog.log

The simulation directory includes a log file simlog.log which helps the user monitor simulation steps.

# Print the contents of log file
-=======
-sim = simulate!(model, t0, dt, tf, simdir=simdir, logtofile=logtofile, reportsim=reportsim)
Simulation(state:done, retcode:success, path:/tmp/Simulation-7473bc7f-2188-4583-a429-5a4ae68a1b4f)

Investigation of Simulation

First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved.

foreach(println, readlines(`ls -al $(sim.path)`))
total 128
-drwxr-xr-x  2 sari sari  4096 Aug 22 12:31 .
-drwxrwxrwt 84 root root 77824 Aug 22 12:31 ..
--rw-r--r--  1 sari sari 15236 Aug 22 12:31 25e52921-40d6-4002-950d-7d28e90f6c4c
--rw-r--r--  1 sari sari 22051 Aug 22 12:31 report.jld2
--rw-r--r--  1 sari sari  1041 Aug 22 12:31 simlog.log

The simulation directory includes a log file simlog.log which helps the user monitor simulation steps.

# Print the contents of log file
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+sim = simulate!(model, t0, dt, tf, simdir=simdir, logtofile=logtofile, reportsim=reportsim)
Simulation(state:done, retcode:success, path:/tmp/Simulation-edfb5169-79f9-4c73-8440-6f85256ae59c)

Investigation of Simulation

First, let us observe Simulation instance sim. We start with the directory in which all simulation files are saved.

foreach(println, readlines(`ls -al $(sim.path)`))
total 128
+drwxr-xr-x   2 sari sari  4096 Aug 24 10:44 .
+drwxrwxrwt 109 root root 77824 Aug 24 10:44 ..
+-rw-r--r--   1 sari sari 15236 Aug 24 10:44 63bcbe07-edd1-4dc5-a8fe-75bdb0c91724
+-rw-r--r--   1 sari sari 22051 Aug 24 10:44 report.jld2
+-rw-r--r--   1 sari sari  1061 Aug 24 10:44 simlog.log

The simulation directory includes a log file simlog.log which helps the user monitor simulation steps.

# Print the contents of log file
 open(joinpath(sim.path, "simlog.log"), "r") do file
     for line in readlines(file)
         println(line)
     end
-<<<<<<< HEAD
-end
┌ Info: 2020-08-22T12:01:54.955 Started simulation...
+end
┌ Info: 2020-08-24T10:44:28.509 Started simulation...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.011 Inspecting model...
+┌ Info: 2020-08-24T10:44:28.548 Inspecting model...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.033 Done.
+┌ Info: 2020-08-24T10:44:28.564 Done.
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.033 Initializing the model...
+┌ Info: 2020-08-24T10:44:28.564 Initializing the model...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.072 Done...
+┌ Info: 2020-08-24T10:44:28.595 Done...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.072 Running the simulation...
+┌ Info: 2020-08-24T10:44:28.595 Running the simulation...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.398 Done...
+┌ Info: 2020-08-24T10:44:28.857 Done...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.398 Terminating the simulation...
+┌ Info: 2020-08-24T10:44:28.857 Terminating the simulation...
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:01:55.512 Done.
+┌ Info: 2020-08-24T10:44:28.924 Done.
 └ @ Causal /home/sari/.julia/dev/Causal/src/utilities/utils.jl:5

report.jld2 file, which includes the information about the simulation and model components, can be read back after the simulation.

julia> using FileIO, JLD2
-=======
-end
┌ Info: 2020-08-22T12:31:34.479 Started simulation...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.589 Inspecting model...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.609 Done.
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.609 Initializing the model...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.64 Done...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.64 Running the simulation...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.952 Done...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:34.952 Terminating the simulation...
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5
-┌ Info: 2020-08-22T12:31:35.067 Done.
-└ @ Jusdl /home/sari/.julia/dev/Jusdl/src/utilities/utils.jl:5

report.jld2 file, which includes the information about the simulation and model components, can be read back after the simulation.

julia> using FileIO, JLD2
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 
 julia> filecontent = load(joinpath(sim.path, "report.jld2"))
 Dict{String,Any} with 9 entries:
   "retcode"         => :success
-<<<<<<< HEAD
-  "name"            => "Simulation-ef0dbbd6-2ae0-4134-b114-c4e71ce87197"
-  "model/callbacks" => nothing
-  "model/name"      => ""
-  "model/clock"     => Clock(t:10.0, dt:0.01, tf:10.0, paused:false, isrunning:…
-  "model/id"        => "055e7668-b557-4842-9344-32d2e1bbc3b9"
-  "components/"     => SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0…
-  "path"            => "/tmp/Simulation-ef0dbbd6-2ae0-4134-b114-c4e71ce87197"
-=======
-  "name"            => "Simulation-7473bc7f-2188-4583-a429-5a4ae68a1b4f"
+  "name"            => "Simulation-edfb5169-79f9-4c73-8440-6f85256ae59c"
   "model/callbacks" => nothing
   "model/name"      => ""
   "model/clock"     => Clock(t:10.0, dt:0.01, tf:10.0, paused:false, isrunning:…
-  "model/id"        => "75359fb6-900d-4b58-afb7-9f166043df42"
+  "model/id"        => "26066427-9dce-41ef-9222-23064309ac83"
   "components/"     => SinewaveGenerator(amp:1.0, freq:1.0, phase:0.0, offset:0…
-  "path"            => "/tmp/Simulation-7473bc7f-2188-4583-a429-5a4ae68a1b4f"
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
+  "path"            => "/tmp/Simulation-edfb5169-79f9-4c73-8440-6f85256ae59c"
   "state"           => :done
 
 julia> clock = filecontent["model/clock"]
@@ -110,13 +64,9 @@
 
 # Plot the data
 using Plots
-<<<<<<< HEAD
 plot(t, x, xlabel="t", ylabel="x", label="")
qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
 connect: Connection refused
-=======
-plot(t, x, xlabel="t", ylabel="x", label="")
connect: Connection refused
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
@@ -155,41 +105,22 @@
 
 # Reading and plotting the simulation data
 t, x = read(getnode(model, :writer).component)
-<<<<<<< HEAD
-plot(t, x)
[ Info: 2020-08-22T12:02:12.697 Started simulation...
-[ Info: 2020-08-22T12:02:12.697 Inspecting model...
+plot(t, x)
[ Info: 2020-08-24T10:44:43.576 Started simulation...
+[ Info: 2020-08-24T10:44:43.576 Inspecting model...
 ┌ Info: 	The model has algrebraic loops:[[5, 6, 8]]
 └ 		Trying to break these loops...
 [ Info: 	Loop [5, 6, 8] is broken
-[ Info: 2020-08-22T12:02:12.924 Done.
-[ Info: 2020-08-22T12:02:12.924 Initializing the model...
-[ Info: 2020-08-22T12:02:13.139 Done...
-[ Info: 2020-08-22T12:02:13.139 Running the simulation...
-[ Info: 2020-08-22T12:02:13.413 Done...
-[ Info: 2020-08-22T12:02:13.413 Terminating the simulation...
-[ Info: 2020-08-22T12:02:13.545 Done.
+[ Info: 2020-08-24T10:44:43.801 Done.
+[ Info: 2020-08-24T10:44:43.801 Initializing the model...
+[ Info: 2020-08-24T10:44:44.028 Done...
+[ Info: 2020-08-24T10:44:44.028 Running the simulation...
+[ Info: 2020-08-24T10:44:44.31 Done...
+[ Info: 2020-08-24T10:44:44.31 Terminating the simulation...
+[ Info: 2020-08-24T10:44:44.361 Done.
 qt.qpa.screen: QXcbConnection: Could not connect to display
 Could not connect to any X display.
-=======
-plot(t, x)
[ Info: 2020-08-22T12:32:02.404 Started simulation...
-[ Info: 2020-08-22T12:32:02.437 Inspecting model...
-┌ Info: 	The model has algrebraic loops:[[5, 6, 8]]
-└ 		Trying to break these loops...
-[ Info: 	Loop [5, 6, 8] is broken
-[ Info: 2020-08-22T12:32:02.728 Done.
-[ Info: 2020-08-22T12:32:02.728 Initializing the model...
-[ Info: 2020-08-22T12:32:02.973 Done...
-[ Info: 2020-08-22T12:32:02.973 Running the simulation...
-[ Info: 2020-08-22T12:32:03.357 Done...
-[ Info: 2020-08-22T12:32:03.357 Terminating the simulation...
-[ Info: 2020-08-22T12:32:03.581 Done.
->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2
 connect: Connection refused
 GKS: can't connect to GKS socket application
 
 GKS: Open failed in routine OPEN_WS
-<<<<<<< HEAD
-GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

-======= -GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

->>>>>>> c5170cf116e3eb0211e4abfc2932fb6ea7bc35c2 +GKS: GKS not in proper state. GKS must be either in the state WSOP or WSAC in routine ACTIVATE_WS

diff --git a/docs/build/tutorials/simple_model_plot.svg b/docs/build/tutorials/simple_model_plot.svg index 3dfec6f2..d880ade2 100644 --- a/docs/build/tutorials/simple_model_plot.svg +++ b/docs/build/tutorials/simple_model_plot.svg @@ -1,183 +1,93 @@ -<<<<<<< HEAD - + - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -