Symbolic variables and variable metadata
ModelingToolkit uses Symbolics.jl for the symbolic manipulation infrastructure. In fact, the @variables macro is defined in Symbolics.jl. In addition to @variables, ModelingToolkit defines @parameters, @independent_variables, @constants and @brownians. These macros function identically to @variables but allow ModelingToolkit to attach additional metadata.
Missing docstring for Symbolics.@variables. Check Documenter's build log for details.
Missing docstring for @independent_variables. Check Documenter's build log for details.
Symbolic variables can have metadata attached to them. The defaults and guesses assigned at variable construction time are examples of this metadata. ModelingToolkit also defines additional types of metadata.
Variable defaults
Variables can be assigned default values during construction. For example:
@variables x(t) = 1 y(t) = xHere x has a default of 1, and y has a default of x. While both of these cases are stored under the same metadata key, ModelingToolkit treats them differently. Constant (non-symbolic) defaults (such as that of x) are translated to initial conditions (initial_conditions). Symbolic defaults (such as that of y) are translated to bindings (bindings). For more information on the difference between bindings and initial conditions, please refer to the documentation on initialization of systems, and specifically the section on bindings and initial conditions.
Missing docstring for ModelingToolkit.hasdefault. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.getdefault. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.setdefault. Check Documenter's build log for details.
Variable descriptions
Descriptive strings can be attached to variables using the [description = "descriptive string"] syntax:
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
@variables u [description = "This is my input"]
getdescription(u)"This is my input"When variables with descriptions are present in systems, they will be printed when the system is shown in the terminal:
@variables u(t) [description = "A short description of u"]
@parameters p [description = "A description of p"]
@named sys = System([u ~ p], t)Model sys:
Equations (1):
1 standard: see equations(sys)
Unknowns (1): see unknowns(sys)
u(t): A short description of u
Parameters (1): see parameters(sys)
p: A description of pCalling help on the variable u displays the description, alongside other metadata:
help?> u
A variable of type Symbolics.Num (Num wraps anything in a type that is a subtype of Real)
Metadata
≡≡≡≡≡≡≡≡≡≡
ModelingToolkit.VariableDescription: This is my input
Symbolics.VariableSource: (:variables, :u)Missing docstring for ModelingToolkit.VariableDescription. Check Documenter's build log for details.
Connect
Variables in connectors can have connect metadata which describes the type of connections.
Flow is used for variables that represent physical quantities that "flow" ex: current in a resistor. These variables sum up to zero in connections.
Stream can be specified for variables that flow bi-directionally.
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
@variables i(t) [connect = Flow]
@variables k(t) [connect = Stream]
hasconnect(i)truegetconnect(k)StreamMissing docstring for ModelingToolkit.VariableConnectType. Check Documenter's build log for details.
Input or output
Designate a variable as either an input or an output using the following
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
@variables u [input = true]
isinput(u)true@variables y [output = true]
isoutput(y)trueMissing docstring for ModelingToolkit.setinput. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.setoutput. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.VariableInput. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.VariableOutput. Check Documenter's build log for details.
Bounds
Bounds are useful when parameters are to be optimized, or to express intervals of uncertainty.
julia> @variables u [bounds = (-1, 1)];julia> hasbounds(u)truejulia> getbounds(u)(-1, 1)
Bounds can also be specified for array variables. A scalar array bound is applied to each element of the array. A bound may also be specified as an array, in which case the size of the array must match the size of the symbolic variable.
julia> @variables x[1:2, 1:2] [bounds = (-1, 1)];julia> hasbounds(x)truejulia> getbounds(x)(-1, 1)julia> getbounds(x[1, 1])ERROR: AssertionError: !(symbolic_has_known_size(arrx)) || SU.shape(arrx) == SU.shape(b)julia> getbounds(x[1:2, 1])ERROR: AssertionError: !(symbolic_has_known_size(arrx)) || SU.shape(arrx) == SU.shape(b)julia> @variables x[1:2] [bounds = (-Inf, [1.0, Inf])];julia> hasbounds(x)truejulia> getbounds(x)(-Inf, [1.0, Inf])julia> getbounds(x[2])ERROR: AssertionError: !(symbolic_has_known_size(arrx)) || SU.shape(arrx) == SU.shape(b)julia> hasbounds(x[2])ERROR: AssertionError: !(symbolic_has_known_size(arrx)) || SU.shape(arrx) == SU.shape(b)
Missing docstring for ModelingToolkit.VariableBounds. Check Documenter's build log for details.
Guess
Specify an initial guess for variables of a System. This is used when building the InitializationProblem.
julia> @variables u [guess = 1];julia> hasguess(u)truejulia> getguess(u)1
When a system is constructed, the guesses of the involved variables are stored in a Dict in the system. After this point, the guess metadata of the variable is irrelevant.
Mark input as a disturbance
Indicate that an input is not available for control, i.e., it's a disturbance input.
@variables u [input = true, disturbance = true]
isdisturbance(u)trueMark parameter as tunable
Indicate that a parameter can be automatically tuned by parameter optimization or automatic control tuning apps.
@parameters Kp [tunable = true]
istunable(Kp)trueMissing docstring for ModelingToolkit.isconstant. Check Documenter's build log for details.
@constants is a convenient way to create @parameters with tunable = false metadata
Probability distributions
A probability distribution may be associated with a parameter to indicate either uncertainty about its value, or as a prior distribution for Bayesian optimization.
julia> using Distributions;WARNING: using Distributions.shape in module SymbolicUtilsDistributionsExt conflicts with an existing identifier.julia> d = Normal(10, 1);julia> @parameters m [dist = d];julia> hasdist(m)truejulia> getdist(m)Distributions.Normal{Float64}(μ=10.0, σ=1.0)
Irreducible
A variable can be marked irreducible to prevent it from being moved to an observed state. This forces the variable to be computed during solving so that it can be accessed in callbacks
@variables important_value [irreducible = true]
isirreducible(important_value)trueMissing docstring for ModelingToolkit.VariableIrreducible. Check Documenter's build log for details.
State Priority
When a model is structurally simplified, the algorithm will try to ensure that the variables with higher state priority become states of the system. A variable's state priority is a number set using the state_priority metadata.
@variables important_dof [state_priority = 10] unimportant_dof [state_priority = -2]
state_priority(important_dof)10.0Missing docstring for ModelingToolkit.VariableStatePriority. Check Documenter's build log for details.
Units
Units for variables can be designated using symbolic metadata. For more information, please see the model validation and units section of the docs. Note that getunit is not equivalent to get_unit - the former is a metadata getter for individual variables (and is provided so the same interface function for unit exists like other metadata), while the latter is used to handle more general symbolic expressions.
julia> using DynamicQuantities;julia> @variables speed [unit = u"m/s"];julia> hasunit(speed)truejulia> getunit(speed)1.0 m s⁻¹
Missing docstring for ModelingToolkit.VariableUnit. Check Documenter's build log for details.
Variable type
This metadata is used by the System constructor for automatically identifying the different types of variables in a system.
Missing docstring for ModelingToolkit.VariableType. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.MTKVariableTypeCtx. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.isparameter. Check Documenter's build log for details.
Miscellaneous metadata
User-defined metadata can be added using the misc metadata. This can be queried using the hasmisc and getmisc functions.
julia> @variables u [misc = :conserved_parameter] y [misc = [2, 4, 6]];julia> hasmisc(u)truejulia> getmisc(y)3-element Vector{Int64}: 2 4 6
Missing docstring for ModelingToolkit.VariableMisc. Check Documenter's build log for details.
Dumping metadata
ModelingToolkit allows dumping the metadata of a variable as a NamedTuple.
Missing docstring for ModelingToolkit.dump_variable_metadata. Check Documenter's build log for details.
Additional functions
For systems that contain parameters with metadata like described above, have some additional functions defined for convenience. In the example below, we define a system with tunable parameters and extract bounds vectors
@variables x(t)=0 u(t)=0 [input=true] y(t)=0 [output=true]
@parameters T [tunable = true, bounds = (0, Inf)]
@parameters k [tunable = true, bounds = (0, Inf)]
eqs = [D(x) ~ (-x + k * u) / T # A first-order system with time constant T and gain k
y ~ x]
sys = System(eqs, t, name = :tunable_first_order)Model tunable_first_order:
Equations (2):
2 standard: see equations(tunable_first_order)
Unknowns (3): see unknowns(tunable_first_order)
x(t)
u(t)
y(t)
Parameters (2): see parameters(tunable_first_order)
k
Tp = tunable_parameters(sys) # extract all parameters marked as tunable2-element Vector{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}}:
k
Tlb, ub = getbounds(p) # operating on a vector, we get lower and upper bound vectors(lb = [0, 0], ub = [Inf, Inf])b = getbounds(sys) # Operating on the system, we get a dictDict{SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{SymReal}, Tuple{Int64, Float64}} with 2 entries:
T => (0, Inf)
k => (0, Inf)See also:
Missing docstring for tunable_parameters. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.dump_unknowns. Check Documenter's build log for details.
Missing docstring for ModelingToolkit.dump_parameters. Check Documenter's build log for details.
Symbolic operators
ModelingToolkit makes heavy use of "operators". These are custom functions that are applied to symbolic variables. The most common operator is the Differential operator, defined in Symbolics.jl.
Missing docstring for Symbolics.Differential. Check Documenter's build log for details.
ModelingToolkit also defines a plethora of custom operators.
While not an operator, ShiftIndex is commonly used to use Shift operators in a more convenient way when writing discrete systems.
Sampled time operators
The following operators are used in hybrid ODE systems, where part of the dynamics of the system happen at discrete intervals on a clock. While ModelingToolkit cannot yet simulate such systems, it has the capability to represent them.