DoubleRodCylinder

model DoubleRodCylinder
    import HydraulicsByFluidon.Media.Base.FluidInterface;
    import SI = Modelica.SIunits;

    parameter SI.Length pistonDiameter(displayUnit = "mm") = 0.1 "Piston diameter"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Length rodDiameterA(displayUnit = "mm") = 0.05 "Rod diameter @ port A"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Length rodDiameterB(displayUnit = "mm") = 0.05 "Rod diameter @ port B"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Length cylinderLength(displayUnit = "mm") = 0.4 "Cylinder length"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Length rodLengthA(displayUnit = "mm") = 0.4 "Rod length @ port A"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Length rodLengthB(displayUnit = "mm") = 0.4 "Rod length @ port B"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Angle angle(displayUnit = "deg") = 0 "Inclination angle"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Volume deadVolume(displayUnit = "l") = 1e-4 "Dead volume"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Mass massPiston = 50 "Piston mass"
        annotation (Dialog(group = "Mass"));
    parameter SI.Mass massCylinder = 40 "Cylinder mass"
        annotation (Dialog(group = "Mass"));
    parameter Real fProp(final unit = "N.s/m", final min = 0) = 10000 "Velocity dependent friction"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter SI.Force fCoulomb = 250 "Constant friction/Coulomb force"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter SI.Force fBreakaway = 500 "Breakaway friction force"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter SI.Velocity vM = 0.005 "Velocity parameter for Stribeck friction"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter Boolean relFric = false "Use \"relative friction factor\" to calculate friction"
        annotation (
            Dialog(
                tab = "Losses",
                group = "Friction"),
            Evaluate = true,
            HideResult = true,
            nchoices(checkBox = true));
    parameter Real relFricFactor = 0 "Relative friction factor"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter SI.Velocity vSmall = 1e-4 "Relative velocity near to zero"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter SI.VolumeFlowRate leakageFlowRateInternal(min = 0, displayUnit = "l/min") = 1.67e-8 "Internal leakage: volume flow"
        annotation (Dialog(
            tab = "Losses",
            group = "Leakage"));
    parameter SI.Pressure leakagePressureDiffInternal(min = 0) = 1e+7 "Internal leakage: pressure difference"
        annotation (Dialog(
            tab = "Losses",
            group = "Leakage"));
    parameter SI.VolumeFlowRate leakageFlowRateExternal(min = 0, displayUnit = "l/min") = 0 "External leakage: volume flow"
        annotation (Dialog(
            tab = "Losses",
            group = "Leakage"));
    parameter SI.Pressure leakagePressureDiffExternal(min = 0) = 1e+7 "External leakage: pressure difference"
        annotation (Dialog(
            tab = "Losses",
            group = "Leakage"));
    parameter SI.Density leakageReferenceDensity = 860 "Reference density for volume flow and pressure difference"
        annotation (Dialog(
            tab = "Losses",
            group = "Leakage"));
    parameter Boolean forwardFluidProperties = false "Forward fluid properties between ports"
        annotation (Dialog(tab = "Fluid Properties"));
    SI.Position stroke(start = 0, displayUnit = "mm") "Distance between cylinder and piston";
    SI.Velocity relVelocity(start = 0) "Relative speed between cylinder and piston";
    SI.AbsolutePressure pA(start = environment.pAmbient, nominal = 100000) "Pressure in chamber A";
    SI.AbsolutePressure pB(start = environment.pAmbient, nominal = 100000) "Pressure in chamber B";
    Modelica.Mechanics.Translational.Interfaces.Flange_a flange_c "Cylinder flange"
        annotation (Placement(
            visible = true,
            transformation(
                origin = {-100, 0},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0),
            iconTransformation(
                origin = {-120, -40},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0)));
    Modelica.Mechanics.Translational.Interfaces.Flange_a flange_pa "Piston flange @ port A"
        annotation (Placement(
            visible = true,
            transformation(
                origin = {-100, 40},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0),
            iconTransformation(
                origin = {-280, 0},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0)));
    Modelica.Mechanics.Translational.Interfaces.Flange_b flange_pb "Piston flange @ port B"
        annotation (Placement(
            visible = true,
            transformation(
                origin = {100, 0},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0),
            iconTransformation(
                origin = {180, 0},
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0)));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPortA "Hydraulic port A"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-90, -90}, 
                    {-70, -110}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-90, -50}, 
                    {-70, -70}},
                rotation = 0)));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPortB "Hydraulic port B"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {70, -90}, 
                    {90, -110}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {70, -50}, 
                    {90, -70}},
                rotation = 0)));
    Modelica.Blocks.Interfaces.RealOutput strokeOut "Relative position of piston"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {100, 50}, 
                    {120, 70}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {112, 30}, 
                    {132, 50}},
                rotation = 0)));
    HydraulicsByFluidon.Components.Base.SimpleCylinder internalCylinder(angle = angle, cylinderLength = cylinderLength, deadVolume = deadVolume, fCoulomb = fCoulomb, fProp = fProp, fBreakaway = fBreakaway, forwardFluidProperties = forwardFluidProperties, massCylinder = massCylinder, massPiston = massPiston, pistonDiameter = pistonDiameter, rodDiameterA = rodDiameterA, rodDiameterB = rodDiameterB, rodLength = rodLengthB, vM = vM, vSmall = vSmall, relFric = relFric, relFricFactor = relFricFactor) annotation (Placement(
        visible = true,
        transformation(
            origin = {-32, 0},
            extent = {
                {-19, -8}, 
                {21, 12}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Volumes.OpenTank leakageTank annotation (Placement(
        visible = true,
        transformation(
            origin = {20, -50},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Resistors.IdealResistor internalLeakage(forwardFluidProperties = false, NominalPressureDifference = leakagePressureDiffInternal, NominalVolumeFlow = leakageFlowRateInternal, ReferenceDensity = leakageReferenceDensity, resistorType = HydraulicsByFluidon.Types.TResistorTypes.Throttle) annotation (Placement(
        visible = true,
        transformation(
            origin = {-30, -80},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = -90)));
    HydraulicsByFluidon.Components.Resistors.IdealResistor externalLeakage(forwardFluidProperties = true, NominalPressureDifference = leakagePressureDiffExternal, NominalVolumeFlow = leakageFlowRateExternal, ReferenceDensity = leakageReferenceDensity, resistorType = HydraulicsByFluidon.Types.TResistorTypes.Throttle) annotation (Placement(
        visible = true,
        transformation(
            origin = {-10, -40},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 90)));
    Modelica.Mechanics.Translational.Components.Rod offsetRod(L = rodLengthA + rodLengthB) annotation (Placement(
        visible = true,
        transformation(
            origin = {-30, 40},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
protected
    outer HydraulicsByFluidon.Media.Environment environment;
initial equation
    internalCylinder.flange_p.s = flange_pb.s;
equation
    connect(fluidPortB,internalLeakage.fluidPortB) annotation (Line(
        points = {
            {80, -100}, 
            {80, -100}, 
            {80, -80}, 
            {-20, -80}, 
            {-20, -80}},
        color = {0, 93, 152}));
    connect(offsetRod.flange_a,flange_pa) annotation (Line(
        points = {
            {-40, 40}, 
            {-100, 40}, 
            {-100, 40}, 
            {-100, 40}},
        color = {0, 127, 0}));
    connect(offsetRod.flange_b,internalCylinder.flange_p) annotation (Line(
        points = {
            {-20, 40}, 
            {-14, 40}, 
            {-14, 0}, 
            {-14, 0}},
        color = {0, 127, 0}));
    connect(externalLeakage.fluidPortA,leakageTank.fluidPort) annotation (Line(
        points = {
            {0, -40}, 
            {20, -40}, 
            {20, -40}, 
            {20, -40}},
        color = {0, 93, 152}));
    connect(externalLeakage.fluidPortB,internalLeakage.fluidPortB) annotation (Line(
        points = {
            {-20, -40}, 
            {-20, -80}},
        color = {0, 93, 152}));
    connect(internalCylinder.flange_c,flange_c) annotation (Line(
        points = {
            {-44, 0}, 
            {-100, 0}},
        color = {0, 127, 0}));
    connect(internalCylinder.flange_p,flange_pb) annotation (Line(
        points = {
            {-14, 0}, 
            {100, 0}, 
            {100, 0}, 
            {100, 0}},
        color = {0, 127, 0}));
    connect(internalCylinder.strokeOut,strokeOut) annotation (Line(
        points = {
            {-20, 4}, 
            {0, 4}, 
            {0, 60}, 
            {110, 60}},
        color = {0, 0, 127}));
    connect(internalCylinder.fluidPortA,internalLeakage.fluidPortA) annotation (Line(
        points = {
            {-40, -6}, 
            {-40, -80}},
        color = {0, 93, 152}));
    connect(internalCylinder.fluidPortB,externalLeakage.fluidPortB) annotation (Line(
        points = {
            {-24, -6}, 
            {-20, -6}, 
            {-20, -40}},
        color = {0, 93, 152}));
    connect(internalLeakage.fluidPortA,fluidPortA) annotation (Line(
        points = {
            {-40, -80}, 
            {-80, -80}, 
            {-80, -100}},
        color = {0, 93, 152}));
    pA = internalCylinder.pA;
    pB = internalCylinder.pB;
    stroke = internalCylinder.stroke;
    relVelocity = internalCylinder.relVelocity;

    annotation (
        defaultComponentName = "doubleRodCylinder",
        Documentation(info = "<html>\n            <p>\n                Model of a double rod cylinder with Stribeck friction and volumetric losses.\n            </p>\n            <p>\n                The fundamental geometrical properties of the double rod cylinder are the piston and rod diameters (<b>pistonDiameter</b>, <b>rodDiameterA</b>, <b>rodDiameterB</b>) as well as the\n                lengths of the cylinder and the rod (<b>cylinderLength</b> and <b>rodLength</b>). By using the parameter <b>angle</b>, the inclination of the cylinder with respect to the horizon can be adjusted. \n                The resulting forces due to gravity are taken into account automatically, however without inclusion of static fluid masses.\n            </p>\n            <p>\n                For dynamic calculations, the masses of the piston and the cylinder are required. These\n                can be provided by specifying the parameters <var>Piston mass</var> and <var>Cylinder mass</var>.\n                The dynamic mass of the fluid, which acts as an additional inertia, is automatically taken\n                into account by the model.\n            </p>\n            <p>\n                The parameters <var>Breakaway friction force</var>, <var>Constant friction/Coulomb force</var>, <var>Velocity dependent friction</var> \n                and <var>Velocity parameter for Stribeck friction</var> (velocity where the friction force begins to grow linearly) characterize \n                the velocity dependence of the friction force between piston and cylinder.\n                Instead of using the Stribeck friction model, a simplified friction calculation can be enabled by setting the check mark <var>relFric</var>. In this case,\n                the friction force equals the net force acting on the interface between piston and cylinder multiplied by the parameter <var>Relative friction factor</var>.\n                Regardless of which friction model is used, the friction force is not influenced by the inclination of the cylinder or the system pressure.\n                The parameter <var>Relative velocity near to zero</var> is used by the internal state machine of the cylinder model \n                and determines the velocity below which the piston is considered stuck.\n            </p>\n            <p>\n                <center><img src=\"modelica://HydraulicsByFluidon/Resources/Images/Components/Cylinders/DiagramStribeckFriction.png\" width=\"400\"></center>\n            </p>\n            <p>\n                The pressure in both cylinder chambers can be initialized by assigning start values to <var>Pressure in chamber A</var> (bore side) and <var>Pressure in chamber B</var> (rod side).\n                The parameter <var>Dead volume</var> determines the size of the parasitic volume which remains even if the piston has reached the mechanical stops at the cylinder ends.\n            </p>\n            <p>\n                The volumetric losses due to internal and external leakage are parameterized by providing the respective \n                flow rates (<var>Internal leakage: volume flow</var> and <var>External leakage: volume flow</var>),\n                associated pressure drops (<var>Internal leakage: pressure difference</var> and <var>External leakage: pressure difference</var>) \n                and the fluid density <var>Reference density for volume flow and pressure difference</var> for which these values were obtained.\n            </p>\n            <p>\n                The fluid properties can be propagated between the two hydraulic ports by setting the parameter <var>Forward fluid properties</var> to \"true\".\n            </p></html>"),
        Icon(
            coordinateSystem(
                extent = {
                    {-300, -80}, 
                    {210, 120}},
                initialScale = 0.1),
            graphics = {
                Rectangle(
                    fillColor = {255, 255, 255},
                    pattern = LinePattern.None,
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-90, -40}, 
                        {90, 40}}), 
                Line(points = {
                    {90, 10}, 
                    {90, 40}, 
                    {-90, 40}, 
                    {-90, -40}, 
                    {90, -40}, 
                    {90, -10}}), 
                Rectangle(
                    fillColor = {139, 69, 19},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-70, -40}, 
                        {-30, 40}}), 
                Rectangle(
                    fillColor = {255, 255, 0},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-30, -10}, 
                        {150, 10}}), 
                Line(
                    points = {
                        {150, 0}, 
                        {180, 0}},
                    color = {0, 127, 0}), 
                Line(
                    points = {
                        {-90, -40}, 
                        {-120, -40}},
                    color = {0, 127, 0}), 
                Line(points = {
                    {-280, 0}, 
                    {-200, 0}}), 
                Text(
                    lineColor = {0, 0, 255},
                    extent = {
                        {-90, 100}, 
                        {90, 60}},
                    textString = "%name",
                    horizontalAlignment = TextAlignment.Left), 
                Line(points = {
                    {80, -40}, 
                    {80, -60}}), 
                Line(points = {
                    {-80, -40}, 
                    {-80, -60}}), 
                Line(points = {
                    {90, 40}, 
                    {120, 40}}), 
                Rectangle(
                    fillColor = {255, 255, 0},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-250, -15}, 
                        {-70, 15}})}));
end DoubleRodCylinder;