BladderAccumulator

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

    parameter SI.Volume nominalVolume = 0.005 "Nominal volume";
    parameter SI.Volume deadVolume = 1e-4 "Dead volume";
    parameter SI.AbsolutePressure relBiasingPressure = 5e+6 "Biasing pressure (rel.)";
    parameter SI.Temperature biasingTemperature = 293.1 "Biasing Temperature";
    parameter Real polytropicExponent = 1.4 "Polytropic exponent";
    parameter Boolean isothermalStart = true "Isothermal start"
        annotation (choices(checkBox = true));
    parameter SI.AbsolutePressure initialPressure = environment.pAmbient "Initial pressure of the hydraulic volume";
    parameter Boolean FixedInitialPressure = false "fixed initial pressure";
    parameter Boolean enableVolumeOutput = false "Enable fluid volume output"
        annotation (choices(checkBox = true));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPort(p(start = initialPressure, fixed = FixedInitialPressure, nominal = 100000)) "Hydraulic port"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-10, -10}, 
                    {10, 10}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-10, -110}, 
                    {10, -90}},
                rotation = 0)));
    Modelica.Blocks.Interfaces.RealOutput fluidVolume if enableVolumeOutput "Fluid volume"
        annotation (Placement(transformation(extent = {
            {30, -30}, 
            {50, -10}})));
protected
    outer HydraulicsByFluidon.Media.Environment environment;
    Real bulkModulus;
    Real density;
    Real inversePolytropicExponent = polytropicExponent ^ (-1);
    SI.AbsolutePressure actualBiasingPressure = if initialPressure < biasingPressure then biasingPressureTempCorrected else initialPressure;
    SI.Volume actualGasVolume = if isothermalStart then nominalVolume * biasingPressure / actualBiasingPressure else nominalVolume * (biasingPressure / actualBiasingPressure) ^ (polytropicExponent ^ (-1));
    SI.AbsolutePressure polytropicBiasingPressure = if isothermalStart then actualBiasingPressure * (actualGasVolume / nominalVolume) ^ polytropicExponent else biasingPressureTempCorrected;
    SI.Volume totalVolume = deadVolume + nominalVolume;
    SI.AbsolutePressure biasingPressureTempCorrected = biasingPressure * fluidPort.fluidTemperature / biasingTemperature;
    Real hydCapacity;
    SI.Pressure biasingPressure;
initial equation
    if enableVolumeOutput then 
        fluidVolume = nominalVolume - actualGasVolume;
    end if;
equation
    if enableVolumeOutput then 
        der(fluidVolume) = fluidPort.mFlow / density;
    end if;
    if noEvent(fluidPort.p < polytropicBiasingPressure) then 
        hydCapacity = deadVolume / bulkModulus;
    else 
        hydCapacity = totalVolume / bulkModulus + actualGasVolume * (actualBiasingPressure / fluidPort.p) ^ inversePolytropicExponent * (inversePolytropicExponent / fluidPort.p - bulkModulus ^ (-1));
    end if;
    density * der(fluidPort.p) = if noEvent(0 < hydCapacity) then fluidPort.mFlow / hydCapacity else 0;
    density = FluidInterface.calcRho(fluidPort.fluidId, fluidPort.p, fluidPort.fluidTemperature);
    biasingPressure = relBiasingPressure + environment.pAmbient;
    bulkModulus = FluidInterface.calcKtCorrection(FluidInterface.calcKt(fluidPort.fluidId, fluidPort.p, fluidPort.fluidTemperature), fluidPort.proportionUndissolvedAir, fluidPort.polytropicExponent, fluidPort.p);

    annotation (
        defaultComponentName = "accu",
        Icon(
            coordinateSystem(initialScale = 0.1),
            graphics = {
                Ellipse(
                    origin = {10, -30},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-50, 50}, 
                        {30, -30}},
                    endAngle = 360), 
                Ellipse(
                    origin = {10, 50},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-50, 50}, 
                        {30, -30}},
                    endAngle = 360), 
                Rectangle(
                    lineColor = {255, 255, 255},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-41, 60}, 
                        {41, -20}}), 
                Ellipse(
                    origin = {0, 50},
                    rotation = -143,
                    extent = {
                        {-50, 50}, 
                        {50, -50}},
                    endAngle = 106), 
                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, -8},
                    points = {
                        {-7, 28}, 
                        {-17, 8}, 
                        {-27, 28}, 
                        {-7, 28}}), 
                Text(
                    extent = {
                        {-100, 145}, 
                        {100, 105}},
                    textString = "%name",
                    horizontalAlignment = TextAlignment.Center,
                    lineColor = {0, 0, 255})}),
        Documentation(info = "<html>\n                <p>\n                    Model of a gas-loaded accumulator with a bladder separating the media. Fluid\n                    inertia or the stiffness of the bladder is not considered. The gas is\n                    modelled as an ideal gas.\n                </p>\n                <p>\n                    The parameters <var>Biasing pressure</var>, <var>Nominal volume</var> and <var>Dead volume</var>\n                    describe the accumulator in the unconnected state. At the beginning of a simulation, \n                    the state variables of the accumulator are computed depending on the parameter\n                    <var>Initial pressure of the hydraulic volume</var> and <var>Isothermal start</var>.\n                </p>\n                <p>                                                      \n                    If the bladder expands to its maximum volume, 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 bladder. 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                    If <var>Isothermal start</var> is set to true, it is assumed that the change from biasing\n                    pressure to the initial pressure happened at constant temperature. If\n                    <var>Isothermal start</var> is set to false, a polytropic process incorporating the parameter\n                    <var>Polytropic exponent</var> is assumed.     \n                </p>\n            </html>"));
end BladderAccumulator;