Skip to content
MANUAL

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.

dyad
# 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
end

Declarations precede relations. Equations and connections follow it. An optional metadata object follows the relations and precedes end.

DefinitionPurpose
component Name ... endA reusable model with equations and subcomponents
partial component Name ... endA base model to complete through extension
example component Name ... endA component marked as an example
test component Name ... endA component marked for testing
analysis Name ... endA configuration extending an analysis implementation
connector Name ... endA physical port with named fields
connector Name = input RealA scalar input signal type; output defines its counterpart
type Name = Real(...)A named type carrying attributes
struct Name ... endA record with typed fields
`enum Name = AB`

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.

dyad
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")
QualifierMeaning
variableA model unknown, typically varying during simulation
parameterA value fixed during a simulation
structural parameterA construction-time value that can determine dimensions, declarations, or equations
constantA fixed value defined when constructing the model
final before a declarationPrevents an enclosing model from overriding the declaration
pathA 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 ​

dyad
component Assembly
  extends BaseComponent(gain = 2.0)
  resistor = Resistor(R = 100.0)
  stage = Controller(filter(T = 0.1))
end

Resistor(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:

dyad
structural parameter use_filter::Boolean = true
filter = Filter() if use_filter

Use the same structural condition around relations that reference an optional element.

Parameter files ​

A subcomponent constructor can apply a TOML or JSON parameter file:

dyad
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.

dyad
type Length = Real(units = "m")
type PositiveLength = Length(min = 0)

struct Point
  x::Real
  y::Real
end

Access 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:

dyad
type BinaryOp = func(::Real, ::Real)::Real
using MyLibrary: myfunc::BinaryOp

Argument 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.

dyad
using Mechanical: Flange, Spring
using .: density::DensityFunction
FormScope
using Mechanical: Flange, SpringImports names from a dependency declared in Project.toml.
using .: density::DensityFunctionImports a typed function from the current library's Julia module.
BlockComponents.Sources.ConstantRefers 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.

FormExample
Integer, real, scientific notation10, 3.14, 1.5e-3
Metric suffix10k means 10000; 2m means 0.002
String and Boolean"water", true, false
Arithmetica + b, a - b, a * b, a / b, a % b, a ^ b
Elementwise arithmetica .+ b, a .- b, a .* b, a ./ b, a .^ b
Comparisona < b, a <= b, a > b, a >= b, a == b, a != b
Logica and b, a or b, !a
Grouping(a + b) * c
Conditional valuecondition ? yes_value : no_value
Function callsin(angle), myfunc(x, y)
Named argumentcustom_func(x, tolerance = 0.01)
Range1:N, 1:2:N
Field and indexmotor.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:

dyad
relations
  y = time < 10 ? 0.0 : 1.0
  der(x) = sin(time) - x

For 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.

dyad
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 ==.

dyad
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.

dyad
connector Pin
  potential v::Real(units = "V")
  flow i::Real(units = "A")
end

connector SignalInput = input Real
connector SignalOutput = output Real
Field qualifierConnection meaning
potentialEqual values across the connection set
flowSigned flows sum to zero; positive flow enters a component
streamA transported outflow property, read from other ports with instream
pathA shared value propagated through the network
input, outputDirected 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:

dyad
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:

dyad
relations
  for i in 1:N
    der(x[i]) = -x[i]
  end

A relation if selects equations at construction time. Use a constant or structural condition:

dyad
relations
  if use_filter
    connect(source.y, filter.u)
    connect(filter.y, sink.u)
  else
    connect(source.y, sink.u)
  end

Additional 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:

dyad
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
end

switch selects the model configuration at construction time using an enum value.

FormMeaning
Initialization.Fixed(x0 = 1.0)Constructs an alternative with a payload.
Initialization.Steady()Constructs an alternative without fields; parentheses are required.
case FixedSelects relations for the named alternative.
mode.x0Accesses the payload through the switched value.
defaultHandles the remaining alternatives.

Assertions ​

A top-level assertion in relations records a model condition and an optional diagnostic message:

dyad
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:

dyad
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
FormMeaning
x@clkSelects 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:

dyad
analysis DecaySimulation
  extends TransientAnalysis(stop = 10.0)
  model = Decay()
end

The 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.

dyad
component AnnotatedDecay
  variable x::Real
relations
  der(x) = -x
metadata {
  "ACME": {"partNumber": "D-1"}
}
end

The Dyad namespace holds tool-defined metadata. Custom namespaces can hold application-specific information. See graphical metadata for diagram authoring.