ShuttleValve

model ShuttleValve
    import HydraulicsByFluidon.Media.Base.FluidInterface;

    outer HydraulicsByFluidon.Media.Environment environment;
    parameter Modelica.SIunits.VolumeFlowRate NominalVolumeFlow = 5e-4 "Nominal volume flow";
    parameter Modelica.SIunits.Pressure NominalPressureDifference = 500000 "Nominal pressure difference";
    parameter Modelica.SIunits.Density ReferenceDensity = 860 "Reference density for volume flow and pressure difference";
    parameter Modelica.SIunits.Pressure SwitchingThreshold = 100 "Pressure threshold to switch between ports";
    parameter Modelica.SIunits.Volume deadVolume(final min = 1e-9) = 1e-6 "Dead volume at ports"
        annotation (Dialog(group = "Geometry"));
    Modelica.SIunits.AbsolutePressure pA(start = environment.pAmbient, nominal = 100000) "Pressure at port A";
    Modelica.SIunits.AbsolutePressure pB(start = environment.pAmbient, nominal = 100000) "Pressure at port B";
    Modelica.SIunits.AbsolutePressure pC(start = environment.pAmbient, nominal = 100000) "Pressure at port C";
    parameter Boolean forwardFluidProperties = true "Forward fluid properties between ports"
        annotation (
            Dialog(tab = "Fluid Properties"),
            choices(checkBox = true));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPortA(p(start = environment.pAmbient, nominal = 100000)) "Hydraulic port A"
        annotation (Placement(transformation(extent = {
            {-110, -10}, 
            {-90, 10}})));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPortB(p(start = environment.pAmbient, nominal = 100000)) "Hydraulic port B"
        annotation (Placement(transformation(extent = {
            {90, -10}, 
            {110, 10}})));
    HydraulicsByFluidon.Interfaces.FluidPort fluidPortC(p(start = environment.pAmbient, nominal = 100000)) "Hydraulic port C"
        annotation (Placement(
            visible = true,
            transformation(
                extent = {
                    {-10, -110}, 
                    {10, -90}},
                rotation = 0),
            iconTransformation(
                extent = {
                    {-10, -110}, 
                    {10, -90}},
                rotation = 0)));
    HydraulicsByFluidon.Components.Resistors.IdealResistor idealResistor1(NominalVolumeFlow = NominalVolumeFlow, NominalPressureDifference = NominalPressureDifference, ReferenceDensity = ReferenceDensity, forwardFluidProperties = true, resistorType = resistorType) annotation (Placement(
        visible = true,
        transformation(
            origin = {0, -44},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Sources.VariablePressureSource variablePressureSource1 annotation (Placement(
        visible = true,
        transformation(
            origin = {0, -10},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 180)));
    HydraulicsByFluidon.Components.Volumes.Volume volumeA(capacity = deadVolume) annotation (Placement(
        visible = true,
        transformation(
            origin = {-70, 0},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Volumes.Volume volumeB(capacity = deadVolume) annotation (Placement(
        visible = true,
        transformation(
            origin = {70, 0},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Volumes.Volume volumeC(capacity = deadVolume) annotation (Placement(
        visible = true,
        transformation(
            origin = {0, -74},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Sources.VariableMassFlowSource variableFlowSourceA annotation (Placement(
        visible = true,
        transformation(
            origin = {-40, -10},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
    HydraulicsByFluidon.Components.Sources.VariableMassFlowSource variableFlowSourceB annotation (Placement(
        visible = true,
        transformation(
            origin = {40, -10},
            extent = {
                {-10, -10}, 
                {10, 10}},
            rotation = 0)));
protected
    Boolean connectA;
    parameter HydraulicsByFluidon.Types.TResistorTypes resistorType = HydraulicsByFluidon.Types.TResistorTypes.Orifice "Type of the resistor"
        annotation (Dialog(group = "Check Valve"));
initial equation
    if fluidPortB.p < fluidPortA.p then 
        connectA = true;
    else 
        connectA = false;
    end if;
equation
    if forwardFluidProperties then 
        fluidPortA.fluidTemperature = fluidPortC.fluidTemperature;
        fluidPortB.fluidTemperature = fluidPortC.fluidTemperature;
        fluidPortA.fluidId = fluidPortC.fluidId;
        fluidPortB.fluidId = fluidPortC.fluidId;
        fluidPortA.proportionUndissolvedAir = fluidPortC.proportionUndissolvedAir;
        fluidPortB.proportionUndissolvedAir = fluidPortC.proportionUndissolvedAir;
        fluidPortA.polytropicExponent = fluidPortC.polytropicExponent;
        fluidPortB.polytropicExponent = fluidPortC.polytropicExponent;
    end if;
    if connectA then 
        variableFlowSourceA.massFlow = idealResistor1.fluidPortA.mFlow;
        variableFlowSourceB.massFlow = 0;
    else 
        variableFlowSourceA.massFlow = 0;
        variableFlowSourceB.massFlow = idealResistor1.fluidPortA.mFlow;
    end if;
    when fluidPortB.p + SwitchingThreshold < fluidPortA.p then 
        connectA = true;
    elsewhen fluidPortA.p < fluidPortB.p - SwitchingThreshold then 
        connectA = false;
    end when;
    connect(fluidPortC,volumeC.fluidPort) annotation (Line(
        points = {
            {0, -100}, 
            {0, -74}},
        color = {0, 93, 152}));
    connect(volumeA.fluidPort,fluidPortA) annotation (Line(
        points = {
            {-70, 0}, 
            {-100, 0}},
        color = {0, 93, 152}));
    connect(volumeB.fluidPort,fluidPortB) annotation (Line(
        points = {
            {70, 0}, 
            {100, 0}},
        color = {0, 93, 152}));
    connect(idealResistor1.fluidPortA,volumeC.fluidPort) annotation (Line(
        points = {
            {0, -54}, 
            {0, -74}},
        color = {0, 93, 152}));
    connect(idealResistor1.fluidPortB,variablePressureSource1.fluidPort) annotation (Line(
        points = {
            {0, -34}, 
            {0, -20}},
        color = {0, 93, 152}));
    connect(variableFlowSourceA.fluidPort,volumeA.fluidPort) annotation (Line(
        points = {
            {-40, 0}, 
            {-70, 0}},
        color = {0, 93, 152}));
    connect(variableFlowSourceB.fluidPort,volumeB.fluidPort) annotation (Line(
        points = {
            {40, 0}, 
            {70, 0}},
        color = {0, 93, 152}));
    volumeA.p = pA;
    volumeB.p = pB;
    volumeC.p = pC;
    variablePressureSource1.setPressure = max(fluidPortA.p, fluidPortB.p);

    annotation (
        Icon(
            coordinateSystem(
                preserveAspectRatio = false,
                extent = {
                    {-100, -100}, 
                    {100, 60}},
                initialScale = 0.1),
            graphics = {
                Rectangle(
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-80, 40}, 
                        {80, -40}}), 
                Line(
                    origin = {-60, 0},
                    points = {
                        {20, 20}, 
                        {0, 0}, 
                        {20, -20}}), 
                Line(
                    origin = {60, 0},
                    points = {
                        {-20, 20}, 
                        {0, 0}, 
                        {-20, -20}}), 
                Ellipse(
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {2, 2}, 
                        {-2, -2}},
                    endAngle = 360), 
                Line(points = {
                    {0, -100}, 
                    {0, 0}}), 
                Line(points = {
                    {100, 0}, 
                    {-100, 0}}), 
                Ellipse(
                    origin = {-46, 0},
                    fillColor = {255, 255, 255},
                    fillPattern = FillPattern.Solid,
                    extent = {
                        {-10, 10}, 
                        {10, -10}},
                    endAngle = 360)}),
        Documentation(info = "<html>\n            <p>\n                The component ShuttleValve is the model of a changeover valve with <var>Dead volume</var> at each port. It connects port C (the middle port)\n                with the port that has the highest pressure. The flow characteristic is represented by an orifice.\n            </p>\n            <p>\n                <center><img src=\"modelica://HydraulicsByFluidon/Resources/Images/Components/Valves/CheckValves/ShuttleValve.png\"></center>\n            </p>\n            <p>\n                SwitchingThreshold defines deadband to avoid chattering. The shuttle valve switches from A to B when\n            </p>\n            <p>\n                pressure A > (pressure B + SwitchingThreshold)\n            </p>\n            <p>\n                and switches from B to A when\n            </p>\n            <p>\n                pressure A < (pressure B - SwitchingThreshold)\n            </p>\n            <p>\n                A typical application of this valve is in a load sensing system to determine the highest load pressure.\n            </p>\n            <p>\n                <b>Note</b>: Due to small volumes between the ShuttleValve and connected components and switching action, a very high numerical \n                stiffness may occur, resulting in small step sizes.\n            </p>\n            </html>"));
end ShuttleValve;