Skip to content
LIBRARY
examples.Engine1b.md

examples.Engine1b

One-cylinder engine with gas force (planar loop closed by a constraint)

Model of the mechanical part of one cylinder of a combustion engine. A flywheel inertia (initial angular velocity 10 rad/s) drives the crankshaft through the bearing revolute joint. The crank (crank1..crank4) drives the connecting rod and piston, which slide in the cylinder prismatic guide. The gasForce element applies the combustion pressure to the piston.

The mechanism forms a planar kinematic loop. Because the cut forces perpendicular to the loop plane and the in-plane cut torques cannot be uniquely computed for a loop of parallel-axis revolute joints, one joint in the loop (b2) is a RevolutePlanarLoopConstraint instead of a Revolute, which makes the problem well-posed.

The diagram layout (component placements and connection routing) is preserved from the reference one-cylinder engine model: Modelica diagram coordinates (x right, y up, range [-100, 100]) are mapped to Dyad canvas coordinates (x right, y down, range [0, 1000]) by x_d = 500 + 5*x_m, y_d = 500 - 5*y_m, with component rotation rot_d = (360 - rot_m) mod 360. Do not run dyad layout on this model: it auto-rearranges the diagram and discards these coordinates.

Usage

MultibodyComponents.examples.Engine1b()

Behavior

Source

dyad
"""
# One-cylinder engine with gas force (planar loop closed by a constraint)

Model of the mechanical part of one cylinder of a combustion engine. A flywheel
`inertia` (initial angular velocity 10 rad/s) drives the crankshaft through the
`bearing` revolute joint. The crank (`crank1`..`crank4`) drives the connecting
rod and piston, which slide in the `cylinder` prismatic guide. The `gasForce`
element applies the combustion pressure to the piston.

The mechanism forms a planar kinematic loop. Because the cut forces perpendicular
to the loop plane and the in-plane cut torques cannot be uniquely computed for a
loop of parallel-axis revolute joints, one joint in the loop (`b2`) is a
`RevolutePlanarLoopConstraint` instead of a `Revolute`, which makes the problem
well-posed.

The diagram layout (component placements and connection routing) is preserved
from the reference one-cylinder engine model: Modelica diagram coordinates
(x right, y up, range [-100, 100]) are mapped to Dyad canvas coordinates
(x right, y down, range [0, 1000]) by `x_d = 500 + 5*x_m`, `y_d = 500 - 5*y_m`,
with component rotation `rot_d = (360 - rot_m) mod 360`. Do not run `dyad layout`
on this model: it auto-rearranges the diagram and discards these coordinates.
"""
example component Engine1b
  world = MultibodyComponents.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 0, "y1": 900, "x2": 100, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  piston = MultibodyComponents.BodyCylinder(diameter = 0.1, r = [0, -0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 250, "x2": 1000, "y2": 350, "rot": 90}
      },
      "tags": []
    }
  }
  connectingRod = MultibodyComponents.BodyBox(width_dir = [1, 0, 0], width = 0.02, height = 0.06, color = [0, 0, 0.784, 1], r = [0, -0.2, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 1000, "y1": 590, "x2": 900, "y2": 690, "rot": 270}
      },
      "tags": []
    }
  }
  bearing = MultibodyComponents.Revolute(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025, statePriority = 100) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 900, "x2": 300, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  inertia = RotationalComponents.Components.Inertia(J = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 700, "x2": 300, "y2": 800, "rot": 0}
      },
      "tags": []
    }
  }
  crank1 = MultibodyComponents.BodyCylinder(diameter = 0.05, r = [0.1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 350, "y1": 900, "x2": 450, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  crank2 = MultibodyComponents.BodyBox(height = 0.05, width_dir = [1, 0, 0], width = 0.02, r = [0, 0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 850, "x2": 550, "y2": 950, "rot": 270}
      },
      "tags": []
    }
  }
  crank3 = MultibodyComponents.BodyCylinder(diameter = 0.03, r = [0.1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 780, "x2": 800, "y2": 880, "rot": 0}
      },
      "tags": []
    }
  }
  crank4 = MultibodyComponents.BodyBox(height = 0.05, width_dir = [1, 0, 0], width = 0.02, r = [0, -0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 850, "x2": 1000, "y2": 950, "rot": 270}
      },
      "tags": []
    }
  }
  mid = MultibodyComponents.FixedTranslation(r = [0.05, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 550, "y1": 650, "x2": 650, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  cylPosition = MultibodyComponents.FixedTranslation(r = [0.15, 0.45, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 250, "x2": 200, "y2": 350, "rot": 270}
      },
      "tags": []
    }
  }
  gasForce = MultibodyComponents.GasForce2(d = 0.1, L = 0.35) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 50, "x2": 1000, "y2": 150, "rot": 270}
      },
      "tags": []
    }
  }
  b1 = MultibodyComponents.Revolute(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 450, "x2": 800, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  b2 = MultibodyComponents.RevolutePlanarLoopConstraint(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 650, "x2": 800, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  cylinder = MultibodyComponents.Prismatic(n = [0, -1, 0], box_width = 0.02) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 50, "x2": 800, "y2": 150, "rot": 90}
      },
      "tags": []
    }
  }
  rod1 = MultibodyComponents.FixedTranslation(r = [0, -0.2, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 550, "x2": 800, "y2": 650, "rot": 270}
      },
      "tags": []
    }
  }
  rod3 = MultibodyComponents.FixedTranslation(r = [0, -0.1, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 800, "y1": 250, "x2": 700, "y2": 350, "rot": 270}
      },
      "tags": []
    }
  }
