Skip to content
LIBRARY
Components.Tests.AllComponents.md

Components.Tests.AllComponents

Smoke test exercising all available translational components in a single model.

Replicates the structure of ModelicaTest.Translational.AllComponents.

Top chain: sliding_mass → rod(L=0) → spring(c=1) → damper(d=10) → sliding_mass1 A RelativeStates element spans from sliding_mass.flange_b to damper.flange_a, measuring the relative displacement and velocity across the rod and spring.

Branch from sliding_mass.flange_b: A Force source (driven by a sine signal) and a SpringDamper(c=1, d=1) connect to sliding_mass2. A Fixed ground provides the reaction reference for the two-flange Force component.

ElastoGap branch from sliding_mass2.flange_b: An ElastoGap(c=1, d=1) connects to sliding_mass3. A FixedTemperature closes the thermal energy balance.

Position branch: sine → position (Filtered) → sliding_mass4 Speed branch: sine1 → position1 (Speed, Filtered) → sliding_mass5 Accelerate branch: sine2 → position2 (Accelerate) → sliding_mass6

Initial conditions: all masses at rest at the origin, all relative displacements and velocities zero.

Usage

TranslationalComponents.Components.Tests.AllComponents()

Behavior

julia
using TranslationalComponents #hide
using ModelingToolkit #hide
@named sys = TranslationalComponents.Components.Tests.AllComponents() #hide
let eqs = full_equations(sys); Base.length(eqs) > 25 ? nothing : eqs end #hide
<< @example-block not executed in draft mode >>

Source

dyad
"""
Smoke test exercising all available translational components in a single model.

Replicates the structure of ModelicaTest.Translational.AllComponents.

**Top chain:** sliding_mass → rod(L=0) → spring(c=1) → damper(d=10) → sliding_mass1
A RelativeStates element spans from sliding_mass.flange_b to damper.flange_a,
measuring the relative displacement and velocity across the rod and spring.

**Branch from sliding_mass.flange_b:** A Force source (driven by a sine signal)
and a SpringDamper(c=1, d=1) connect to sliding_mass2. A Fixed ground provides
the reaction reference for the two-flange Force component.

**ElastoGap branch from sliding_mass2.flange_b:** An ElastoGap(c=1, d=1) connects
to sliding_mass3. A FixedTemperature closes the thermal energy balance.

**Position branch:** sine → position (Filtered) → sliding_mass4
**Speed branch:** sine1 → position1 (Speed, Filtered) → sliding_mass5
**Accelerate branch:** sine2 → position2 (Accelerate) → sliding_mass6

Initial conditions: all masses at rest at the origin, all relative
displacements and velocities zero.
"""
test component AllComponents
  "First sliding mass (MSL: slidingMass)"
  sliding_mass = TranslationalComponents.Components.Mass(m = 1, L = 0, s(initial = 0), v(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 1020, "y2": 1120}}}
  }
  "Rigid rod (zero length) connecting sliding_mass to spring"
  rod = TranslationalComponents.Components.Rod(L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 1140, "y2": 1240}}}
  }
  "Linear spring"
  spring = TranslationalComponents.Components.Spring(c = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 1140, "y2": 1240}}}
  }
  "Linear damper"
  damper = TranslationalComponents.Components.Damper(d = 10, s_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 555, "x2": 655, "y1": 1020, "y2": 1120}}}
  }
  "Second sliding mass at the end of the top chain (MSL: slidingMass1)"
  sliding_mass1 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 685, "x2": 785, "y1": 1020, "y2": 1120}}}
  }
  "Relative state measurement from sliding_mass.flange_b to damper.flange_a"
  relative_states = TranslationalComponents.Components.RelativeStates(s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 1020, "y2": 1120}}}
  }
  "Spring-damper on the branch from sliding_mass"
  spring_damper = TranslationalComponents.Components.SpringDamper(c = 1, d = 1, s_rel0 = 0, s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 780, "y2": 880}}}
  }
  "Third sliding mass at the end of the spring-damper branch (MSL: slidingMass2)"
  sliding_mass2 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 780, "y2": 880}}}
  }
  "Force source acting between ground and the junction node"
  force = TranslationalComponents.Sources.Force() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 780, "y2": 880}}}
  }
  "Sine signal driving the force source (MSL: sine4)"
  sine4 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 670, "y2": 770}}}
  }
  "Fixed ground providing reaction reference for the force and source supports"
  ground = TranslationalComponents.Components.Fixed() {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 345, "y2": 445}}}
  }
  "ElastoGap connecting from sliding_mass2 to sliding_mass3"
  elasto_gap = TranslationalComponents.Components.ElastoGap(c = 1, d = 1, s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 555, "x2": 655, "y1": 780, "y2": 880}}}
  }
  "Fourth sliding mass connected via ElastoGap (MSL: slidingMass3)"
  sliding_mass3 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 690, "x2": 790, "y1": 780, "y2": 880}}}
  }
  "Thermal boundary for ElastoGap heat port"
  fixed_temp = ThermalComponents.Sources.FixedTemperature(T = 293.15) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 900, "y2": 1000}}}
  }
  "Sine reference for Position source (MSL: sine)"
  sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 340, "y2": 440}}}
  }
  "Position source — Filtered (MSL: position)"
  position = TranslationalComponents.Sources.Position() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 340, "y2": 440}}}
  }
  "Fifth sliding mass driven by Position source (MSL: slidingMass4)"
  sliding_mass4 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 140, "y2": 240}}}
  }
  "Sine reference for Speed source (MSL: sine1)"
  sine1 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 545, "y2": 645}}}
  }
  "Speed source — Filtered (MSL: position1)"
  position1 = TranslationalComponents.Sources.VelocitySource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 545, "y2": 645}}}
  }
  "Sixth sliding mass driven by Speed source (MSL: slidingMass5)"
  sliding_mass5 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 545, "y2": 645}}}
  }
  "Sine reference for Accelerate source (MSL: sine2)"
  sine2 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {"Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 20, "y2": 120}}}}
  "Accelerate source (MSL: position2)"
  position2 = TranslationalComponents.Sources.AccelerationSource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 20, "y2": 120}}}
  }
  "Seventh sliding mass driven by Accelerate source (MSL: slidingMass6)"
  sliding_mass6 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 20, "y2": 120}}}
  }
