- Building models
- verbosity
- ModelType
- UnknownVariable
- UnknownCategory
- DefaultUnknown
- UnknownConstraint
- Normal
- Negative
- NonNegative
- Positive
- NonPositive
- Unknown
- is_unknown
- DerUnknown
- der
- MExpr
- mexpr
- Equation
- Model
- RefUnknown
- value
- name
- compatible_values
- MTime
- RefBranch
- Branch
- InitialEquation
- PassedUnknown
- delay
- UnknownReactive
- Discrete
- Parameter
- reinit
- LeftVar
- map
- foldp
- @liftd
- pre
- Event
- BoolEvent
- ifelse
- StructuralEvent
- @equations
Building models
The API for building models with Sims. Includes basic types, models, and functions.
verbosity
Sims.verbosity
— Function.Control the verbosity of output.
verbosity(i)
Arguments
i
: Int indicator with the following meanings:i == 0
: don't print informationi == 1
: minimal infoi == 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)
.
ModelType
Sims.ModelType
— Type.The main overall abstract type in Sims.
UnknownVariable
Sims.UnknownVariable
— Type.An abstract type for variables to be solved. Examples include Unknown, DerUnknown, and Parameter.
UnknownCategory
Sims.UnknownCategory
— Type.Categories of Unknown types; used to subtype Unknowns.
DefaultUnknown
Sims.DefaultUnknown
— Type.The default UnknownCategory.
UnknownConstraint
Sims.UnknownConstraint
— Type.Categories of constraints on Unknowns; used to create positive, negative, etc., constraints.
Normal
Sims.Normal
— Type.Indicates no constraint is imposed.
Negative
Sims.Negative
— Type.Indicates unknowns of this type must be constrained to negative values.
NonNegative
Sims.NonNegative
— Type.Indicates unknowns of this type must be constrained to positive or zero values.
Positive
Sims.Positive
— Type.Indicates unknowns of this type must be constrained to positive values.
NonPositive
Sims.NonPositive
— Type.Indicates unknowns of this type must be constrained to negative or zero values.
Unknown
Sims.Unknown
— Type.An Unknown represents variables to be solved in Sims. An Unknown
is a symbolic type. When used in Julia expressions, Unknowns combine into MExpr
s 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, includingUVoltage
andUAngularVelocity
.C
: contstraint on the unknown; possibilities includeNormal
(the default),Positive
,NonNegative
, `Negative
, andNonPositive
.
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 togensym()
x
: initial value and type information, defaults to 0.0label::AbstractString
: labeling string, defaults to ""
Examples
a = 4
b = Unknown(3.0, "len")
a * b + b^2
is_unknown
Sims.is_unknown
— Function.Is the object an UnknownVariable?
DerUnknown
Sims.DerUnknown
— Type.An UnknownVariable representing the derivitive of an Unknown, normally created with der(x)
.
Arguments
x::Unknown
: the Unknown variableval
: initial value, defaults to 0.0
Examples
a = Unknown()
der(a) + 1
typeof(der(a))
der
Sims.der
— Function.Represents the derivative of an Unknown.
der(x::Unknown)
der(x::Unknown, val)
Arguments
x::Unknown
: the Unknown variableval
: initial value, defaults to 0.0
Examples
a = Unknown()
der(a) + 1
MExpr
Sims.MExpr
— Type.Represents expressions used in models.
MExpr(ex::Expr)
Arguments
ex::Expr
: an expression
Examples
a = Unknown()
b = Unknown()
d = a + sin(b)
typeof(d)
mexpr
Sims.mexpr
— Function.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 headargs...
: 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)
Equation
Sims.Equation
— Type.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() )
Model
Sims.Model
— Type.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)
RefUnknown
Sims.RefUnknown
— Type.An UnknownVariable used to allow Arrays as Unknowns. Normally created with getindex
. Defined methods include:
getindex
length
size
hcat
vcat
value
ReactiveBasics.value
— Function.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))
name
Sims.name
— Function.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)
compatible_values
Sims.compatible_values
— Function.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].
MTime
Sims.MTime
— Constant.The model time - a special unknown variable.
RefBranch
Sims.RefBranch
— Type.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
Branch
Sims.Branch
— Function.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 assigningv
ton1 - 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
InitialEquation
Sims.InitialEquation
— Type.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 initializedeqs::Array{Equation}
: a vector of equations, each to be equated to zero during the initial equation solution.
PassedUnknown
Sims.PassedUnknown
— Type.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
delay
Sims.delay
— Function.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
UnknownReactive
Sims.UnknownReactive
— Type.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!
).
Discrete
Sims.Discrete
— Type.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.0x::ReactiveBasics.Signal
: aSignal
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.
Parameter
Sims.Parameter
— Type.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.0sig
: AReactiveBasics.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
reinit
Sims.reinit
— Function.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 DerUnknowny
: 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.
LeftVar
Sims.LeftVar
— Type.A helper type needed to mark unknowns as left-side variables in assignments during event responses.
map
Base.map
— Function.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 eachinputs
argumentinputs::UnknownReactive
: signals to applyf
tot::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.
foldp
ReactiveBasics.foldp
— Function."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 eachinputs
argumentv0
: initial value of the stored stateinputs::UnknownReactive
: signals to applyf
to
Returns
::UnknownReactive
Examples
See the definition of pre for an example.
@liftd
Sims.@liftd
— Macro.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)
pre
Sims.pre
— Function.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
Event
Sims.Event
— Type.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.
BoolEvent
Sims.BoolEvent
— Function.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.
ifelse
Base.ifelse
— Function.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 ModelTypey
: the value to return when truez
: the value to return when false, defaults tonothing
Returns
Either
y
orz
Examples
StructuralEvent
Sims.StructuralEvent
— Type.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 crossingdefault
: the default Model usednew_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)
@equations
Sims.@equations
— Macro.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 abegin
-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