Skip to content
MANUAL

Components and Reuse ​

A component groups parameters, variables, connectors, and equations into a reusable model. A small component might express one constitutive law; a subsystem might contain dozens of connected parts. Both use the same component declaration.

Define a complete behavior ​

This model relaxes toward target with time constant tau: Download as a Dyad projectlanguage_components.zipOpen in Dyad Studio

dyad
component Relaxation
  parameter tau::Real = 1
  parameter target::Real = 0
  variable x::Real
relations
  initial x = 1
  der(x) = (target - x) / tau
end

In Relaxation(), x starts at 1 and approaches the default target of 0. Relaxation(target=2) starts at the same value but approaches 2. The equation determines x throughout the simulation; the parameters set its target and time constant. A simulation of this model requires tau > 0 for the intended relaxation behavior.

Compose a subsystem ​

A charging circuit combines a voltage source, resistor, capacitor, and ground. The source charges the capacitor through the resistor; resistance * capacitance sets the charging time constant.

The constant block supplies the voltage source's input. The electrical connections complete a loop through the resistor and capacitor, with ground fixing the return node at zero volts.

Part of the definitionWhat it does in this circuit
resistor = …Resistor(R=resistance)Creates a resistor subcomponent; the parameter override R=resistance sets the child's R parameter to the circuit's resistance.
connect(source.p, resistor.p)Joins the source and resistor terminals into one electrical node.
initial capacitor.v = 0Starts the capacitor uncharged.
stored_energy = capacitor.C * capacitor.v^2 / 2Defines the capacitor's stored energy in joules.

Each subcomponent contributes its own equations. The connections impose equal voltage and current balance at each electrical node. The circuit adds an initial condition and an equation for stored_energy; capacitor.v and capacitor.C refer to the contained capacitor's voltage and capacitance. See Connectors and Networks for connection semantics.

Expose settings intentionally ​

The circuit's public parameters configure its internal parts. For example, RCCharging(resistance=2000) sets resistor.R to 2000 Ω while retaining the default 5 V supply and 100 μF capacitance. This doubles the charging time constant from 0.1 s to 0.2 s.

Use ordinary parameters for numerical settings and structural parameters for choices that change a component's shape. A final parameter expresses a setting that derived definitions and instances must preserve. See Parameters, Variables, and Equations for these declarations.

Arrays of components ​

A comprehension constructs repeated instances. A structural parameter controls how many instances exist:

dyad
component RelaxationBank
  structural parameter N::Integer = 3
  cells = [Relaxation(tau=i) for i in 1:N]
end

RelaxationBank() creates three cells with tau values of 1, 2, and 3. Each state starts at 1 and approaches 0; the third cell relaxes most slowly. cells[1].x names the first state. A relation loop can connect neighboring elements or relate their variables; see Arrays and repeated equations. Choose N during model construction and construct the model again when changing it.

Inheritance ​

Choose composition when the existing component is a part of your model, and inheritance when the new component specializes its definition.

Modeling choiceUse it whenResulting name
part = Base()The base is a contained part of an assemblypart.x
extends BaseThe new definition specializes the base interface and behaviorx

Inheritance specializes a common definition. extends brings the base component's declarations and relations into the derived component's namespace:

dyad
component SlowRelaxation
  extends Relaxation(tau=5)
end

SlowRelaxation() starts with x = 1 and approaches zero with tau = 5. The inherited state is directly available as x, with the initialization and differential equation from Relaxation. Extending a complete component works well for a named preset; adding an incompatible equation for an inherited state would overconstrain it.

Partial components ​

A partial component defines declarations and equations shared by a family of components. Derived components supply the remaining behavior.

For an electrical family, the shared definition can contain two ports and a current convention. The example below uses the potential and flow fields introduced in Connectors and Networks. TwoPin defines the interface and current balance; LinearResistor adds Ohm's law.

dyad
partial component TwoPin
  p = Pin() {^p}
  n = Pin() {^n}
  variable v::Real
  variable i::Real
relations
  v = p.v - n.v
  i = p.i
  p.i + n.i = 0
metadata {
  "_links": {
    "p": {
      "Dyad": {
        "placement": {"icon": {"iconName": "pos", "x1": -50, "y1": 450, "x2": 50, "y2": 550}}
      }
    },
    "n": {
      "Dyad": {
        "placement": {"icon": {"iconName": "neg", "x1": 950, "y1": 450, "x2": 1050, "y2": 550}}
      }
    }
  }
}
end

component LinearResistor
  extends TwoPin
  parameter R::Real = 1
relations
  v = R * i
end

TwoPin deliberately leaves the relation between voltage and current open. A resistor closes it with v = R * i; another derived component can supply a storage law. Instantiate the completed component in a network that supplies its electrical boundary conditions.

The built-in Pin supplies the pos and neg electrical icons. The port metadata places them on opposite edges using the placement from ElectricalComponents' TwoPin interface. Derived components inherit these placements.

This pattern gives library parts consistent port names, sign conventions, and shared definitions. See the RLC Circuit tutorial for an assembled circuit.

Make a component easy to use ​

Before sharing a component, check that its users can:

  • Configure it through documented public parameters with sensible defaults.

  • Connect its ports using documented physical meanings and sign conventions.

  • Understand its initialization requirements.

  • Run a complete example with the boundary conditions it needs.

For a component library, continue with Julia-Based Component Libraries. Add icons and port placement using Graphical Models and Metadata.