relations
  # Top chain
  connect(sliding_mass.flange_b, rod.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 270, "y": 1190}], "E": 2}],
      "junctions": [{"x": 270, "y": 1070}]
    }
  }
  connect(rod.flange_b, spring.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(spring.flange_b, damper.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 540, "y": 1190}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 540, "y": 1070}]
    }
  }
  connect(damper.flange_b, sliding_mass1.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  # RelativeStates across rod + spring (same span as MSL)
  connect(sliding_mass.flange_b, relative_states.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(relative_states.flange_b, damper.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  # Branch: force + spring_damper + sliding_mass2
  connect(sliding_mass.flange_b, spring_damper.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 1070}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 270, "y": 830}]
    }
  }
  connect(spring_damper.flange_b, sliding_mass2.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(force.flange_b, spring_damper.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(force.flange_a, ground.flange) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [
            {"x": 140, "y": 830},
            {"x": 140, "y": 710},
            {"x": 280, "y": 710},
            {"x": 280, "y": 290},
            {"x": 345, "y": 290}
          ],
          "E": 2
        }
      ]
    }
  }
  connect(sine4.y, force.f) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 720}], "E": 2}]}}
  # ElastoGap branch from sliding_mass2 (MSL: slidingMass2.flange_b → elastoGap)
  connect(sliding_mass2.flange_b, elasto_gap.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(elasto_gap.flange_b, sliding_mass3.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(elasto_gap.heat_port, fixed_temp.port) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 540, "y": 880}, {"x": 540, "y": 950}], "E": 2}]}
  }
  # Position branch: sine → position → sliding_mass4
  connect(sine.y, position.s_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position.flange, sliding_mass4.flange_a) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 270, "y": 390}, {"x": 270, "y": 190}], "E": 2}]}
  }
  connect(position.support, ground.flange) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 205, "y": 495}], "E": -1},
        {"S": -1, "M": [], "E": -2},
        {"S": -2, "M": [{"x": 345, "y": 290}], "E": 2}
      ],
      "junctions": [{"x": 280, "y": 495}, {"x": 280, "y": 290}]
    }
  }
  initial position.v = 0
  # Speed branch: sine1 → position1 → sliding_mass5
  connect(sine1.y, position1.v_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position1.flange, sliding_mass5.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position1.support, ground.flange) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 205, "y": 700}], "E": -1},
        {"S": -1, "M": [{"x": 280, "y": 290}, {"x": 345, "y": 290}], "E": 2}
      ],
      "junctions": [{"x": 280, "y": 700}]
    }
  }
  # Accelerate branch: sine2 → position2 → sliding_mass6
  connect(sine2.y, position2.a_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position2.flange, sliding_mass6.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position2.support, ground.flange) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 290}, {"x": 345, "y": 290}], "E": 2}]}
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://TranslationalComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 1.1,
        "atol": {
          "sliding_mass.s": 0.001,
          "sliding_mass.v": 0.001,
          "damper.s_rel": 0.001,
          "relative_states.s_rel": 0.001,
          "relative_states.v_rel": 0.001,
          "spring_damper.s_rel": 0.001,
          "spring_damper.v_rel": 0.001,
          "elasto_gap.s_rel": 0.001,
          "elasto_gap.v_rel": 0.001,
          "position.s": 0.001,
          "position.v": 0.01,
          "position1.s": 0.001,
          "position1.v": 0.01,
          "position2.s": 0.001,
          "position2.v": 0.001
        },
        "expect": {
          "final": {
            "sliding_mass.s": 0.07425,
            "sliding_mass.v": -0.0935,
            "damper.s_rel": -0.00582,
            "relative_states.s_rel": -0.04583,
            "relative_states.v_rel": 0.1563,
            "spring_damper.s_rel": -0.02107,
            "spring_damper.v_rel": 0.12458,
            "elasto_gap.s_rel": -0.04303,
            "elasto_gap.v_rel": 0.00352,
            "position.s": 0.56547,
            "position.v": 5.18124,
            "position1.s": 0.02858,
            "position1.v": 0.57138,
            "position2.s": 0.16018,
            "position2.v": 0.0304
          },
          "signals": [
            "sliding_mass.s",
            "sliding_mass.v",
            "damper.s_rel",
            "relative_states.s_rel",
            "relative_states.v_rel",
            "spring_damper.s_rel",
            "spring_damper.v_rel",
            "elasto_gap.s_rel",
            "elasto_gap.v_rel",
            "position.s",
            "position.v",
            "position1.s",
            "position1.v",
            "position2.s",
            "position2.v"
          ]
        }
      }
    }
  }
}
end
Flattened Source
dyad
"""
Smoke test exercising all available translational components in a single model.

Replicates the structure of ModelicaTest.Translational.AllComponents.

**Top chain:** sliding_mass → rod(L=0) → spring(c=1) → damper(d=10) → sliding_mass1
A RelativeStates element spans from sliding_mass.flange_b to damper.flange_a,
measuring the relative displacement and velocity across the rod and spring.

**Branch from sliding_mass.flange_b:** A Force source (driven by a sine signal)
and a SpringDamper(c=1, d=1) connect to sliding_mass2. A Fixed ground provides
the reaction reference for the two-flange Force component.

**ElastoGap branch from sliding_mass2.flange_b:** An ElastoGap(c=1, d=1) connects
to sliding_mass3. A FixedTemperature closes the thermal energy balance.

**Position branch:** sine → position (Filtered) → sliding_mass4
**Speed branch:** sine1 → position1 (Speed, Filtered) → sliding_mass5
**Accelerate branch:** sine2 → position2 (Accelerate) → sliding_mass6

Initial conditions: all masses at rest at the origin, all relative
displacements and velocities zero.
"""
test component AllComponents
  "First sliding mass (MSL: slidingMass)"
  sliding_mass = TranslationalComponents.Components.Mass(m = 1, L = 0, s(initial = 0), v(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 1020, "y2": 1120}}}
  }
  "Rigid rod (zero length) connecting sliding_mass to spring"
  rod = TranslationalComponents.Components.Rod(L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 1140, "y2": 1240}}}
  }
  "Linear spring"
  spring = TranslationalComponents.Components.Spring(c = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 1140, "y2": 1240}}}
  }
  "Linear damper"
  damper = TranslationalComponents.Components.Damper(d = 10, s_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 555, "x2": 655, "y1": 1020, "y2": 1120}}}
  }
  "Second sliding mass at the end of the top chain (MSL: slidingMass1)"
  sliding_mass1 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 685, "x2": 785, "y1": 1020, "y2": 1120}}}
  }
  "Relative state measurement from sliding_mass.flange_b to damper.flange_a"
  relative_states = TranslationalComponents.Components.RelativeStates(s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 1020, "y2": 1120}}}
  }
  "Spring-damper on the branch from sliding_mass"
  spring_damper = TranslationalComponents.Components.SpringDamper(c = 1, d = 1, s_rel0 = 0, s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 780, "y2": 880}}}
  }
  "Third sliding mass at the end of the spring-damper branch (MSL: slidingMass2)"
  sliding_mass2 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 780, "y2": 880}}}
  }
  "Force source acting between ground and the junction node"
  force = TranslationalComponents.Sources.Force() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 780, "y2": 880}}}
  }
  "Sine signal driving the force source (MSL: sine4)"
  sine4 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 670, "y2": 770}}}
  }
  "Fixed ground providing reaction reference for the force and source supports"
  ground = TranslationalComponents.Components.Fixed() {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 345, "y2": 445}}}
  }
  "ElastoGap connecting from sliding_mass2 to sliding_mass3"
  elasto_gap = TranslationalComponents.Components.ElastoGap(c = 1, d = 1, s_rel(initial = 0), v_rel(initial = 0)) {
    "Dyad": {"placement": {"diagram": {"x1": 555, "x2": 655, "y1": 780, "y2": 880}}}
  }
  "Fourth sliding mass connected via ElastoGap (MSL: slidingMass3)"
  sliding_mass3 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 690, "x2": 790, "y1": 780, "y2": 880}}}
  }
  "Thermal boundary for ElastoGap heat port"
  fixed_temp = ThermalComponents.Sources.FixedTemperature(T = 293.15) {
    "Dyad": {"placement": {"diagram": {"x1": 425, "x2": 525, "y1": 900, "y2": 1000}}}
  }
  "Sine reference for Position source (MSL: sine)"
  sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 340, "y2": 440}}}
  }
  "Position source — Filtered (MSL: position)"
  position = TranslationalComponents.Sources.Position() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 340, "y2": 440}}}
  }
  "Fifth sliding mass driven by Position source (MSL: slidingMass4)"
  sliding_mass4 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 140, "y2": 240}}}
  }
  "Sine reference for Speed source (MSL: sine1)"
  sine1 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 545, "y2": 645}}}
  }
  "Speed source — Filtered (MSL: position1)"
  position1 = TranslationalComponents.Sources.VelocitySource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 545, "y2": 645}}}
  }
  "Sixth sliding mass driven by Speed source (MSL: slidingMass5)"
  sliding_mass5 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 545, "y2": 645}}}
  }
  "Sine reference for Accelerate source (MSL: sine2)"
  sine2 = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1) {"Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 20, "y2": 120}}}}
  "Accelerate source (MSL: position2)"
  position2 = TranslationalComponents.Sources.AccelerationSource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 20, "y2": 120}}}
  }
  "Seventh sliding mass driven by Accelerate source (MSL: slidingMass6)"
  sliding_mass6 = TranslationalComponents.Components.Mass(m = 1, L = 0) {
    "Dyad": {"placement": {"diagram": {"x1": 295, "x2": 395, "y1": 20, "y2": 120}}}
  }
