Building models

The API for building models with Sims. Includes basic types, models, and functions.

verbosity

Sims.verbosityFunction.

Control the verbosity of output.

verbosity(i)

Arguments

  • i : Int indicator with the following meanings:

    • i == 0 : don't print information

    • i == 1 : minimal info

    • i == 2 : all info, including events

More options may be added in the future. This function is not exported, so you must qualify it as Sims.verbosity(0).

source

ModelType

Sims.ModelTypeType.

The main overall abstract type in Sims.

source

UnknownVariable

An abstract type for variables to be solved. Examples include Unknown, DerUnknown, and Parameter.

source

UnknownCategory

Categories of Unknown types; used to subtype Unknowns.

source

DefaultUnknown

The default UnknownCategory.

source

UnknownConstraint

Categories of constraints on Unknowns; used to create positive, negative, etc., constraints.

source

Normal

Sims.NormalType.

Indicates no constraint is imposed.

source

Negative

Sims.NegativeType.

Indicates unknowns of this type must be constrained to negative values.

source

NonNegative

Indicates unknowns of this type must be constrained to positive or zero values.

source

Positive

Sims.PositiveType.

Indicates unknowns of this type must be constrained to positive values.

source

NonPositive

Indicates unknowns of this type must be constrained to negative or zero values.

source

Unknown

Sims.UnknownType.

An Unknown represents variables to be solved in Sims. An Unknown is a symbolic type. When used in Julia expressions, Unknowns combine into MExprs which are symbolic representations of equations.

Expressions (of type MExpr) are built up based on Unknown's. Unknown is a symbol with a uniquely generated symbol name. If you have

Unknowns can contain Float64, Complex, and Array{Float64} values. Additionally, Unknowns can be extended to support other types. All Unknown types currently map to positions in an Array{Float64}.

In addition to a value, Unknowns can carry additional metadata, including an identification symbol and a label. In the future, unit information may be added.

