Syntax reference ​
Dyad source files (.dyad) describe reusable models and analysis configurations. This reference covers syntax accepted by the compiler and supported by its ModelingToolkit backend. Start with the language guide for a reading path; use this page to look up a form while writing a model.
Code fragments below illustrate the indicated context. Names such as BaseComponent, Resistor, and MyLibrary stand for definitions supplied by your library.
Files and definitions ​
A file can contain imports, types, structs, enums, connectors, components, and analyses. Definitions end with end when they have a body. A # starts a line comment; comments immediately before a definition or declaration also supply documentation.
# A first-order decay model.
component Decay
parameter rate::Real = 1.0
variable x::Real(guess = 1.0)
relations
initial x = 1.0
der(x) = -rate * x
endDeclarations precede relations. Equations and connections follow it. An optional metadata object follows the relations and precedes end.
| Definition | Purpose |
|---|---|
component Name ... end | A reusable model with equations and subcomponents |
partial component Name ... end | A base model to complete through extension |
example component Name ... end | A component marked as an example |
test component Name ... end | A component marked for testing |
analysis Name ... end | A configuration extending an analysis implementation |
connector Name ... end | A physical port with named fields |
connector Name = input Real | A scalar input signal type; output defines its counterpart |
type Name = Real(...) | A named type carrying attributes |
struct Name ... end | A record with typed fields |
| `enum Name = A | B` |
Declarations and modifications ​
A typed declaration has the form qualifier name::Type(attributes) = value. Attributes and the value are optional where the definition supplies the necessary information.
parameter gain::Real = 2.0
structural parameter N::Integer = 3
final parameter identity::Integer = 123
constant scale::Real = 1000.0
variable position::Real(units = "m", guess = 0.0)
variable velocity::Real(units = "m/s")| Qualifier | Meaning |
|---|---|
variable | A model unknown, typically varying during simulation |
parameter | A value fixed during a simulation |
structural parameter | A construction-time value that can determine dimensions, declarations, or equations |
constant | A fixed value defined when constructing the model |
final before a declaration | Prevents an enclosing model from overriding the declaration |
path | A value shared through a connector network |
A structural parameter can determine an array size or select a component configuration. Changing it requires constructing and processing the model again. final structural parameter combines the structural and override restrictions.
Attributes use named modifications: Real(min = 0, max = 10, guess = 1, units = "m"). A guess supplies a numerical starting point for initialization; an initial equation imposes a constraint. Supply units consistently across connected quantities and equations.
Subcomponents and inheritance ​
component Assembly
extends BaseComponent(gain = 2.0)
resistor = Resistor(R = 100.0)
stage = Controller(filter(T = 0.1))
endResistor(R = 100.0) modifies the resistor's R parameter. Controller(filter(T = 0.1)) modifies T inside its filter. A component can contain multiple extends clauses; each base must resolve to a compatible component definition.
A declaration condition selects whether an element exists when the model is constructed:
structural parameter use_filter::Boolean = true
filter = Filter() if use_filterUse the same structural condition around relations that reference an optional element.
Parameter files ​
A subcomponent constructor can apply a TOML or JSON parameter file:
controller = Controller(apply "dyad://MyLibrary/parameters/controller.toml")The URI identifies a file in the library. File entries must match the target model's parameter and initialization schema. This form belongs directly in a subcomponent's modification list; use ordinary nested modifications for individual nested settings.
Types and imports ​
Primitive and named types ​
The primitive types include Real, Integer, Boolean, String, and Native. Native carries a Julia value, useful for data objects and interfaces implemented in Julia.
type Length = Real(units = "m")
type PositiveLength = Length(min = 0)
struct Point
x::Real
y::Real
endAccess record fields with a dot, such as point.x. Define record fields using scalar or supported record types; enum-valued struct fields are outside the supported ModelingToolkit subset.
Function types and imports ​
A named function type describes a Julia function's interface:
type BinaryOp = func(::Real, ::Real)::Real
using MyLibrary: myfunc::BinaryOpArgument types follow ::; a function type can also declare keyword argument types after ;, as in func(::Real; tolerance::Real)::Real. The return type follows the closing parenthesis.
using Mechanical: Flange, Spring
using .: density::DensityFunction| Form | Scope |
|---|---|
using Mechanical: Flange, Spring | Imports names from a dependency declared in Project.toml. |
using .: density::DensityFunction | Imports a typed function from the current library's Julia module. |
BlockComponents.Sources.Constant | Refers to a definition by its qualified name. |
A library can also expose Julia definitions through dyad/definitions.jl; see Julia-based component libraries.
Expressions ​
Expressions combine literals, references, operators, and function calls. A dotted reference selects a field or nested component; brackets select array elements. Array indices start at one.
| Form | Example |
|---|---|
| Integer, real, scientific notation | 10, 3.14, 1.5e-3 |
| Metric suffix | 10k means 10000; 2m means 0.002 |
| String and Boolean | "water", true, false |
| Arithmetic | a + b, a - b, a * b, a / b, a % b, a ^ b |
| Elementwise arithmetic | a .+ b, a .- b, a .* b, a ./ b, a .^ b |
| Comparison | a < b, a <= b, a > b, a >= b, a == b, a != b |
| Logic | a and b, a or b, !a |
| Grouping | (a + b) * c |
| Conditional value | condition ? yes_value : no_value |
| Function call | sin(angle), myfunc(x, y) |
| Named argument | custom_func(x, tolerance = 0.01) |
| Range | 1:N, 1:2:N |
| Field and index | motor.flange.phi, cells[i].x, A[i, j] |
Use parentheses to make compound conditions and powers unambiguous. Functions must be available to the library and compatible with the symbolic values they receive. A function signature describes its types; it does not make every Julia operation symbolic.
time is the simulation time, and der(x) is the time derivative of x:
relations
y = time < 10 ? 0.0 : 1.0
der(x) = sin(time) - xFor a symbolic condition, the conditional expression becomes an ifelse expression. Both branches must be valid to evaluate, including domains of functions such as sqrt and log.
Arrays ​
Array dimensions follow the type. Use dimensions known when constructing the model.
structural parameter N::Integer = 3
parameter weights::Real[3] = [1.0, 2.0, 3.0]
parameter A::Real[2, 2] = [[1.0, 2.0], [3.0, 4.0]]
variable x::Real[N]
resistors = [Resistor(R = i * 10.0) for i in 1:N]Array literals use commas. A matrix literal contains rows, each written as an array. Rows must have equal length. fill(0.0, 2, 2) creates a uniform matrix. Component comprehensions create one instance per index value.
Equations, initialization, and connections ​
Equations ​
Within relations, lhs = rhs declares an equation. The equation constrains its two sides throughout the model's operation. Equality testing inside an expression uses ==.
relations
initial x = 0.0
der(x) = v
force = mass * der(v)
guess v = 1.0
connect(source.p, resistor.p)Initialization ​
initial equations constrain the initialization problem. guess relations supply initialization guesses, including for variables reached through subcomponents. Choose enough consistent initial conditions for the model's independent states.
Connectors and connections ​
connect joins compatible connectors. A connection can list more than two connectors. The connector's field qualifiers determine the generated connection equations.
connector Pin
potential v::Real(units = "V")
flow i::Real(units = "A")
end
connector SignalInput = input Real
connector SignalOutput = output Real| Field qualifier | Connection meaning |
|---|---|
potential | Equal values across the connection set |
flow | Signed flows sum to zero; positive flow enters a component |
stream | A transported outflow property, read from other ports with instream |
path | A shared value propagated through the network |
input, output | Directed signals |
A connector with stream fields has one flow field. See media and fluids for stream equations and medium configuration.
Path continuity ​
A top-level continuity(a, b) relation joins compatible path values into a shared continuity set. A component-level path declaration supplies the shared value. Use a single provider for a connected set.
Analysis points ​
An analysis point names a signal connection for later analysis:
relations
loop_signal: analysis_point(controller.y, plant.u)See analysis points for its use in linearization and control design.
Structural control ​
Relation loops generate repeated equations or connections while constructing the model:
relations
for i in 1:N
der(x[i]) = -x[i]
endA relation if selects equations at construction time. Use a constant or structural condition:
relations
if use_filter
connect(source.y, filter.u)
connect(filter.y, sink.u)
else
connect(source.y, sink.u)
endAdditional branches use elseif. For a value that changes during simulation, put a conditional expression on an equation's right-hand side.
Enums and switch ​
Enums express a finite set of configurations. An alternative can carry typed data:
enum Initialization = Fixed(x0::Real) | Steady
component ConfigurableDecay
structural parameter mode::Initialization = Initialization.Fixed(x0 = 1.0)
variable x::Real
relations
der(x) = -x
switch mode
case Fixed
initial x = mode.x0
case Steady
initial der(x) = 0.0
end
endswitch selects the model configuration at construction time using an enum value.
| Form | Meaning |
|---|---|
Initialization.Fixed(x0 = 1.0) | Constructs an alternative with a payload. |
Initialization.Steady() | Constructs an alternative without fields; parentheses are required. |
case Fixed | Selects relations for the named alternative. |
mode.x0 | Accesses the payload through the switched value. |
default | Handles the remaining alternatives. |
Assertions ​
A top-level assertion in relations records a model condition and an optional diagnostic message:
relations
assert(temperature > 0, "Temperature must be positive")The compiler passes these conditions to ModelingToolkit as model assertions. Their evaluation follows the generated system and the analysis used to run it.
Clocked syntax ​
Clock parameters appear after a component name; clock bindings appear after a referenced type:
component Delay@[input clk extends Discrete]
u = RealInput@[clk]()
y = RealOutput@[clk]()
relations
initial u@(clk-1) = 0.0
y@clk = u@(clk-1)
end| Form | Meaning |
|---|---|
x@clk | Selects the current sample. |
x@(clk-1) | Selects the preceding sample. |
Block@[clk = other_clock]() | Binds the component's clk to other_clock. |
variable x::Real@[clk = clk] | Declares a clocked variable. |
See Clocks and discrete-time models for clock constraints, initialization, sampling, and holding.
Analyses ​
An analysis extends an existing analysis implementation and supplies model instances and options:
analysis DecaySimulation
extends TransientAnalysis(stop = 10.0)
model = Decay()
endThe base analysis defines its accepted options and result. See analyses for the available workflows and custom analyses to implement one in Julia.
Metadata ​
A definition's metadata block contains a JSON object. Inline element metadata follows a declaration or relation; {^tag} refers to an entry in the definition's _links object.
component AnnotatedDecay
variable x::Real
relations
der(x) = -x
metadata {
"ACME": {"partNumber": "D-1"}
}
endThe Dyad namespace holds tool-defined metadata. Custom namespaces can hold application-specific information. See graphical metadata for diagram authoring.