relations
  # Top chain
  connect(sliding_mass.flange_b, rod.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 270, "y": 1190}], "E": 2}],
      "junctions": [{"x": 270, "y": 1070}]
    }
  }
  connect(rod.flange_b, spring.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(spring.flange_b, damper.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 540, "y": 1190}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 540, "y": 1070}]
    }
  }
  connect(damper.flange_b, sliding_mass1.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  # RelativeStates across rod + spring (same span as MSL)
  connect(sliding_mass.flange_b, relative_states.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(relative_states.flange_b, damper.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  # Branch: force + spring_damper + sliding_mass2
  connect(sliding_mass.flange_b, spring_damper.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 1070}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 270, "y": 830}]
    }
  }
  connect(spring_damper.flange_b, sliding_mass2.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(force.flange_b, spring_damper.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(force.flange_a, ground.flange) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [
            {"x": 140, "y": 830},
            {"x": 140, "y": 710},
            {"x": 280, "y": 710},
            {"x": 280, "y": 290},
            {"x": 345, "y": 290}
          ],
          "E": 2
        }
      ]
    }
  }
  connect(sine4.y, force.f) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 720}], "E": 2}]}}
  # ElastoGap branch from sliding_mass2 (MSL: slidingMass2.flange_b → elastoGap)
  connect(sliding_mass2.flange_b, elasto_gap.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(elasto_gap.flange_b, sliding_mass3.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(elasto_gap.heat_port, fixed_temp.port) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 540, "y": 880}, {"x": 540, "y": 950}], "E": 2}]}
  }
  # Position branch: sine → position → sliding_mass4
  connect(sine.y, position.s_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position.flange, sliding_mass4.flange_a) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 270, "y": 390}, {"x": 270, "y": 190}], "E": 2}]}
  }
  connect(position.support, ground.flange) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 205, "y": 495}], "E": -1},
        {"S": -1, "M": [], "E": -2},
        {"S": -2, "M": [{"x": 345, "y": 290}], "E": 2}
      ],
      "junctions": [{"x": 280, "y": 495}, {"x": 280, "y": 290}]
    }
  }
  initial position.v = 0
  # Speed branch: sine1 → position1 → sliding_mass5
  connect(sine1.y, position1.v_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position1.flange, sliding_mass5.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position1.support, ground.flange) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 205, "y": 700}], "E": -1},
        {"S": -1, "M": [{"x": 280, "y": 290}, {"x": 345, "y": 290}], "E": 2}
      ],
      "junctions": [{"x": 280, "y": 700}]
    }
  }
  # Accelerate branch: sine2 → position2 → sliding_mass6
  connect(sine2.y, position2.a_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position2.flange, sliding_mass6.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}]}}
  connect(position2.support, ground.flange) {
    "Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 290}, {"x": 345, "y": 290}], "E": 2}]}
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://TranslationalComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 1.1,
        "atol": {
          "sliding_mass.s": 0.001,
          "sliding_mass.v": 0.001,
          "damper.s_rel": 0.001,
          "relative_states.s_rel": 0.001,
          "relative_states.v_rel": 0.001,
          "spring_damper.s_rel": 0.001,
          "spring_damper.v_rel": 0.001,
          "elasto_gap.s_rel": 0.001,
          "elasto_gap.v_rel": 0.001,
          "position.s": 0.001,
          "position.v": 0.01,
          "position1.s": 0.001,
          "position1.v": 0.01,
          "position2.s": 0.001,
          "position2.v": 0.001
        },
        "expect": {
          "final": {
            "sliding_mass.s": 0.07425,
            "sliding_mass.v": -0.0935,
            "damper.s_rel": -0.00582,
            "relative_states.s_rel": -0.04583,
            "relative_states.v_rel": 0.1563,
            "spring_damper.s_rel": -0.02107,
            "spring_damper.v_rel": 0.12458,
            "elasto_gap.s_rel": -0.04303,
            "elasto_gap.v_rel": 0.00352,
            "position.s": 0.56547,
            "position.v": 5.18124,
            "position1.s": 0.02858,
            "position1.v": 0.57138,
            "position2.s": 0.16018,
            "position2.v": 0.0304
          },
          "signals": [
            "sliding_mass.s",
            "sliding_mass.v",
            "damper.s_rel",
            "relative_states.s_rel",
            "relative_states.v_rel",
            "spring_damper.s_rel",
            "spring_damper.v_rel",
            "elasto_gap.s_rel",
            "elasto_gap.v_rel",
            "position.s",
            "position.v",
            "position1.s",
            "position1.v",
            "position2.s",
            "position2.v"
          ]
        }
      }
    }
  }
}
end