relations
  initial inertia.phi = 0
  initial inertia.w = 10
  connect(world.frame_b, bearing.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(crank2.frame_a, crank1.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 950}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bearing.frame_b, crank1.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, cylPosition.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 150, "y": 950}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(crank3.frame_b, crank4.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 880, "y": 830}, {"x": 880, "y": 940}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(inertia.spline_b, bearing.axis) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 350, "y": 750}, {"x": 350, "y": 850}, {"x": 250, "y": 850}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(crank2.frame_b, crank3.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 830}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(crank2.frame_b, mid.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(cylinder.frame_b, rod3.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cylPosition.frame_b, cylinder.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 150, "y": 30}, {"x": 750, "y": 30}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(piston.frame_a, cylinder.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 950, "y": 200}, {"x": 750, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(rod3.frame_b, b1.frame_a) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 750, "y": 400}, {"x": 650, "y": 400}, {"x": 650, "y": 500}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(mid.frame_b, b2.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(b2.frame_b, connectingRod.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 950, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(b2.frame_b, rod1.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 850, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(b1.frame_b, rod1.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 850, "y": 500}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(gasForce.flange_a, cylinder.support) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 950, "y": 150}, {"x": 950, "y": 180}, {"x": 700, "y": 180}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(cylinder.axis, gasForce.flange_b) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 840, "y": 100}, {"x": 840, "y": 30}, {"x": 950, "y": 30}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
end
Flattened Source
dyad
"""
# One-cylinder engine with gas force (planar loop closed by a constraint)

Model of the mechanical part of one cylinder of a combustion engine. A flywheel
`inertia` (initial angular velocity 10 rad/s) drives the crankshaft through the
`bearing` revolute joint. The crank (`crank1`..`crank4`) drives the connecting
rod and piston, which slide in the `cylinder` prismatic guide. The `gasForce`
element applies the combustion pressure to the piston.

The mechanism forms a planar kinematic loop. Because the cut forces perpendicular
to the loop plane and the in-plane cut torques cannot be uniquely computed for a
loop of parallel-axis revolute joints, one joint in the loop (`b2`) is a
`RevolutePlanarLoopConstraint` instead of a `Revolute`, which makes the problem
well-posed.

The diagram layout (component placements and connection routing) is preserved
from the reference one-cylinder engine model: Modelica diagram coordinates
(x right, y up, range [-100, 100]) are mapped to Dyad canvas coordinates
(x right, y down, range [0, 1000]) by `x_d = 500 + 5*x_m`, `y_d = 500 - 5*y_m`,
with component rotation `rot_d = (360 - rot_m) mod 360`. Do not run `dyad layout`
on this model: it auto-rearranges the diagram and discards these coordinates.
"""
example component Engine1b
  world = MultibodyComponents.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 0, "y1": 900, "x2": 100, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  piston = MultibodyComponents.BodyCylinder(diameter = 0.1, r = [0, -0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 250, "x2": 1000, "y2": 350, "rot": 90}
      },
      "tags": []
    }
  }
  connectingRod = MultibodyComponents.BodyBox(width_dir = [1, 0, 0], width = 0.02, height = 0.06, color = [0, 0, 0.784, 1], r = [0, -0.2, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 1000, "y1": 590, "x2": 900, "y2": 690, "rot": 270}
      },
      "tags": []
    }
  }
  bearing = MultibodyComponents.Revolute(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025, statePriority = 100) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 900, "x2": 300, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  inertia = RotationalComponents.Components.Inertia(J = 1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 700, "x2": 300, "y2": 800, "rot": 0}
      },
      "tags": []
    }
  }
  crank1 = MultibodyComponents.BodyCylinder(diameter = 0.05, r = [0.1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 350, "y1": 900, "x2": 450, "y2": 1000, "rot": 0}
      },
      "tags": []
    }
  }
  crank2 = MultibodyComponents.BodyBox(height = 0.05, width_dir = [1, 0, 0], width = 0.02, r = [0, 0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 850, "x2": 550, "y2": 950, "rot": 270}
      },
      "tags": []
    }
  }
  crank3 = MultibodyComponents.BodyCylinder(diameter = 0.03, r = [0.1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 780, "x2": 800, "y2": 880, "rot": 0}
      },
      "tags": []
    }
  }
  crank4 = MultibodyComponents.BodyBox(height = 0.05, width_dir = [1, 0, 0], width = 0.02, r = [0, -0.1, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 850, "x2": 1000, "y2": 950, "rot": 270}
      },
      "tags": []
    }
  }
  mid = MultibodyComponents.FixedTranslation(r = [0.05, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 550, "y1": 650, "x2": 650, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  cylPosition = MultibodyComponents.FixedTranslation(r = [0.15, 0.45, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 250, "x2": 200, "y2": 350, "rot": 270}
      },
      "tags": []
    }
  }
  gasForce = MultibodyComponents.GasForce2(d = 0.1, L = 0.35) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 50, "x2": 1000, "y2": 150, "rot": 270}
      },
      "tags": []
    }
  }
  b1 = MultibodyComponents.Revolute(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 450, "x2": 800, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  b2 = MultibodyComponents.RevolutePlanarLoopConstraint(n = [1, 0, 0], cylinder_length = 0.02, radius = 0.025) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 650, "x2": 800, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  cylinder = MultibodyComponents.Prismatic(n = [0, -1, 0], box_width = 0.02) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 700, "y1": 50, "x2": 800, "y2": 150, "rot": 90}
      },
      "tags": []
    }
  }
  rod1 = MultibodyComponents.FixedTranslation(r = [0, -0.2, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 900, "y1": 550, "x2": 800, "y2": 650, "rot": 270}
      },
      "tags": []
    }
  }
  rod3 = MultibodyComponents.FixedTranslation(r = [0, -0.1, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 800, "y1": 250, "x2": 700, "y2": 350, "rot": 270}
      },
      "tags": []
    }
  }
