Skip to content
LIBRARY
Examples.Damper.md

Examples.Damper

Demonstrate the use of damper models.

Replicates the structure of Modelica.Mechanics.Translational.Examples.Damper.

Three parallel systems compare different damping configurations, all starting with the same initial conditions (s=3 m, v=10 m/s, m=1 kg) connected to a wall at s0=4.5 m:

System 1 (top): mass1 → damper1(d=25) → fixed1. Pure velocity-dependent damping, exponential decay of velocity.

System 2 (middle): mass2 → [damper2(d=25) ‖ spring2(c=1, s_rel0=1)] → fixed2. Damper and spring in parallel, damped oscillation.

System 3 (bottom): mass3 → springDamper3(d=25, c=1, s_rel0=1) → fixed3. Single SpringDamper component, equivalent to system 2.

Usage

TranslationalComponents.Examples.Damper()

Behavior

julia
using TranslationalComponents #hide
using ModelingToolkit #hide
@named sys = TranslationalComponents.Examples.Damper() #hide
full_equations(sys) #hide
<< @example-block not executed in draft mode >>

Source

dyad
"""
Demonstrate the use of damper models.

Replicates the structure of Modelica.Mechanics.Translational.Examples.Damper.

Three parallel systems compare different damping configurations, all starting
with the same initial conditions (s=3 m, v=10 m/s, m=1 kg) connected to a
wall at s0=4.5 m:

**System 1 (top):** mass1 → damper1(d=25) → fixed1. Pure velocity-dependent
damping, exponential decay of velocity.

**System 2 (middle):** mass2 → [damper2(d=25) ‖ spring2(c=1, s_rel0=1)]
→ fixed2. Damper and spring in parallel, damped oscillation.

**System 3 (bottom):** mass3 → springDamper3(d=25, c=1, s_rel0=1) → fixed3.
Single SpringDamper component, equivalent to system 2.
"""
example component Damper
  "Mass for system 1"
  mass1 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 20, "x2": 200, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  "Pure damper"
  damper1 = TranslationalComponents.Components.Damper(d = 25) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 440, "y1": 20, "x2": 540, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 1"
  fixed1 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 850, "y1": 170, "x2": 950, "y2": 270, "rot": 0}
      },
      "tags": []
    }
  }
  "Mass for system 2"
  mass2 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 300, "x2": 200, "y2": 400, "rot": 0}
      },
      "tags": []
    }
  }
  "Damper in parallel with spring"
  damper2 = TranslationalComponents.Components.Damper(d = 25) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 300, "x2": 570, "y2": 400, "rot": 0}
      },
      "tags": []
    }
  }
  "Spring in parallel with damper"
  spring2 = TranslationalComponents.Components.Spring(s_rel0 = 1, c = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 450, "x2": 570, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 2"
  fixed2 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 850, "y1": 500, "x2": 950, "y2": 600, "rot": 0}
      },
      "tags": []
    }
  }
  "Mass for system 3"
  mass3 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 120, "y1": 720, "x2": 220, "y2": 820, "rot": 0}
      },
      "tags": []
    }
  }
  "Combined spring-damper"
  spring_damper3 = TranslationalComponents.Components.SpringDamper(s_rel0 = 1, d = 25, c = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 720, "x2": 560, "y2": 820, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 3"
  fixed3 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 860, "y1": 800, "x2": 960, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # System 1: mass → damper → fixed
  connect(mass1.flange_b, damper1.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper1.flange_b, fixed1.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 70}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  # System 2: mass → [damper ‖ spring] → fixed
  connect(mass2.flange_b, damper2.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper2.flange_a, spring2.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 270, "y": 500}], "E": 2}],
      "junctions": [{"x": 270, "y": 350}],
      "renderStyle": "standard"
    }
  }
  connect(damper2.flange_b, spring2.flange_b) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 740, "y": 350}, {"x": 740, "y": 500}], "E": 2}
      ],
      "junctions": [{"x": 570, "y": 350}],
      "renderStyle": "standard"
    }
  }
  connect(damper2.flange_b, fixed2.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 350}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  # System 3: mass → springDamper → fixed
  connect(mass3.flange_b, spring_damper3.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(spring_damper3.flange_b, fixed3.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 910, "y": 770}], "E": 2}],
      "renderStyle": "standard"
    }
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://TranslationalComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 1,
        "atol": {
          "mass1.s": 0.001,
          "mass1.v": 0.001,
          "mass2.s": 0.001,
          "mass2.v": 0.001,
          "mass3.s": 0.001,
          "mass3.v": 0.001
        },
        "expect": {
          "final": {
            "mass1.s": 3.4,
            "mass1.v": 0,
            "mass2.s": 3.38552676,
            "mass2.v": -0.01544582,
            "mass3.s": 3.38552676,
            "mass3.v": -0.01544582
          },
          "signals": [
            "mass1.s",
            "mass1.v",
            "mass2.s",
            "mass2.v",
            "mass3.s",
            "mass3.v",
            "damper1.s_rel",
            "damper1.v_rel",
            "damper2.s_rel",
            "damper2.v_rel",
            "spring_damper3.s_rel",
            "spring_damper3.v_rel"
          ]
        }
      }
    }
  }
}
end
Flattened Source
dyad
"""
Demonstrate the use of damper models.

Replicates the structure of Modelica.Mechanics.Translational.Examples.Damper.

Three parallel systems compare different damping configurations, all starting
with the same initial conditions (s=3 m, v=10 m/s, m=1 kg) connected to a
wall at s0=4.5 m:

**System 1 (top):** mass1 → damper1(d=25) → fixed1. Pure velocity-dependent
damping, exponential decay of velocity.

**System 2 (middle):** mass2 → [damper2(d=25) ‖ spring2(c=1, s_rel0=1)]
→ fixed2. Damper and spring in parallel, damped oscillation.

**System 3 (bottom):** mass3 → springDamper3(d=25, c=1, s_rel0=1) → fixed3.
Single SpringDamper component, equivalent to system 2.
"""
example component Damper
  "Mass for system 1"
  mass1 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 20, "x2": 200, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  "Pure damper"
  damper1 = TranslationalComponents.Components.Damper(d = 25) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 440, "y1": 20, "x2": 540, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 1"
  fixed1 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 850, "y1": 170, "x2": 950, "y2": 270, "rot": 0}
      },
      "tags": []
    }
  }
  "Mass for system 2"
  mass2 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 300, "x2": 200, "y2": 400, "rot": 0}
      },
      "tags": []
    }
  }
  "Damper in parallel with spring"
  damper2 = TranslationalComponents.Components.Damper(d = 25) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 300, "x2": 570, "y2": 400, "rot": 0}
      },
      "tags": []
    }
  }
  "Spring in parallel with damper"
  spring2 = TranslationalComponents.Components.Spring(s_rel0 = 1, c = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 470, "y1": 450, "x2": 570, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 2"
  fixed2 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 850, "y1": 500, "x2": 950, "y2": 600, "rot": 0}
      },
      "tags": []
    }
  }
  "Mass for system 3"
  mass3 = TranslationalComponents.Components.Mass(L = 1, m = 1, s = initial 3, v = initial 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 120, "y1": 720, "x2": 220, "y2": 820, "rot": 0}
      },
      "tags": []
    }
  }
  "Combined spring-damper"
  spring_damper3 = TranslationalComponents.Components.SpringDamper(s_rel0 = 1, d = 25, c = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 460, "y1": 720, "x2": 560, "y2": 820, "rot": 0}
      },
      "tags": []
    }
  }
  "Wall for system 3"
  fixed3 = TranslationalComponents.Components.Fixed(s0 = 4.5) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 860, "y1": 800, "x2": 960, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # System 1: mass → damper → fixed
  connect(mass1.flange_b, damper1.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper1.flange_b, fixed1.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 70}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  # System 2: mass → [damper ‖ spring] → fixed
  connect(mass2.flange_b, damper2.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(damper2.flange_a, spring2.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 270, "y": 500}], "E": 2}],
      "junctions": [{"x": 270, "y": 350}],
      "renderStyle": "standard"
    }
  }
  connect(damper2.flange_b, spring2.flange_b) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 740, "y": 350}, {"x": 740, "y": 500}], "E": 2}
      ],
      "junctions": [{"x": 570, "y": 350}],
      "renderStyle": "standard"
    }
  }
  connect(damper2.flange_b, fixed2.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 900, "y": 350}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  # System 3: mass → springDamper → fixed
  connect(mass3.flange_b, spring_damper3.flange_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(spring_damper3.flange_b, fixed3.flange) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 910, "y": 770}], "E": 2}],
      "renderStyle": "standard"
    }
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://TranslationalComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 1,
        "atol": {
          "mass1.s": 0.001,
          "mass1.v": 0.001,
          "mass2.s": 0.001,
          "mass2.v": 0.001,
          "mass3.s": 0.001,
          "mass3.v": 0.001
        },
        "expect": {
          "final": {
            "mass1.s": 3.4,
            "mass1.v": 0,
            "mass2.s": 3.38552676,
            "mass2.v": -0.01544582,
            "mass3.s": 3.38552676,
            "mass3.v": -0.01544582
          },
          "signals": [
            "mass1.s",
            "mass1.v",
            "mass2.s",
            "mass2.v",
            "mass3.s",
            "mass3.v",
            "damper1.s_rel",
            "damper1.v_rel",
            "damper2.s_rel",
            "damper2.v_rel",
            "spring_damper3.s_rel",
            "spring_damper3.v_rel"
          ]
        }
      }
    }
  }
}
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.Examples.Damper()
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 = 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.mass1.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass1.s], width=2, label="Actual value of mass1.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass1.s")
end
scatter!(plt, [df_case1.t[end]], [3.4], label="Final Condition for `mass1.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.mass1.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass1.v], width=2, label="Actual value of mass1.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass1.v")
end
scatter!(plt, [df_case1.t[end]], [0], label="Final Condition for `mass1.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.mass2.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass2.s], width=2, label="Actual value of mass2.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass2.s")
end
scatter!(plt, [df_case1.t[end]], [3.38552676], label="Final Condition for `mass2.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.mass2.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass2.v], width=2, label="Actual value of mass2.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass2.v")
end
scatter!(plt, [df_case1.t[end]], [-0.01544582], label="Final Condition for `mass2.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.mass3.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass3.s], width=2, label="Actual value of mass3.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass3.s")
end
scatter!(plt, [df_case1.t[end]], [3.38552676], label="Final Condition for `mass3.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.mass3.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.mass3.v], width=2, label="Actual value of mass3.v")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of mass3.v")
end
scatter!(plt, [df_case1.t[end]], [-0.01544582], label="Final Condition for `mass3.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.damper1.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.damper1.s_rel], width=2, label="Actual value of damper1.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of damper1.s_rel")
end
<< @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.damper1.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig7.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.damper1.v_rel], width=2, label="Actual value of damper1.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of damper1.v_rel")
end
<< @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.damper2.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig8.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.damper2.s_rel], width=2, label="Actual value of damper2.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of damper2.s_rel")
end
<< @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.damper2.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig9.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.damper2.v_rel], width=2, label="Actual value of damper2.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of damper2.v_rel")
end
<< @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_damper3.s_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig10.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.spring_damper3.s_rel], width=2, label="Actual value of spring_damper3.s_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of spring_damper3.s_rel")
end
<< @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_damper3.v_rel])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "TranslationalComponents.Examples.Damper_case1_sig11.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.spring_damper3.v_rel], width=2, label="Actual value of spring_damper3.v_rel")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of spring_damper3.v_rel")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>