Test Cases

julia
using TranslationalComponents
using DyadInterface: TransientAnalysis, rebuild_sol, ODEAlg
using ModelingToolkit: toggle_namespacing, get_initial_conditions, @named
using CSV, DataFrames, Plots

snapshotsdir = joinpath(dirname(dirname(pathof(TranslationalComponents))), "test", "snapshots")
<< @setup-block not executed in draft mode >>

Test Case case1

julia
@named model_case1 = TranslationalComponents.Components.Tests.AllComponents()
model_case1 = toggle_namespacing(model_case1, false)

model_case1 = toggle_namespacing(model_case1, true)
result_case1 = TransientAnalysis(; model = model_case1, alg = ODEAlg.Auto(), start = 0e+0, stop = 1.1e+0, abstol=1e-6, reltol=1e-6)
sol_case1 = rebuild_sol(result_case1)
<< @setup-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.sliding_mass.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.sliding_mass.s], width=2, label="Actual value of sliding_mass.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of sliding_mass.s")
end
scatter!(plt, [df_case1.t[end]], [0.07425], label="Final Condition for `sliding_mass.s`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.sliding_mass.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.sliding_mass.v], width=2, label="Actual value of sliding_mass.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of sliding_mass.v")
end
scatter!(plt, [df_case1.t[end]], [-0.0935], label="Final Condition for `sliding_mass.v`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.damper.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.damper.s_rel], width=2, label="Actual value of damper.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of damper.s_rel")
end
scatter!(plt, [df_case1.t[end]], [-0.00582], label="Final Condition for `damper.s_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.relative_states.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.relative_states.s_rel], width=2, label="Actual value of relative_states.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of relative_states.s_rel")
end
scatter!(plt, [df_case1.t[end]], [-0.04583], label="Final Condition for `relative_states.s_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.relative_states.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.relative_states.v_rel], width=2, label="Actual value of relative_states.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of relative_states.v_rel")
end
scatter!(plt, [df_case1.t[end]], [0.1563], label="Final Condition for `relative_states.v_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.spring_damper.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.spring_damper.s_rel], width=2, label="Actual value of spring_damper.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of spring_damper.s_rel")
end
scatter!(plt, [df_case1.t[end]], [-0.02107], label="Final Condition for `spring_damper.s_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.spring_damper.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.spring_damper.v_rel], width=2, label="Actual value of spring_damper.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of spring_damper.v_rel")
end
scatter!(plt, [df_case1.t[end]], [0.12458], label="Final Condition for `spring_damper.v_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.elasto_gap.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig7.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.elasto_gap.s_rel], width=2, label="Actual value of elasto_gap.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of elasto_gap.s_rel")
end
scatter!(plt, [df_case1.t[end]], [-0.04303], label="Final Condition for `elasto_gap.s_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.elasto_gap.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig8.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.elasto_gap.v_rel], width=2, label="Actual value of elasto_gap.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of elasto_gap.v_rel")
end
scatter!(plt, [df_case1.t[end]], [0.00352], label="Final Condition for `elasto_gap.v_rel`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig9.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position.s], width=2, label="Actual value of position.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position.s")
end
scatter!(plt, [df_case1.t[end]], [0.56547], label="Final Condition for `position.s`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig10.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position.v], width=2, label="Actual value of position.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position.v")
end
scatter!(plt, [df_case1.t[end]], [5.18124], label="Final Condition for `position.v`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position1.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig11.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position1.s], width=2, label="Actual value of position1.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position1.s")
end
scatter!(plt, [df_case1.t[end]], [0.02858], label="Final Condition for `position1.s`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position1.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig12.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position1.v], width=2, label="Actual value of position1.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position1.v")
end
scatter!(plt, [df_case1.t[end]], [0.57138], label="Final Condition for `position1.v`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position2.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig13.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position2.s], width=2, label="Actual value of position2.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position2.s")
end
scatter!(plt, [df_case1.t[end]], [0.16018], label="Final Condition for `position2.s`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.position2.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Components.Tests.AllComponents_case1_sig14.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.position2.v], width=2, label="Actual value of position2.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of position2.v")
end
scatter!(plt, [df_case1.t[end]], [0.0304], label="Final Condition for `position2.v`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>