Skip to content
TestDoubleActingCylinder.md

TestDoubleActingCylinder ​

This test case simulates a Double Acting cylinder with an external mass connected to the piston via a flange. The piston starts at the center position, with higher initial pressure in the fixed volume on the right side causing the piston to move left and stop when it hits the left chamber end. At 1 second, the pressure at the left side is increased, causing the piston to move right and stop upon hitting the right chamber end. The connected mass follows the piston movement, demonstrating the dynamic response of the cylinder and the attached load

Usage ​

HydraulicComponents.TestDoubleActingCylinder()

Behavior ​

Behavior of this component cannot be rendered because it includes path variables.

Source ​

dyad
"""
This test case simulates a Double Acting cylinder with an external mass connected 
to the piston via a flange. The piston starts at the center position, with higher 
initial pressure in the fixed volume on the right side causing the piston to move 
left and stop when it hits the left chamber end. At 1 second, the pressure at the 
left side is increased, causing the piston to move right and stop upon hitting the 
right chamber end. The connected mass follows the piston movement, demonstrating 
the dynamic response of the cylinder and the attached load 
"""
component TestDoubleActingCylinder
  double_acting_cylinder = DoubleActingCylinder(L = 1.0, M = 0.2, area_a = 0.001, area_b = 0.001, s0 = 0.5) {
    "Dyad": {"placement": {"diagram": {"x1": 450, "y1": 400, "x2": 550, "y2": 500}}}
  }
  port_a_side = BoundaryPressure() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 290, "y1": 400, "x2": 190, "y2": 500, "rot": 180}
      },
      "tags": []
    }
  }
  fixed_volume = FixedVolume(p0 = 1e6, vol = 100) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 690, "y1": 420, "x2": 790, "y2": 520, "rot": 0}
      },
      "tags": []
    }
  }
  step = BlockComponents.Step(start_time = 1, height = 2e6) {
    "Dyad": {
      "placement": {
        "diagram": {"x1": 20, "y1": 180, "x2": 120, "y2": 280, "sw": 0.1, "sh": 0.1, "rot": 0}
      }
    }
  }
  mass = TranslationalComponents.Mass(L = 1, m = 0.5) {
    "Dyad": {
      "placement": {
        "diagram": {"x1": 590, "x2": 690, "y1": 620, "y2": 720, "sh": 1, "sw": 1, "rot": 0}
      }
    }
  }
  path medium::AbstractMedium = IsothermalCompressible(bulk_modulus = 1e9, let_gas = false)
relations
  initial double_acting_cylinder.port_a.m_flow = 0.0
  connect(port_a_side.port, double_acting_cylinder.port_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(step.y, port_a_side.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 156.5, "y": 230}, {"x": 156.5, "y": 450}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  continuity(medium, fixed_volume.port.medium)
  continuity(medium, port_a_side.port.medium)
  connect(double_acting_cylinder.flange, mass.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 670}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(fixed_volume.port, double_acting_cylinder.port_b) {
    "Dyad": {
      "renderStyle": "standard",
      "edges": [{"S": 1, "M": [{"x": 620, "y": 470}, {"x": 620, "y": 450}], "E": 2}]
    }
  }
metadata {
  "Dyad": {
    "experiments": {},
    "tests": {
      "case1": {
        "stop": 3,
        "atol": {"double_acting_cylinder.s": 0.01},
        "expect": {"signals": ["double_acting_cylinder.s"]}
      }
    },
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 1100,
        "rot": 0,
        "layer": "icon",
        "attrs": {}
      }
    ],
    "icons": {"default": "dyad://Dyad/Default.svg"},
    "path": {},
    "doc": {"behavior": true}
  }
}
end
Flattened Source
dyad
"""
This test case simulates a Double Acting cylinder with an external mass connected 
to the piston via a flange. The piston starts at the center position, with higher 
initial pressure in the fixed volume on the right side causing the piston to move 
left and stop when it hits the left chamber end. At 1 second, the pressure at the 
left side is increased, causing the piston to move right and stop upon hitting the 
right chamber end. The connected mass follows the piston movement, demonstrating 
the dynamic response of the cylinder and the attached load 
"""
component TestDoubleActingCylinder
  double_acting_cylinder = DoubleActingCylinder(L = 1.0, M = 0.2, area_a = 0.001, area_b = 0.001, s0 = 0.5) {
    "Dyad": {"placement": {"diagram": {"x1": 450, "y1": 400, "x2": 550, "y2": 500}}}
  }
  port_a_side = BoundaryPressure() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 290, "y1": 400, "x2": 190, "y2": 500, "rot": 180}
      },
      "tags": []
    }
  }
  fixed_volume = FixedVolume(p0 = 1e6, vol = 100) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 690, "y1": 420, "x2": 790, "y2": 520, "rot": 0}
      },
      "tags": []
    }
  }
  step = BlockComponents.Step(start_time = 1, height = 2e6) {
    "Dyad": {
      "placement": {
        "diagram": {"x1": 20, "y1": 180, "x2": 120, "y2": 280, "sw": 0.1, "sh": 0.1, "rot": 0}
      }
    }
  }
  mass = TranslationalComponents.Mass(L = 1, m = 0.5) {
    "Dyad": {
      "placement": {
        "diagram": {"x1": 590, "x2": 690, "y1": 620, "y2": 720, "sh": 1, "sw": 1, "rot": 0}
      }
    }
  }
  path medium::AbstractMedium = IsothermalCompressible(bulk_modulus = 1e9, let_gas = false)
relations
  initial double_acting_cylinder.port_a.m_flow = 0.0
  connect(port_a_side.port, double_acting_cylinder.port_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(step.y, port_a_side.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 156.5, "y": 230}, {"x": 156.5, "y": 450}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  continuity(medium, fixed_volume.port.medium)
  continuity(medium, port_a_side.port.medium)
  connect(double_acting_cylinder.flange, mass.flange_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 670}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(fixed_volume.port, double_acting_cylinder.port_b) {
    "Dyad": {
      "renderStyle": "standard",
      "edges": [{"S": 1, "M": [{"x": 620, "y": 470}, {"x": 620, "y": 450}], "E": 2}]
    }
  }
metadata {
  "Dyad": {
    "experiments": {},
    "tests": {
      "case1": {
        "stop": 3,
        "atol": {"double_acting_cylinder.s": 0.01},
        "expect": {"signals": ["double_acting_cylinder.s"]}
      }
    },
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 1100,
        "rot": 0,
        "layer": "icon",
        "attrs": {}
      }
    ],
    "icons": {"default": "dyad://Dyad/Default.svg"},
    "path": {},
    "doc": {"behavior": true}
  }
}
end


Test Cases ​

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

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

Test Case case1 ​

julia
@named model_case1 = HydraulicComponents.TestDoubleActingCylinder()
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 = 3e+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.double_acting_cylinder.s])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "HydraulicComponents.TestDoubleActingCylinder_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.double_acting_cylinder.s], width=2, label="Actual value of double_acting_cylinder.s")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of double_acting_cylinder.s")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
  • Examples

  • Experiments

  • Analyses