Unknowns can also have type parameters. Two parameters are provided:

  • T: type of unknown; several are defined in Sims.Lib, including UVoltage and UAngularVelocity.

  • C: contstraint on the unknown; possibilities include Normal (the default), Positive, NonNegative, `Negative, and NonPositive.

As an example, Voltage is defined as Unknown{UVoltage,Normal} in the standard library. The UVoltage type parameter is a marker to distinguish those Unknown from others. Users can add their own Unknown types. Different Unknown types makes it easier to dispatch on model arguments.

Unknown(s::Symbol, x, label::AbstractString, fixed::Bool)
Unknown()
Unknown(x)
Unknown(s::Symbol, label::AbstractString)
Unknown(x, label::AbstractString)
Unknown(label::AbstractString)
Unknown(s::Symbol, x, fixed::Bool)
Unknown(s::Symbol, x)
Unknown{T,C}(s::Symbol, x, label::AbstractString, fixed::Bool)
Unknown{T,C}()
Unknown{T,C}(x)
Unknown{T,C}(s::Symbol, label::AbstractString)
Unknown{T,C}(x, label::AbstractString)
Unknown{T,C}(label::AbstractString)
Unknown{T,C}(s::Symbol, x, fixed::Bool)
Unknown{T,C}(s::Symbol, x)

Arguments

  • s::Symbol : identification symbol, defaults to gensym()

  • x : initial value and type information, defaults to 0.0

  • label::AbstractString : labeling string, defaults to ""

Examples

  a = 4
  b = Unknown(3.0, "len")
  a * b + b^2
source

is_unknown

Sims.is_unknownFunction.

Is the object an UnknownVariable?

source

DerUnknown

Sims.DerUnknownType.

An UnknownVariable representing the derivitive of an Unknown, normally created with der(x).

Arguments

  • x::Unknown : the Unknown variable

  • val : initial value, defaults to 0.0

Examples

a = Unknown()
der(a) + 1
typeof(der(a))
source

der

Sims.derFunction.

Represents the derivative of an Unknown.

der(x::Unknown)
der(x::Unknown, val)

Arguments

  • x::Unknown : the Unknown variable

  • val : initial value, defaults to 0.0

Examples

a = Unknown()
der(a) + 1
source

MExpr

Sims.MExprType.

Represents expressions used in models.

MExpr(ex::Expr)

Arguments

  • ex::Expr : an expression

Examples

a = Unknown()
b = Unknown()
d = a + sin(b)
typeof(d)
source

mexpr

Sims.mexprFunction.

Create MExpr's (model expressions). Analogous to expr in Base.

This is also useful for wrapping user-defined functions where the built-in mechanisms don't work.

mexpr(head::Symbol, args::ANY...)

Arguments

  • head::Symbol : the expression head

  • args... : values and expressions passed to expression arguments

Returns

  • ex::MExpr : a model expression

Examples

a = Unknown()
b = Unknown()
d = a + sin(b)
typeof(d)
myfun(x) = mexpr(:call, :myfun, x)
source

Equation

Sims.EquationType.

Equations are used in Models. Right now, Equation is defined as Any, but that may change. Normally, Equations are of type Unknown, DerUnknown, MExpr, or Array{Equation} (for nesting models).

Examples

Models return Arrays of Equations. Here is an example:

function Vanderpol()
    y = Unknown(1.0, "y")
    x = Unknown("x")
    Equation[
        der(x, -1.0) - ((1 - y^2) * x - y)      # == 0 is assumed
        der(y) - x
    ]
end
dump( Vanderpol() )
source

Model

Sims.ModelType.

Represents a vector of Equations. For now, Equation equals Any, but in the future, it may only include ModelType's.

Models return Arrays of Equations.

Examples

function Vanderpol()
    y = Unknown(1.0, "y")
    x = Unknown("x")
    Equation[
        der(x, -1.0) - ((1 - y^2) * x - y)      # == 0 is assumed
        der(y) - x
    ]
end
dump( Vanderpol() )
x = sim(Vanderpol(), 50.0)
source

RefUnknown

Sims.RefUnknownType.

An UnknownVariable used to allow Arrays as Unknowns. Normally created with getindex. Defined methods include:

  • getindex

  • length

  • size

  • hcat

  • vcat

source

value

ReactiveBasics.valueFunction.

The value of an object or UnknownVariable.

value(x)

Arguments

  • x : an object

Returns

For standard Julia objects, value(x) returns x. For Unknowns and other ModelTypes, returns the current value of the object. value evaluates immediately, so don't expect to use this in model expressions, except to grab an immediate value.

Examples

v = Voltage(value(n1) - value(n2))
source

name

Sims.nameFunction.

The name of an UnknownVariable.

name(a::UnknownVariable)

Arguments

  • x::UnknownVariable

Returns

  • s::AbstractString : either the label of the Unknown or if that's blank, the symbol name of the Unknown.

Examples

a = Unknown("var1")
name(a)
source

compatible_values

A helper functions to return the base value from an Unknown to use when creating other Unknowns. It is especially useful for taking two model arguments and creating a new Unknown compatible with both arguments.

compatible_values(x,y)
compatible_values(x)

It's still somewhat broken but works for basic cases. No type promotion is currently done.

Arguments

  • x, y : objects or Unknowns

Returns

The returned object has zeros of type and length common to both x and y.

Examples

a = Unknown(45.0 + 10im)
x = Unknown(compatible_values(a))   # Initialized to 0.0 + 0.0im.
a = Unknown()
b = Unknown([1., 0.])
y = Unknown(compatible_values(a,b)) # Initialized to [0.0, 0.0].
source

MTime

Sims.MTimeConstant.

The model time - a special unknown variable.

source

RefBranch

Sims.RefBranchType.

A special ModelType to specify branch flows into nodes. When the model is flattened, equations are created to zero out branch flows into nodes.

See also Branch.

RefBranch(n, i) 

Arguments

  • n : the reference node.

  • i : the flow variable that goes with this node.

References

This nodal description is based on work by David Broman. See the following:

  • http://www.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-173.pdf

  • http://www.bromans.com/software/mkl/mkl-source-1.0.0.zip

  • https://github.com/david-broman/modelyze

Modelyze has both RefBranch and Branch.

Examples

Here is an example of RefBranch used in the definition of a HeatCapacitor in the standard library. hp is the reference node (a HeatPort aka Temperature), and Q_flow is the flow variable.

function HeatCapacitor(hp::HeatPort, C::Signal)
    Q_flow = HeatFlow(compatible_values(hp))
    @equations begin
        RefBranch(hp, Q_flow)
        C .* der(hp) = Q_flow
    end
end

Here is the definition of SignalCurrent from the standard library a model that injects current (a flow variable) between two nodes:

function SignalCurrent(n1::ElectricalNode, n2::ElectricalNode, I::Signal)  
    @equations begin
        RefBranch(n1, I) 
        RefBranch(n2, -I) 
    end
end
source

Branch

Sims.BranchFunction.

A helper Model to connect a branch between two different nodes and specify potential between nodes and the flow between nodes.

See also RefBranch.

Branch(n1, n2, v, i)

Arguments

  • n1 : the positive reference node.

  • n2 : the negative reference node.

  • v : the potential variable between nodes.

  • i : the flow variable between nodes.

Returns

  • ::Array{Equation} : the model, consisting of a RefBranch entry for each node and an equation assigning v to n1 - n2.

References

This nodal description is based on work by David Broman. See the following:

  • http://www.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-173.pdf

  • http://www.bromans.com/software/mkl/mkl-source-1.0.0.zip

  • https://github.com/david-broman/modelyze

Examples

Here is the definition of an electrical resistor in the standard library:

function Resistor(n1::ElectricalNode, n2::ElectricalNode, R::Signal)
    i = Current(compatible_values(n1, n2))
    v = Voltage(value(n1) - value(n2))
    @equations begin
        Branch(n1, n2, v, i)
        v = R .* i
    end
end
source

InitialEquation

A ModelType describing initial equations. Current support is limited and may be broken. There are no tests. The idea is that the equations provided will only be used during the initial solution.

InitialEquation(eqs)

Arguments

  • x::Unknown : the quantity to be initialized

  • eqs::Array{Equation} : a vector of equations, each to be equated to zero during the initial equation solution.

source

PassedUnknown

An UnknownVariable used as a helper for the delay function. It is an identity unknown, but it doesn't replace with a reference to the y array.

PassedUnknown(ref::UnknownVariable)

Arguments

  • ref::UnknownVariable : an Unknown

source

delay

Sims.delayFunction.

A Model specifying a delay to an Unknown.

Internally, Unknowns that are delayed store past history. This is interpolated as needed to find the delayed quantity.

delay(x::Unknown, val)

Arguments

  • x::Unknown : the quantity to be delayed.

  • val : the value of the delay; may be an object or Unknown.

Returns

  • ::MExpr : a delayed Unknown

source

UnknownReactive

An abstract type representing Unknowns that use the ReactiveBasics.jl package. The main types included are Discrete and Parameter. Discrete is normally used as inputs inside of models and includes an initial value that is reset at every simulation run. Parameter is used to pass information from outside to the model. Use this for repeated simulation runs based on parameter variations.

Because they are Unknowns, UnknownReactive types form MExpr's when used in expressions just like Unknowns.

Many of the methods from ReactiveBasics.jl are supported, including map, foldp, filter, and merge. Use reinit to reinitialize a Discrete or a Parameter (equivalent to push!).

source

Discrete

Sims.DiscreteType.

Discrete is a type for discrete variables. These are only changed during events. They are not used by the integrator. Because they are not used by the integrator, almost any type can be used as a discrete variable. Discrete variables wrap a Signal from the ReactiveBasics.jl package.

Constructors

Discrete(initialvalue = 0.0)
Discrete(x::ReactiveBasics.Signal, initialvalue)

Without arguments, Discrete() uses an initial value of 0.0.

Arguments

  • initialvalue : initial value and type information, defaults to 0.0

  • x::ReactiveBasics.Signal : a Signal from the ReactiveBasics.jl package.

Details

Discrete is the main input type for discrete variables. By default, it wraps a ReactiveBasics.Signal type. Discrete variables support data flow using ReactiveBasics.jl. Use reinit to update Discrete variables. Use map to create additional UnknownReactive types that depend on the Discrete input. Use foldp for actions that remember state. For more information on Reactive Programming, see the ReactiveBasics.jl package.

source

Parameter

Sims.ParameterType.

An UnknownReactive type that is useful for passing parameters at the top level.

Arguments

Parameter(x = 0.0)
Parameter(sig::ReactiveBasics.Signal}

Arguments

  • x : initial value and type information, defaults to 0.0

  • sig : A ReactiveBasics.Signal

Details

Parameters can be reinitialized with reinit, either externally or inside models. If you want Parameters to be read-only, wrap them in another UnknownReactive before passing to models. For example, use param_read_only = map(x -> x, param).

Examples

Sims.Examples.Basics.VanderpolWithParameter takes one model argument mu. Here is an example of it used externally with a Parameter:

mu = Parameter(1.0)
ss = create_simstate(VanderpolWithParameter(mu))
vwp1 = sim(ss, 10.0)
reinit(mu, 1.5)
vwp2 = sim(ss, 10.0)
reinit(mu, 1.0)
vwp3 = sim(ss, 10.0) # should be the same as vwp1
source

reinit

Sims.reinitFunction.

reinit is used in Event responses to redefine variables.

reinit(x, y)

Arguments

  • x : the object to be reinitialized; can be a Discrete, Parameter, an Unknown, or DerUnknown

  • y : value for redefinition.

Returns

  • A value stored just prior to an event.

Examples

Here is the definition of Step in the standard library:

function Step(y::Signal, 
              height = 1.0,
              offset = 0.0, 
              startTime = 0.0)
    ymag = Discrete(offset)
    @equations begin
        y = ymag  
        Event(MTime - startTime,
              Equation[reinit(ymag, offset + height)],   # positive crossing
              Equation[reinit(ymag, offset)])            # negative crossing
    end
end

See also IdealThyristor in the standard library.

source

LeftVar

Sims.LeftVarType.

A helper type needed to mark unknowns as left-side variables in assignments during event responses.

source

map

Base.mapFunction.

Create a new UnknownReactive type that links to existing UnknownReactive types (like Discrete and Parameter).

map{T}(f::Function, inputs::UnknownReactive{T}...)
map{T}(f::Function, t::Type, inputs::UnknownReactive{T}...)

Arguments

  • f::Function : the transformation function; takes one argument for each inputs argument

  • inputs::UnknownReactive : signals to apply f to

  • t::Type : optional output type

Note: you cannot use Unknowns or MExprs in f, the transformation function.

Examples

a = Discrete(1)
b = map(x -> x + 1, a)
c = map((x,y) -> x * y, a, b)
reinit(a, 3)
b    # now 4
c    # now 12

See IdealThyristor in the standard library.

Note that you can use Discretes and Parameters in expressions that create MExprs. Compare the following:

j = map((x,y) = x * y, a, b)
k = a * b

In this example, j uses map to immediately connect to a and b. k is an MExpr with a * b embedded inside. When j is used in a model, the j UnknownReactive object is embedded in the model, and it is updated automatically. With k, a * b is inserted into the model, so it's more like a macro; a * b will be evaluated every time in the residual calculation. The advantage of the a * b approach is that the expression can include Unknowns.

source

foldp

ReactiveBasics.foldpFunction.

"Fold over past values" – an UnknownReactive updated based on stored state and additional inputs.

foldp(f::Function, v0, inputs::UnknownReactive{T}...)

Arguments

  • f::Function : the transformation function; the first argument is the stored state followed by one argument for each inputs argument

  • v0 : initial value of the stored state

  • inputs::UnknownReactive : signals to apply f to

Returns

  • ::UnknownReactive

Examples

See the definition of pre for an example.

source

@liftd

Sims.@liftdMacro.

A helper for an expression of UnknownReactive variables

@liftd exp

Note that the expression should not contain Unknowns. To mark the Discrete variables, enter them as Symbols. This uses map().

Arguments

  • exp : an expression, usually containing other Discrete variables

Returns

  • ::Discrete : a signal

Examples

x = Discrete(true)
y = Discrete(false)
z = @liftd :x & !:y
## equivalent to:
z2 = map((x, y) -> x & !y, x, y)
source

pre

Sims.preFunction.

An UnknownReactive based on the previous value of x (normally prior to an event).

See also Event.

pre(x::UnknownReactive)

Arguments

  • x::Discrete

Returns

  • ::UnknownReactive

source

Event

Sims.EventType.

Event is the main type used for hybrid modeling. It contains a condition for root finding and model expressions to process after positive and negative root crossings are detected.

See also BoolEvent.

Event(condition::ModelType, pos_response, neg_response)

Arguments

  • condition::ModelType : an expression used for the event detection.

  • pos_response : an expression indicating what to do when the condition crosses zero positively. May be Model or MExpr.

  • neg_response::Model : an expression indicating what to do when the condition crosses zero in the negative direction. Defaults to Equation[].

Examples

See IdealThyristor in the standard library.

source

BoolEvent

Sims.BoolEventFunction.

BoolEvent is a helper for attaching an event to a boolean variable. In conjunction with ifelse, this allows constructs like Modelica's if blocks.

Note that the lengths of d and condition must match for arrays.

BoolEvent(d::Discrete, condition::ModelType)

Arguments

  • d::Discrete : the discrete variable.

  • condition::ModelType : the model expression(s)

Returns

  • ::Event : a model Event

Examples

See IdealDiode and Limiter in the standard library.

source

ifelse

Base.ifelseFunction.

A function allowing if-then-else action for objections and expressions.

Note that when this is used in a model, it does not trigger an event. You need to use Event or BoolEvent for that. It is used often in conjunction with Event.

ifelse(x, y)
ifelse(x, y, z)

Arguments

  • x : the condition, a Bool or ModelType

  • y : the value to return when true

  • z : the value to return when false, defaults to nothing

Returns

  • Either y or z

Examples

See DeadZone and Limiter in the standard library.

source

StructuralEvent

StructuralEvent defines a type for elements that change the structure of the model. An event is created where the condition crosses zero. When the event is triggered, the model is re-flattened after replacing default with new_relation in the model.

StructuralEvent(condition::MExpr, default, new_relation::Function,
                pos_response, neg_response)

Arguments

  • condition::MExpr : an expression that will trigger the event at a zero crossing

  • default : the default Model used

  • new_relation : a function that returns a model that will replace the default model when the condition triggers the event.

  • pos_response : an expression indicating what to do when the condition crosses zero positively. Defaults to Equation[].

  • neg_response::Model : an expression indicating what to do when the condition crosses zero in the negative direction. Defaults to Equation[].

Examples

Here is an example from examples/breaking_pendulum.jl:

function FreeFall(x,y,vx,vy)
    @equations begin
        der(x) = vx
        der(y) = vy
        der(vx) = 0.0
        der(vy) = -9.81
    end
end

function Pendulum(x,y,vx,vy)
    len = sqrt(x.value^2 + y.value^2)
    phi0 = atan2(x.value, -y.value) 
    phi = Unknown(phi0)
    phid = Unknown()
    @equations begin
        der(phi) = phid
        der(x) = vx
        der(y) = vy
        x = len * sin(phi)
        y = -len * cos(phi)
        der(phid) = -9.81 / len * sin(phi)
    end
end

function BreakingPendulum()
    x = Unknown(cos(pi/4), "x")
    y = Unknown(-cos(pi/4), "y")
    vx = Unknown()
    vy = Unknown()
    Equation[
        StructuralEvent(MTime - 5.0,     # when time hits 5 sec, switch to FreeFall
            Pendulum(x,y,vx,vy),
            () -> FreeFall(x,y,vx,vy))
    ]
end

p_y = sim(BreakingPendulum(), 6.0)  
source

@equations

Sims.@equationsMacro.

A helper to make writing Models a little easier. It allows the use of = in model equations.

@equations begin
    ...
end

Arguments

  • eq : the model equations, normally in a begin - end block.

Returns

  • ::Array{Equation}

Examples

The following are both equivalent:

function Vanderpol1()
    y = Unknown(1.0, "y")
    x = Unknown("x")
    Equation[
        der(x, -1.0) - ((1 - y^2) * x - y)      # == 0 is assumed
        der(y) - x
    ]
end
function Vanderpol2()
    y = Unknown(1.0, "y") 
    x = Unknown("x")
    @equations begin
        der(x, -1.0) = (1 - y^2) * x - y
        der(y) = x
    end
end
source