relations
  initial inertia.phi = 0
  initial inertia.w = 10
  connect(world.frame_b, bearing.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(crank2.frame_a, crank1.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 950}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bearing.frame_b, crank1.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, cylPosition.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 150, "y": 950}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(crank3.frame_b, crank4.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 880, "y": 830}, {"x": 880, "y": 940}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(inertia.spline_b, bearing.axis) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 350, "y": 750}, {"x": 350, "y": 850}, {"x": 250, "y": 850}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(crank2.frame_b, crank3.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 830}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(crank2.frame_b, mid.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(cylinder.frame_b, rod3.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cylPosition.frame_b, cylinder.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 150, "y": 30}, {"x": 750, "y": 30}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(piston.frame_a, cylinder.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 950, "y": 200}, {"x": 750, "y": 200}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(rod3.frame_b, b1.frame_a) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 750, "y": 400}, {"x": 650, "y": 400}, {"x": 650, "y": 500}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(mid.frame_b, b2.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(b2.frame_b, connectingRod.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 950, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(b2.frame_b, rod1.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 850, "y": 700}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(b1.frame_b, rod1.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 850, "y": 500}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(gasForce.flange_a, cylinder.support) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 950, "y": 150}, {"x": 950, "y": 180}, {"x": 700, "y": 180}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
  connect(cylinder.axis, gasForce.flange_b) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 840, "y": 100}, {"x": 840, "y": 30}, {"x": 950, "y": 30}],
          "E": 2
        }
      ],
      "renderStyle": "standard"
    }
  }
metadata {}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses