PistonAccumulator

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

    parameter SI.Length pistonDiameter = 0.2 "Diameter of piston"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Volume nominalVolume = 0.005 "Nominal volume"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Volume gasDeadVolume = 5e-4 "Additional gas volume"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Volume deadVolume = 1e-4 "Fluid dead volume"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Angle angle = 0 "Inclination angle"
        annotation (Dialog(group = "Geometry"));
    parameter SI.Mass massPiston = 1 "Piston mass"
        annotation (Dialog(group = "Mass"));
    parameter SI.Pressure relBiasingPressure = 5e+6 "Biasing pressure (rel.)"
        annotation (Dialog(group = "Gas parameters"));
    parameter SI.Temperature biasingTemperature = 293.1 "Biasing Temperature"
        annotation (Dialog(group = "Gas parameters"));
    parameter Real polytropicExponent = 1.4 "Polytropic exponent"
        annotation (Dialog(group = "Gas parameters"));
    SI.Position stroke(start = 0) "Position of piston";
    SI.Velocity velocity(start = 0) "Velocity of piston";
    SI.AbsolutePressure pA(start = environment.pAmbient, nominal = 100000) "Fluid pressure";
    parameter Real fProp(final unit = "N.s/m", final min = 0) = 10000 "Velocity dependent friction"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter Modelica.SIunits.Force fCoulomb = 25 "Constant friction/Coulomb force"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter Modelica.SIunits.Force fBreakaway = 50 "Breakaway friction force"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    parameter Modelica.SIunits.Velocity vM = 0.005 "Velocity parameter for Stribeck friction"
        annotation (Dialog(
            tab = "Losses",
            group = "Friction"));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPort "Hydraulic port"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-90, -90}, 
                    {-70, -110}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-10, -90}, 
                    {10, -110}},
                rotation = 0)));
    parameter Boolean enableStrokeOutput = false "Enable stroke output"
        annotation (choices(checkBox = true));
    parameter Boolean enableVelocityOutput = false "Enable velocity output"
        annotation (choices(checkBox = true));
    parameter Boolean enableVolumeOutput = false "Enable fluid volume output"
        annotation (choices(checkBox = true));
    output Modelica.Blocks.Interfaces.RealOutput strokeOut if enableStrokeOutput "Stroke of piston"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {40, 50}, 
                    {60, 70}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {40, 50}, 
                    {60, 70}},
                rotation = 0)));
    output Modelica.Blocks.Interfaces.RealOutput velocityOut if enableVelocityOutput "Velocity of piston"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {40, 30}, 
                    {60, 50}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {40, 10}, 
                    {60, 30}},
                rotation = 0)));
    output Modelica.Blocks.Interfaces.RealOutput volumeOut if enableVolumeOutput "Fluid volume"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {40, -70}, 
                    {60, -50}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {40, -30}, 
                    {60, -10}},
                rotation = 0)));
    HydraulicsByFluidon.Components.Base.SimplePlunger internalCylinder(angle = angle, cylinderLength = cylinderLength, deadVolume = deadVolume, fCoulomb = fCoulomb, fProp = fProp, fBreakaway = fBreakaway, massCylinder = 1, massPiston = massPiston, pistonDiameter = pistonDiameter, rodDiameterB = pistonDiameter, rodLength = cylinderLength, vM = vM, vSmall = 1e-4, relFric = false, relFricFactor = 0) annotation (Placement(
        visible = true,
        transformation(
            origin = {-32, 0},
            extent = {
                {-19, -8}, 
                {21, 12}},
            rotation = 0)));
    Modelica.Mechanics.Translational.Components.Fixed fixed annotation (Placement(
        visible = true,
        transformation(
            origin = {-60, 0},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    Modelica.Mechanics.Translational.Sources.Force force annotation (Placement(
        visible = true,
        transformation(
            origin = {10, 0},
            extent = {
                {10, -10}, 
                {-10, 10}},
            rotation = 0)));
protected
    outer HydraulicsByFluidon.Media.Environment environment;
    parameter SI.Length cylinderLength = nominalVolume / (0.25 * Modelica.Constants.pi * pistonDiameter ^ 2) "Cylinder length";
    SI.Volume totalGasVolume = gasDeadVolume + nominalVolume;
    SI.AbsolutePressure biasingPressure = relBiasingPressure + environment.pAmbient;
    SI.AbsolutePressure biasingPressureTempCorrected = biasingPressure * fluidPort.fluidTemperature / biasingTemperature;
    SI.Volume actualGasVolume;
    SI.AbsolutePressure pGas(nominal = 100000) "Gas pressure";
equation
    if enableStrokeOutput then 
        strokeOut = stroke;
    end if;
    if enableVelocityOutput then 
        velocityOut = velocity;
    end if;
    if enableVolumeOutput then 
        volumeOut = 0.25 * Modelica.Constants.pi * pistonDiameter ^ 2 * stroke;
    end if;
    connect(fixed.flange,internalCylinder.flange_c) annotation (Line(
        points = {
            {-60, 0}, 
            {-44, 0}},
        color = {0, 127, 0}));
    connect(force.flange,internalCylinder.flange_p) annotation (Line(
        points = {
            {0, 0}, 
            {-14, 0}},
        color = {0, 127, 0}));
    connect(internalCylinder.fluidPortA,fluidPort) annotation (Line(
        points = {
            {-40, -6}, 
            {-40, -55}, 
            {-80, -55}, 
            {-80, -100}},
        color = {0, 93, 152}));
    pA = internalCylinder.pA;
    pGas = biasingPressureTempCorrected * (totalGasVolume / actualGasVolume) ^ polytropicExponent;
    stroke = internalCylinder.stroke;
    velocity = internalCylinder.relVelocity;
    actualGasVolume = totalGasVolume - 0.25 * Modelica.Constants.pi * pistonDiameter ^ 2 * stroke;
    force.f = -0.25 * ((pGas - environment.pAmbient) * Modelica.Constants.pi) * pistonDiameter ^ 2;

    annotation (
        Icon(
            coordinateSystem(initialScale = 0.1),
            graphics = {
                Ellipse(
                    origin = {10, -30},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-50, 50}, 
                        {30, -30}}), 
                Ellipse(
                    origin = {10, 50},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-50, 50}, 
                        {30, -30}}), 
                Rectangle(
                    lineColor = {255, 255, 255},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-41, 60}, 
                        {41, -20}}), 
                Line(points = {
                    {0, -100}, 
                    {0, -60}}), 
                Line(points = {
                    {-40, 60}, 
                    {-40, -20}}), 
                Line(points = {
                    {40, 60}, 
                    {40, -20}}), 
                Polygon(
                    origin = {17, 32},
                    points = {
                        {-7, 28}, 
                        {-17, 8}, 
                        {-27, 28}, 
                        {-7, 28}}), 
                Text(
                    lineColor = {0, 0, 255},
                    extent = {
                        {-100, 145}, 
                        {100, 105}},
                    textString = "%name"), 
                Rectangle(
                    origin = {0, 20},
                    extent = {
                        {-40, 20}, 
                        {40, -20}})}),
        Documentation(info = "<html>\n            <p>\n                Model of a gas-loaded accumulator with a piston separating the media. Fluid\n                inertia is not considered. The gas is modelled as an ideal gas.\n            </p>\n            <p>\n                <center><img src=\"modelica://HydraulicsByFluidon/Resources/Images/Components/Volumes/PistonAccumulator.png\"></center>\n            </p>\n            <p>\n                The parameters <var>Biasing pressure</var>, <var>Nominal volume</var>, <var>Dead volume</var>,\n                and <var>Additional gas volume</var> describe the accumulator in the unconnected state.\n            </p>\n            <p>                                                      \n                At a piston stroke of 0 m only the <var>Dead volume</var> remains in the\n                accumulator. Due to the typically small dead volume, a high mathematical stiffness\n                of the accumulator can result. This behavior might require choosing a\n                correspondingly small timestep.\n            </p>\n            <p>\n                The parameter <var>Polytropic exponent</var> characterizes how pressure changes affect the\n                volume and stiffness of the gas volume. If <var>Polytropic exponent</var> is set to unity,\n                the change of state within the gas is isothermal. This implies perfect heat\n                transfer between the gas in the bladder and the environment such that no change \n                of temperature occurs in the gas. This situation is encountered in hydraulic\n                accumulators if the load cycles of the liquid are lengthy.\n            </p>\n            <p>\n                If the <var>Polytropic exponent</var> is set to the isentropic exponent (1.4 for air), the\n                gas undergoes an adiabatic change of state which means that no heat exchange\n                with the environment can occur. This is typically the case for very short\n                load cycles.\n            </p>\n            <p>                 \n                The <var>Biasing pressure (rel.)</var> is converted according to the ratio of \n                <var>Biasing Temperature</var> and fluid temperature and the <var>Polytropic exponent</var> \n                at the beginning of the simulation.\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            </p>\n            <p>\n                <center><img src=\"modelica://HydraulicsByFluidon/Resources/Images/Components/Cylinders/DiagramStribeckFriction.png\" width=\"400\"></center>\n            </p>\n        </html>"));
end PistonAccumulator;