Model describing isentropic efficiency based on polynomial approach. This model contains a calculation procedure for isentropic efficiency
  models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The calculation procedures based on a polynomial approach are
  presented below.

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency;
model PolynomialIsentropicEfficiency
  "Model describing isentropic efficiency based on polynomial approach"
  extends PartialIsentropicEfficiency;

  // Definition of parameters describing polynomial approaches in general
  //
  parameter Types.IsentropicPolynomialModels polyMod=Types.IsentropicPolynomialModels.Karlsson2007
    "Chose predefined polynomial model for flow coefficient"
  parameter Real a[:]
    "Multiplication factors for each summand"
  parameter Real b[:]
    "Exponents for each summand"
  parameter Integer nT = size(a,1)
    "Number of terms used for the calculation procedure"

  // Definition of parameters describing specific approaches
  //
  parameter Real c[:] = {1}
    "Coefficients used for correction factors if needed"
  parameter Modelica.Units.SI.Frequency rotSpeRef=9.334
    "Reference rotational speed"

  // Definition of coefficients
  //
  Real p[nT]
    "Array that contains all coefficients used for the calculation procedure";
  Real corFac[2]
    "Array of correction factors used if efficiency model proposed in literature
    differs from efficiency model defined in PartialCompressor model";

equation
  // Calculation of coefficients
  //
  if (polyMod == Types.IsentropicPolynomialModels.DarrAndCrawford1992) then
    /*Polynomial approach presented by Dar and Crawford (1992):
      etaIse = a1 + a2*rotSpe +a3/dInl

      Caution with units - In the following, none S.I units are presented:
      Density:           in lb/ft^3
      Rotational Speed:  in rpm
      Volume flow:       in ft^3/min
    */
    p[1] = 1
      "Dummy value for usage of simple coefficcient";
    p[2] = rotSpe*60
      "Rotational speed";
    p[3] = 1/(Medium.density(staInl)*0.3048^3/0.453592)
      "Effect of clearance";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.IsentropicPolynomialModels.Karlsson2007) then
    /*Polynomial approach presented by Karlsson (2007):
      etaIse = a1 + a2*piPre + a3*piPre^2 + a4*rotSpe + a5*rotSpe^2

      Caution with units - In the following, none S.I units are presented:
      Pressure:            in bar
    */
    p[1] = 1
      "Usage of dummy value for simple coefficient";
    p[2] = piPre
      "Pressure ratio";
    p[3] = piPre^2
      "Quadratic pressure ratio";
    p[4] = rotSpe
      "Rotational speed";
    p[5] = rotSpe^2
      "Quadratic rotational speed";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.IsentropicPolynomialModels.Engelpracht2017) then
    /*Polynomial approach presented by Engelpracht (2017):
      etaIse = a1 + a2*rotSpe + a3*rotSpe^3 + piPre*y^2
    */
    p[1] = 1
      "Dummy value for usage of simple coefficient";
    p[2] = rotSpe
      "Rotational speed";
    p[3] = rotSpe^3
      "Cubic rotational speed";
    p[4] = piPre^2
      "Quadratic pressure ratio";

    corFac = {1,1}
      "No correction factors are needed";

  else
    assert(false, "Invalid choice of polynomial approach");
  end if;

  // Calculationg of flow coefficient
  //
  etaIse = min(1, corFac[1] *
    sum(a[i]*p[i]^b[i] for i in 1:nT)^corFac[2])
    "Calculation procedure of general polynomial";
end PolynomialIsentropicEfficiency;


Model describing flow isentropic efficiency on power approach. This model contains a calculation procedure for isentropic efficiency
  models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The calculation procedures based on a power approach are presented
  below.

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency;
model PowerIsentropicEfficiency
  "Model describing flow isentropic efficiency on power approach"
  extends PartialIsentropicEfficiency;

  // Definition of parameters
  //
  parameter Types.IsentropicPowerModels powMod=Types.IsentropicPowerModels.MendozaMirandaEtAl2016
    "Chose predefined power model for flow coefficient"
  parameter Real a
    "Multiplication factor for generic power approach"
  parameter Real b[:]
    "Exponents for each multiplier"
  parameter Integer nT = size(b,1)
    "Number of terms used for the calculation procedure"

  // Definition of further parameters required for special approaches
  //
  parameter Modelica.Units.SI.MolarMass MRef=0.1 "Reference molar wheight"
  parameter Modelica.Units.SI.Frequency rotSpeRef=9.334
    "Reference rotational speed"

  // Definition of coefficients
  //
  Real p[nT]
    "Array that contains all coefficients used for the calculation procedure";
  Real corFac[2]
    "Array of correction factors used if efficiency model proposed in literature
    differs from efficiency model defined in PartialCompressor model";

equation
  // Calculation of coefficients
  //
  if (powMod == Types.IsentropicPowerModels.MendozaMirandaEtAl2016) then
    /*Power approach presented by Mendoza et al. (2016):
      etaIse = piPre^b1 * (rotSpeRef/rotSpe)^b2 * (rotSpe^3*VDis/dhISe^1.5)^b3
               * (1/((TInl+TOutISe)/2-TOut))^b4
    */
    p[1] = piPre
      "Pressure ratio";
    p[2] = rotSpeRef/rotSpe
      "Rotational Speed";
    p[3] = rotSpe^3*VDis/(Medium.specificEnthalpy(Medium.setState_psX(s=
      Medium.specificEntropy(staInl),p=Medium.pressure(staOut))))^1.5
      "Isentropic specific enthalpy difference";
    p[4] = MRef/Medium.fluidConstants[1].molarMass
      "Molar Mass";

    corFac = {1,1}
      "No correction factors are needed";

  else
    assert(false, "Invalid choice of power approach");
  end if;

  // Calculationg of flow coefficient
  //
  etaIse = min(1, corFac[1] * a *
    product(p[i]^b[i] for i in 1:nT)^corFac[2])
    "Calculation procedure of generic power approach";
end PowerIsentropicEfficiency;


Reciporating Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power. This model contains a calculation procedure for the isentropic
  efficiency presented by Mendoza-Miranda et al. (2016).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Reciprocating
  "Reciporating Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power"
  extends PowerIsentropicEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.IsentropicPowerModels.MendozaMirandaEtAl2016,
    final a=1,
    final b={0.0753,0.2183,0.0015,0.0972});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Reciprocating;


Rotary Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power. This model contains a calculation procedure for the isentropic
  efficiency presented by Mendoza-Miranda et al. (2016).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary
  "Rotary Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power"
  extends PowerIsentropicEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.IsentropicPowerModels.MendozaMirandaEtAl2016,
    final a=0.85,
    final b={0.0753,0.2183,0.0015,0.0972});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary;


Scroll Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similutude - Power. This model contains a calculation procedure for the isentropic
  efficiency presented by Mendoza-Miranda et al. (2016).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Scroll
  "Scroll Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similutude - Power"
  extends PowerIsentropicEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.IsentropicPowerModels.MendozaMirandaEtAl2016,
    final a=1,
    final b={0.0753,0.2183,0.0015,0.0972});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Scroll;


General model that describes a constant overall isentropic efficiency. This model contains a simple calculation procedure for isentropic
  efficiency models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The model provides a constant overall isentropic efficiency and is
  the most basic engine efficiency model.

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model ConstantEfficiency
  "General model that describes a constant overall isentropic efficiency"
  extends PartialIsentropicEfficiency;

  // Definition of parameters
  //
  parameter Modelica.Units.SI.Efficiency etaIseCon=0.9
    "Constant overall isentropic efficiency";

equation
  // Calculate overall isentropic efficiency
  //
  etaIse = etaIseCon "Allocation of constant overall isentropic efficiency";
end ConstantEfficiency;


Generic overall isentropic efficiency based on literature review for
  various compressors. This model contains a calculation procedure for the isentropic
  efficiency presented by Engelpracht (2017). However, this approach is
  just fitted to various experimental data obtained by a literature
  review and, therefore, to use with caution.<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Generic_VarRef_VarDisVol_RotaryScroll
  "Generic overall isentropic efficiency based on literature review for
  various compressors"
  extends PolynomialIsentropicEfficiency(
    final polyMod=Types.IsentropicPolynomialModels.Engelpracht2017,
    final a={0.5816, 0.002604,-1.515e-7,-0.00473},
    final b={1,1,1,1});
end Generic_VarRef_VarDisVol_RotaryScroll;


within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency;
package SpecifiedEfficiencies "Package that engine efficiencies that are specifiied"
  extends Modelica.Icons.VariantsPackage;
end SpecifiedEfficiencies;


Reciporating Compressor - R134a - 169 cm³ - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Darr and Crawford (1992).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Poly_R134a_169_Reciprocating
  "Reciporating Compressor - R134a - 169 cm³ - Polynomial"
  extends PolynomialIsentropicEfficiency(
    final polyMod=Types.IsentropicPolynomialModels.DarrAndCrawford1992,
    final a={0.8405,-4.8711*1e-5,-0.1105},
    final b={1,1,1});
end Poly_R134a_169_Reciprocating;


Scroll Compressor - R407C - Unknown displacement volume - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Karlsson (2007).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies;
model Poly_R407C_Unknown_Scroll
  "Scroll Compressor - R407C - Unknown displacement volume - Polynomial"
  extends PolynomialIsentropicEfficiency(
    final polyMod=Types.IsentropicPolynomialModels.Karlsson2007,
    final a={0.926,-0.0823,0.00352,0.00294,-0.000022},
    final b={1,1,1,1,1});
end Poly_R407C_Unknown_Scroll;


within AixLib.Fluid.Movers.Compressors.Utilities;
package VolumetricEfficiency "Package that contains models describing different volumetric efficiencies"
  extends Modelica.Icons.Package;
end VolumetricEfficiency;


Based model used by all models describing volumetric efficiencies. This is a base model for overall volumetric efficiency models that
  are required for various compressor models. It defines some basic
  inputs and outputs that are commonly used by efficiency models and
  these inputs and outputs are summarised below:<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency;
partial model PartialVolumetricEfficiency
  "Based model used by all models describing volumetric efficiencies"
  extends BaseClasses.PartialEfficiency;

  // Definition of outputs
  //
  output Modelica.Units.SI.Efficiency lamH(
    min=0,
    max=1,
    nominal=0.9) "Overall volumetric efficiency";
end PartialVolumetricEfficiency;


Model describing volumetric efficiency based on polynomial approach. This model contains a calculation procedure for volumetric efficiency
  models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The calculation procedures based on a polynomial approach are
  presented below.

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency;
model PolynomialVolumetricEfficiency
  "Model describing volumetric efficiency based on polynomial approach"
  extends PartialVolumetricEfficiency;

  // Definition of parameters describing polynomial approaches in general
  //
  parameter Types.VolumetricPolynomialModels polyMod=Types.VolumetricPolynomialModels.Karlsson2007
    "Chose predefined polynomial model for flow coefficient"
  parameter Real a[:]
    "Multiplication factors for each summand"
  parameter Real b[:]
    "Exponents for each summand"
  parameter Integer nT = size(a,1)
    "Number of terms used for the calculation procedure"

  // Definition of parameters describing specific approaches
  //
  parameter Real c[:] = {1}
    "Coefficients used for correction factors if needed"
  parameter Modelica.Units.SI.Frequency rotSpeRef=9.334
    "Reference rotational speed"

  // Definition of coefficients
  //
  Real p[nT]
    "Array that contains all coefficients used for the calculation procedure";
  Real corFac[2]
    "Array of correction factors used if efficiency model proposed in literature
    differs from efficiency model defined in PartialCompressor model";

equation
  // Calculation of coefficients
  //
  if (polyMod == Types.VolumetricPolynomialModels.DarrAndCrawford1992) then
    /*Polynomial approach presented by Dar and Crawford (1992):
      lamH = a1 + a2*rotSpe - a3*epsRef*(dInlIse/dInl-1) -
      a4*rotSpe*(dInlIse/dInl-1)

      Caution with units - In the following, none S.I units are presented:
      Density:           in lb/ft^3
      Rotational Speed:  in rpm
      Volume flow:       in ft^3/min
    */
    p[1] = 1
      "Dummy value for usage of simple coefficcient";
    p[2] = rotSpe*60
      "Rotational speed";
    p[3] = -(epsRef)*(Medium.density(Medium.setState_psX(s=
      Medium.specificEntropy(staInl),p=Medium.pressure(staOut)))/
      Medium.density(staInl)-1)
      "Effect of clearance";
    p[4] = -rotSpe*60*(Medium.density(Medium.setState_psX(s=
      Medium.specificEntropy(staInl),p=Medium.pressure(staOut)))/
      Medium.density(staInl)-1)
      "Effect of clearance";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.Karlsson2007) then
    /*Polynomial approach presented by Karlsson (2007):
      lamH = a1*TInl*piPre + a2*piPre + a3 + a4*TInl + a5*rotSpe + a6*rotSpe^2

      Caution with units - In the following, none S.I units are presented:
      Temperature:         in °C
    */
    p[1] = (Medium.temperature(staInl)-273.15)*piPre
      "Inlet temperature times pressure ratio";
    p[2] = piPre
      "Pressure ratio";
    p[3] = 1
      "Dummy value for usage of simple coefficcient";
    p[4] = (Medium.temperature(staInl)-273.15)
      "Inlet temperature";
    p[5] = rotSpe
      "Rotational speed";
    p[6] = rotSpe^2
      "Quadratic rotational speed";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.KinarbEtAl2010) then
    /*Polynomial approach presented by Kinab et al. (2010):
      etaEng = a1 + a2*piPre
    */
    p[1] = 1
      "Dummy value for usage of simple coefficient";
    p[2] = piPre
      "Pressure ratio";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.ZhouEtAl2010) then
    /*Polynomial approach presented by Zhou et al. (2010):
    etaEng = 1 + a1 - a2*piPre^(1/kapMean)
    */
    p[1] = 1
      "Dummy value for usage of simple coefficient";
    p[2] = 1
      "Dummy value for usage of simple coefficient";
    p[3] = -piPre^(2/(Medium.isentropicExponent(staInl)+
      Medium.isentropicExponent(staOut)))
      "Pressure ratio";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.Li2013) then
    /*Polynomial approach presented by Li (2013):
      lamH = lamHRef * (a1 + a2*(rotSpe/rotSpeRef) + a3*(rotSpe/rotSpeRef)^2)
        with  lamHRef = c1 + c2*((pOut/(pInl*(1-c3))^(1/kapMea))

      Caution with units - In the following, none S.I units are presented:
      Pressure:            in kPa
      Temperature:         in °C
      Specific enthalpy:   in kJ/kg
      Rotational speed:    in rpm
    */
    p[1] = 1
      "Dummy value for usage of simple coefficient";
    p[2] = (rotSpe/rotSpeRef)
      "Rotational speed";
    p[3] = (rotSpe/rotSpeRef)^2
      "Quadratic rotational speed";

    corFac[1] = c[1] + c[2]*((Medium.pressure(staOut)/(Medium.pressure(staInl)*
      (1-c[3]*1e-3)))^(2/(Medium.isentropicExponent(staInl)+
      Medium.isentropicExponent(staOut))))
      "Reference volumetric efficiency";
    corFac[2] = 1
      "No correction factor is needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.HongtaoLaughmannEtAl2017) then
    /*Polynomial approach presented by Hongtao et al. (2013):
      lamH = a1 + a2*omega + a3*omega^2 +
             a4*piPre + a5*omega*piPre + a6*omega^2*piPre +
             a7*piPre^2 + a8*omega*piPre^2 + a9*omega^2*piPre^2 +
             a10*pOut + a11*omega*pOut + a12*omega^2*pOut -
             a13*pInl - a14*omega*pInl - a15*omega^2*pInl +
             a16*pInl*pOut + a17*omega*pInl*pOut + a18*omega^2*pInl*pOut +
             a19*omega^3*pInl*pOut + a20*omega^4*pInl*pOut -
             a21*pInl^2 - a22*omega*pInl^2 - a23*omega^2*pInl^2 -
             a24*omega^3*pInl^2 - a25*omega^4*pInl^2

      with omega = rotSpe/rotSpeRef
    */
    p[1] = 1
      "First coefficient";
    p[2] = (rotSpe/rotSpeRef)
      "Second coefficient";
    p[3] = (rotSpe/rotSpeRef)^2
      "Third coefficient";
    p[4] = piPre
      "Fourth coefficient";
    p[5] = piPre*(rotSpe/rotSpeRef)
      "Fifth coefficient";
    p[6] = piPre*(rotSpe/rotSpeRef)^2
      "Sixth coefficient";
    p[7] = piPre^2
      "Seventh coefficient";
    p[8] = piPre^2*(rotSpe/rotSpeRef)
      "Eighth coefficient";
    p[9] = piPre^2*(rotSpe/rotSpeRef)^2
      "Ninth coefficient";
    p[10] = Medium.pressure(staOut)
      "Tenth coefficient";
    p[11] = Medium.pressure(staOut)*(rotSpe/rotSpeRef)
      "Eleventh coefficient";
    p[12] = Medium.pressure(staOut)*(rotSpe/rotSpeRef)^2
      "Twelfth coefficient";
    p[13] = -Medium.pressure(staInl)
      "Thirteenth coefficient";
    p[14] = -Medium.pressure(staInl)*(rotSpe/rotSpeRef)
      "Fourteenth coefficient";
    p[15] = -Medium.pressure(staInl)*(rotSpe/rotSpeRef)^2
      "Fifteenth coefficient";
    p[16] = Medium.pressure(staInl)*Medium.pressure(staOut)
      "Sixteenth coefficient";
    p[17] = Medium.pressure(staInl)*Medium.pressure(staOut)*(rotSpe/rotSpeRef)
      "Seventeenth coefficient";
    p[18] = Medium.pressure(staInl)*Medium.pressure(staOut)*(rotSpe/rotSpeRef)^2
      "Eighteenth coefficient";
    p[19] = Medium.pressure(staInl)*Medium.pressure(staOut)*(rotSpe/rotSpeRef)^3
      "Nineteenth coefficient";
    p[20] = Medium.pressure(staInl)*Medium.pressure(staOut)*(rotSpe/rotSpeRef)^4
      "Twentieth coefficient";
    p[21] = -Medium.pressure(staInl)^2
      "Twenty-first coefficient";
    p[22] = -Medium.pressure(staInl)^2*(rotSpe/rotSpeRef)^2
      "Twenty-second coefficient";
    p[23] = -Medium.pressure(staInl)^2*(rotSpe/rotSpeRef)^3
      "Twenty-third coefficient";
    p[24] = -Medium.pressure(staInl)^2*(rotSpe/rotSpeRef)^4
      "Twenty-fourth coefficient";
    p[25] = -Medium.pressure(staInl)^2*(rotSpe/rotSpeRef)^5
      "Twenty-fifth coefficient";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.Koerner2017) then
    /*Polynomial approach presented by Körner et al.(2017):
      lamH = a1*piPre^b1
    */
    p[1] = piPre
      "Pressure ratio";

    corFac = {1,1}
      "No correction factors are needed";

  elseif (polyMod == Types.VolumetricPolynomialModels.Engelpracht2017) then
    /*Polynomial approach presented by Engelpracht (2017):
      lamH = a1 + a2*((piPre-c1)/c2) + a3*((TInl-c3)/c4)*((piPre-c1)/c2) +
             a4*((TInl-c3)/c4) + a5*((rotSpe-c5)/c6) + a6*((rotSpe-c5)/c6)^2
    */
    p[1] = 1
      "Dummy value for usage of simple coefficient";
    p[2] = ((piPre-c[1])/c[2])
      "Pressure ratio";
    p[3] = ((Medium.temperature(staInl)-c[3])/c[4])*((piPre-c[1])/c[2])
      "Pressure ratio times inlet temperature";
    p[4] = ((Medium.temperature(staInl)-c[3])/c[4])
      "Inlet temperature";
    p[5] = ((rotSpe-c[5])/c[6])
      "Rotational speed";
    p[6] = ((rotSpe-c[5])/c[6])^2
      "Quadratic rotational speed";

    corFac = {1,1}
      "No correction factors are needed";

  else
    assert(false, "Invalid choice of polynomial approach");
  end if;

  // Calculationg of flow coefficient
  //
  lamH = min(1, corFac[1] *
    sum(a[i]*p[i]^b[i] for i in 1:nT)^corFac[2])
    "Calculation procedure of general polynomial";
end PolynomialVolumetricEfficiency;


Model describing flow volumetric efficiency on power approach. This model contains a calculation procedure for volumetric efficiency
  models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The calculation procedures based on a power approach are presented
  below.

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency;
model PowerVolumetricEfficiency
  "Model describing flow volumetric efficiency on power approach"
  extends PartialVolumetricEfficiency;

  // Definition of parameters
  //
  parameter Types.VolumetricPowerModels powMod=Types.VolumetricPowerModels.MendozaMirandaEtAl2016
    "Chose predefined power model for flow coefficient"
  parameter Real a
    "Multiplication factor for generic power approach"
  parameter Real b[:]
    "Exponents for each multiplier"
  parameter Integer nT = size(b,1)
    "Number of terms used for the calculation procedure"

  // Definition of further parameters required for special approaches
  //
  parameter Modelica.Units.SI.MolarMass MRef=0.1 "Reference molar wheight"
  parameter Modelica.Units.SI.Frequency rotSpeRef=9.334
    "Reference rotational speed"

  // Definition of coefficients
  //
  Real p[nT]
    "Array that contains all coefficients used for the calculation procedure";
  Real corFac[2]
    "Array of correction factors used if efficiency model proposed in literature
    differs from efficiency model defined in PartialCompressor model";

equation
  // Calculation of coefficients
  //
  if (powMod == Types.VolumetricPowerModels.MendozaMirandaEtAl2016) then
    /*Power approach presented by Mendoza et al. (2005):
      lamH = piPre^b1 * (piPre^1.5*rotSpe^3*VDis)^b2 * (MRef/M)^b3
    */
    p[1] = piPre
      "Pressure ratio";
    p[2] = piPre^1.5*rotSpe^3*VDis
      "Rotational Speed";
    p[3] = MRef/Medium.fluidConstants[1].molarMass
      "Molar Mass";

    corFac = {1,1}
      "No correction factors are needed";

  else
    assert(false, "Invalid choice of power approach");
  end if;

  // Calculationg of flow coefficient
  //
  lamH = min(1, corFac[1] * a *
    product(abs(p[i])^b[i] for i in 1:nT)^corFac[2])
    "Calculation procedure of generic power approach";
end PowerVolumetricEfficiency;


within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Reciprocating
  "Reciporating Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power"
  extends PowerVolumetricEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.VolumetricPowerModels.MendozaMirandaEtAl2016,
    final a=1,
    final b={-0.2678,-0.0106,0.7195});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Reciprocating;


within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary
  "Rotary Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power"
  extends PowerVolumetricEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.VolumetricPowerModels.MendozaMirandaEtAl2016,
    final a=1.2,
    final b={-0.2678,-0.0106,0.7195});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary;


Scroll Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power. This model contains a calculation procedure for the isentropic
  efficiency presented by Mendoza-Miranda et al. (2016).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Buck_R134aR450aR1234yfR1234zee_VarDisVol_Scroll
  "Scroll Compressor - R134a, R450a, R1234yf, R1234ze(e) - Similitude - Power"
  extends PowerVolumetricEfficiency(
    final MRef=0.102032,
    final rotSpeRef=9.334,
    final powMod=Types.VolumetricPowerModels.MendozaMirandaEtAl2016,
    final a=1.35,
    final b={-0.2678,-0.0106,0.7195});
end Buck_R134aR450aR1234yfR1234zee_VarDisVol_Scroll;


General model that describes a constant overall volumetric efficiency. This model contains a simple calculation procedure for volumetric
  efficiency models (for more information, please check out
  AixLib.Fluid.Movers.Compressors.BaseClasses.PartialCompression).
  The model provides a constant overall volumetric efficiency and is
  the most basic engine efficiency model.

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model ConstantEfficiency
  "General model that describes a constant overall volumetric efficiency"
  extends PartialVolumetricEfficiency;

  // Definition of parameters
  //
  parameter Modelica.Units.SI.Efficiency lamHCon=0.9
    "Constant overall volumetric efficiency";

equation
  // Calculate overall volumetric efficiency
  //
  lamH = lamHCon "Allocation of constant overall volumetric efficiency";
end ConstantEfficiency;


Generic overall volumetric efficiency based on literature review for various compressors. This model contains a calculation procedure for the isentropic
  efficiency presented by Engelpracht (2017). However, this approach is
  just fitted to various experimental data obtained by a literature
  review and, therefore, to use with caution.<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Generic_VarRef_VarDisVol_RotaryScroll
  "Generic overall volumetric efficiency based on literature review for various compressors"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Engelpracht2017,
    final a={0.801790164842882, -0.0521044823322188, 3.216164809959999e-04,
             -0.00493895583430215, 0.049805496348618, -0.021900176265525},
    final b={1,1,1,1,1,1},
    final c={4.54069854496490, 1.63495326341915, 263.864279610770,
             8.43796869242862, 64.4107142857143, 20.8137823859887});
end Generic_VarRef_VarDisVol_RotaryScroll;


within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency;
package SpecifiedEfficiencies "Package that engine efficiencies that are specifiied"
  extends Modelica.Icons.VariantsPackage;
end SpecifiedEfficiencies;


within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R134a_169_Reciprocating
  "Reciporating Compressor - R134a - 169 cm³ - Polynomial"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.DarrAndCrawford1992,
    final a={0.8889,-1.0025*1e-4,0.8889,-1.0025*1e-4},
    final b={1,1,1,1});
end Poly_R134a_169_Reciprocating;


Reciporating Compressor - R134a - 170 cm³ - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Li (2013).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R134a_170_Reciprocating
  "Reciporating Compressor - R134a - 170 cm³ - Polynomial"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Li2013,
    final rotSpeRef=2000/60,
    final a={1.223,-0.206,-0.017},
    final b={1,1,1},
    final c={0.779,-0.036,0});
end Poly_R134a_170_Reciprocating;


Scroll Compressor - R134a - 54.24 cm³ - Polynomial . This model contains a calculation procedure for the isentropic
  efficiency presented by Li (2013).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R134a_54_Scroll
  "Scroll Compressor - R134a - 54.24 cm³ - Polynomial "
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Li2013,
    final rotSpeRef=50,
    final a={0.693,0.543,-0.236},
    final b={1,1,1},
    final c={1.047,-0.051,0});
end Poly_R134a_54_Scroll;


Rotary Compressor - R22 - 20.7 cm³ - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Li (2013).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R22_20_Rotary "Rotary Compressor - R22 - 20.7 cm³ - Polynomial"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Li2013,
    final rotSpeRef=60,
    final a={0.709,0.416,-0.125},
    final b={1,1,1},
    final c={1.083,-0.077,0});
end Poly_R22_20_Rotary;


Scroll Compressor - R407C - Unknown displacement volume - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Karlsson (2017).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R407C_Unknown_Scroll
  "Scroll Compressor - R407C - Unknown displacement volume - Polynomial"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Karlsson2007,
    final a={0.0012,-0.088,1.1262,-0.0045,0.0039,-0.000025},
    final b={1,1,1,1,1,1});
end Poly_R407C_Unknown_Scroll;


Rotary Compressor - R410a - 130 cm³ - Polynomial. This model contains a calculation procedure for the isentropic
  efficiency presented by Körner (2017).<br/>

within AixLib.Fluid.Movers.Compressors.Utilities.VolumetricEfficiency.SpecifiedEfficiencies;
model Poly_R410a_130_Rotary "Rotary Compressor - R410a - 130 cm³ - Polynomial"
  extends PolynomialVolumetricEfficiency(
    final polyMod=Types.VolumetricPolynomialModels.Koerner2017,
    final a={1.108},
    final b={-0.165});
end Poly_R410a_130_Rotary;


within AixLib.Fluid.Movers.Compressors.Validation;
model EfficiencyModels
  "Validation model to check efficiencies calculated with respect to different
  prescribed conditions"
  extends Modelica.Icons.Example;

  // Define medium and parameters
  //
  package Medium =
   Modelica.Media.R134a.R134a_ph
   "Actual medium of the compressor";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.1
    "Nominal mass flow rate";

  // Definition of variables
  //
  Modelica.Units.SI.AbsolutePressure pInl=Medium.pressure(Medium.setBubbleState(
      Medium.setSat_T(preInp.y[2] - 1))) "Actual pressure at inlet conditions";
  Modelica.Units.SI.AbsolutePressure pOut=Medium.pressure(Medium.setDewState(
      Medium.setSat_T(preInp.y[3] - 1)))
    "Actual set point of the compressor's outlet pressure";

  // Definition of models
  //
  Modelica.Blocks.Sources.CombiTimeTable preInp(
    tableOnFile=true,
    tableName="Internals",
    fileName=Modelica.Utilities.Files.loadResource(
      "modelica://AixLib/Resources/Fluid/Movers/Compressors/efficiencyValidation.txt"),
    columns=2:5,
    extrapolation=Modelica.Blocks.Types.Extrapolation.NoExtrapolation,
    smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative)
    "Prescribed inputs to check efficiencies calculated by efficiency models"
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature fixTem
    "Fixed ambient temperature"
  Modelica.Blocks.Sources.RealExpression pInlDum(y=pInl)
    "Dummy to succeed pedantic check"
  Modelica.Blocks.Sources.RealExpression pOutDum(y=pOut)
    "Dummy to succeed pedantic check"

  Sources.Boundary_pT source(
    redeclare package Medium = Medium,
    nPorts=1,
    use_T_in=true,
    use_p_in=true) "Source of constant pressure and temperature"
  replaceable SimpleCompressors.RotaryCompressors.RotaryCompressor rotCom(
    redeclare package Medium = Medium,
    show_staEff=true,
    show_qua=true,
    useInpFil=false,
    redeclare model EngineEfficiency =
        Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare model VolumetricEfficiency =
        Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare model IsentropicEfficiency =
        AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll)
    "Model of a rotary compressor"
  Sources.Boundary_pT sink(
    redeclare package Medium = Medium,
    use_T_in=true,
    use_p_in=true,
    nPorts=1) "Sink with constant pressure and temperature"

equation
  // Connection of components
  //
  connect(source.ports[1],rotCom. port_a)
  connect(fixTem.port,rotCom. heatPort)
  connect(rotCom.port_b, sink.ports[1])
  connect(preInp.y[1], fixTem.T)
  connect(preInp.y[2], source.T_in)
  connect(preInp.y[3], sink.T_in)
  connect(preInp.y[4],rotCom. manVarCom)
  connect(pOutDum.y, sink.p_in)
  connect(pInlDum.y, source.p_in)
end EfficiencyModels;


within AixLib.Fluid.Movers.Compressors.Validation;
model ModularInactiveCompressors
  "Validation model to test modular compressors if not all compressors are active"
  extends Modelica.Icons.Example;

  // Define medium and parameters
  //
  package Medium =
   Modelica.Media.R134a.R134a_ph
   "Medium of the compressor";

  parameter Integer nCom = 3
    "Number of compressors";
  parameter Modelica.Units.SI.AbsolutePressure pInl=Medium.pressure(
      Medium.setBubbleState(Medium.setSat_T(TInl + 1)))
    "Current pressure at inlet conditions";
  parameter Modelica.Units.SI.Temperature TInl=283.15
    "Current temperature at inlet conditions";
  parameter Modelica.Units.SI.AbsolutePressure pOut=Medium.pressure(
      Medium.setDewState(Medium.setSat_T(TOut - 5)))
    "Current set point of the compressor's outlet pressure";
  parameter Modelica.Units.SI.Temperature TOut=333.15
    "Current temperature at outlet conditions";

  // Definition of models
  //
  Sources.Boundary_pT   source(
    redeclare package Medium = Medium,
    p=pInl,
    T=TOut,
    nPorts=1) "Source with constant pressure and temperature"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixTem[nCom](
    each T=283.15)
    "Fixed ambient temperature"
  replaceable ModularCompressors.ModularCompressors modCom(
    nCom=nCom,
    redeclare package Medium = Medium,
    redeclare model EngineEfficiency =
        Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare model VolumetricEfficiency =
        Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary,
    redeclare model IsentropicEfficiency =
        AixLib.Fluid.Movers.Compressors.Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Buck_R134aR450aR1234yfR1234zee_VarDisVol_Rotary,
    useExt=true,
    show_parCom=false,
    show_parCon=false,
    redeclare model SimpleCompressor =
        SimpleCompressors.RotaryCompressors.RotaryCompressor,
    redeclare model ModularController =
        Controls.HeatPump.ModularHeatPumps.ModularCompressorController)
    "Model of modular compressors in parallel"
  Modelica.Blocks.Sources.Sine valOpe(
    offset=0.5,
    amplitude=0.3,
    f=1) "Prescribed valve's opening"
  Obsolete.Year2021.Fluid.Actuators.Valves.SimpleValve simVal(
    redeclare package Medium = Medium,
    m_flow_start=0.025,
    m_flow_small=1e-6,
    Kvs=1.4) "Model of a simple valve to simulate pressure losses"
  Sources.Boundary_pT   sink(
    redeclare package Medium = Medium,
    nPorts=1,
    p=pInl,
    T=TInl) "Sink with constant pressure and temperature"

  Controls.Interfaces.ModularHeatPumpControlBus dataBus(
    nCom=nCom) "Connector that contains all control signals"

  Modelica.Blocks.Sources.Sine rotSpe[nCom](
    each f=1,
    amplitude={50,20,0},
    offset={50,20,0})
    "Input signal to prediscribe compressors' rotational speeds"
  Modelica.Blocks.Routing.Replicator repMea(nout=nCom)
    "Replicating the current value of the controlled variables"
  Modelica.Blocks.Sources.Ramp ramMea(
    duration=1,
    height=60,
    offset=40)
    "Ramp to fake current value sof the controlled variables"

equation
  // Connection of main components
  //
  connect(source.ports[1], modCom.port_a)
  connect(fixTem.port, modCom.heatPort)
  connect(modCom.port_b, simVal.port_a)
  connect(simVal.port_b, sink.ports[1])

  // Connection of control signals
  //
  connect(valOpe.y, simVal.opening)

  connect(dataBus, modCom.dataBus)
  connect(ramMea.y, repMea.u)
  connect(rotSpe.y, dataBus.comBus.extManVarCom)
  connect(rotSpe.y, dataBus.comBus.intSetPoiCom)
  connect(repMea.y, dataBus.comBus.meaConVarCom)
end ModularInactiveCompressors;


within AixLib.Fluid.Movers.Compressors;
package Validation "Package that contains validations models to test compressors' functionalities"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within AixLib.Fluid.Movers.Compressors.Validation;
model SimpleHeatTransfer
  "Validation model to check the implementation of the simple heat transfer"
  extends Modelica.Icons.Example;

  // Define medium and parameters
  //
  package Medium =
   Modelica.Media.R134a.R134a_ph
   "Medium of the compressor";

  parameter Modelica.Units.SI.AbsolutePressure pInl=Medium.pressure(
      Medium.setBubbleState(Medium.setSat_T(TInl + 2)))
    "Current pressure at inlet conditions";
  parameter Modelica.Units.SI.Temperature TInl=283.15
    "Current temperature at inlet conditions";
  parameter Modelica.Units.SI.AbsolutePressure pOut=Medium.pressure(
      Medium.setDewState(Medium.setSat_T(TOut - 5)))
    "Current set point of the compressor's outlet pressure";
  parameter Modelica.Units.SI.Temperature TOut=333.15
    "Current temperature at outlet conditions";

  // Definition of submodels and connectors
  //
  Sources.MassFlowSource_T source(
    redeclare package Medium = Medium,
    nPorts=1,
    m_flow=0.1,
    T=TInl) "Source of constant temperature and mass flow rate"
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixTem(T=263.15)
    "Fixed ambient temperature"
  Utilities.HeatTransfer.SimpleHeatTransfer simheaTra(
    redeclare package Medium = Medium)
    "Model of simple one-dimensional heat transfer"
  MixingVolumes.MixingVolume sink(
    redeclare package Medium = Medium,
    nPorts=1,
    V=10e-3,
    m_flow_nominal=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial,
    massDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial,
    p_start=pInl,
    T_start=TInl) "Sink that allows storage of mass and energy"

equation
  // Connection of main components
  //
  connect(fixTem.port, simheaTra.heatPort)
  connect(source.ports[1], simheaTra.port_a)
  connect(simheaTra.port_b, sink.ports[1])
end SimpleHeatTransfer;


Base model to test compressors using static boundaries


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries;
model BaseModelStaticHeatPump
  "Base model to test compressors using static heat pump boundaries"

  // Definition of medium
  //
  replaceable package Medium =
    Modelica.Media.R134a.R134a_ph
    constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
    "Medium of the compressor"

  // Definition of parameters describing compressors
  //
  parameter Integer nCom = 1
    "Numer of compressors in parallel"

  // Definition of parameters describing boundary conditions
  //
  parameter Modelica.Units.SI.TemperatureDifference dTPinEva=5
    "Pinch temperature at evaporator's outlet"
  parameter Modelica.Units.SI.TemperatureDifference dTSupHea=1
    "Superheating of working fluid"

  parameter Modelica.Units.SI.TemperatureDifference dTPinCon=2.5
    "Pinch temperature at evaporator's outlet"
  parameter Modelica.Units.SI.TemperatureDifference dTSubCool=8
    "Supercooling of working fluid"

  parameter Modelica.Units.SI.Density dSec=1000
    "Constant density of secondary fluid"
  parameter Modelica.Units.SI.SpecificHeatCapacity cpSec=4.1813e3
    "Constant specific heat capacity of secondary fluid"
  parameter Modelica.Units.SI.VolumeFlowRate V_flowSec=(0.776 + 0.781 + 0.44)/3
      /3600 "Constant volume flow of secondary fluid"

  // Definition of variables describing boundary conditions
  //
  Modelica.Blocks.Sources.CombiTimeTable inpDat(
    extrapolation=Modelica.Blocks.Types.Extrapolation.NoExtrapolation,
    columns=2:7,
    timeScale=1,
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    table=[0,64,285.15,5180,308.15,900,5.755555556; 1,64,283.15,4920,308.15,910,
        5.406593407; 2,63,280.15,4370,308.15,930,4.698924731; 3,64,285.15,4980,318.15,
        1140,4.368421053; 4,64,283.15,4730,318.15,1140,4.149122807; 5,55,285.15,
        4180,328.15,1240,3.370967742; 6,64,283.15,4650,328.15,1380,3.369565217;
        7,63,280.15,4160,318.15,1610,2.583850932; 8,55,275.15,2800,308.15,790,3.544303797;
        9,106,258.15,3760,308.15,1570,2.394904459; 10,115,266.15,4850,308.15,1940,
        2.5; 11,55,275.15,2640,318.15,960,2.75; 12,111,258.15,4150,318.15,2120,1.95754717;
        13,107,270.15,4780,318.15,2210,2.162895928; 14,113,266.15,4560,318.15,2290,
        1.991266376; 15,100,266.15,3880,328.15,2240,1.732142857; 16,63,275.15,3280,
        328.15,1330,2.466165414; 17,63,280.15,4080,328.15,1400,2.914285714])
    "Static boundaries of compressor model"

  Modelica.Blocks.Sources.RealExpression inpRotSpe(y=inpDat.y[1])
    "Expressions describing rotational speed"
  Modelica.Blocks.Sources.RealExpression inpAmbTemp(y=inpDat.y[2])
    "Expressions describing ambient temperature"
  Modelica.Blocks.Sources.RealExpression inpHeaCap(y=inpDat.y[3])
    "Expressions describing heat capacity"
  Modelica.Blocks.Sources.RealExpression inpTRetFlo(y=inpDat.y[4] - 10)
    "Expressions describing return flow temperature at heat capacity"

  // Definition of subcomponents
  //
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature ambTemp
    "Source that prescribes boundary ambient temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector thrCol(m=nCom)
    "Model to split the ambient temperature"
  StaticEvaporator eva(
    redeclare final package Medium = Medium,
    final dTPin=dTPinEva,
    final dTSupHea=dTSupHea)
    "Model that describes a simple static evaporator"

  Modelica.Blocks.Routing.Replicator repMea(nout=nCom)
    "Replicating the current value of the manipulated variables"
  ModularCompressors.ModularCompressorsSensors modCom(
    nCom=nCom,
    redeclare package Medium = Medium,
    redeclare model SimpleCompressor =
        SimpleCompressors.RotaryCompressors.RotaryCompressor,
    show_staEff=true,
    show_qua=true,
    m_flow_start=0.05,
    VDis=fill(13.2e-6,nCom),
    useInpFil=fill(false,nCom),
    h_out_start=400e3,
    redeclare replaceable model EngineEfficiency =
        Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare replaceable model VolumetricEfficiency =
        Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare replaceable model IsentropicEfficiency =
        Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll)
    "Model that describes modular compressors in parallel"

  StaticCondenser con(
    redeclare package Medium = Medium,
    dSec=dSec,
    cpSec=cpSec,
    V_flowSec=V_flowSec,
    dTSubCool=dTSubCool,
    dTPin=dTPinCon)
    "Model that describes a simple static condenser"

  Controls.Interfaces.ModularHeatPumpControlBus dataBus(
    nCom=nCom) "Connector that contains all control signals"

  // Definition of further variables
  //
  Modelica.Blocks.Interaction.Show.RealValue COP(
    use_numberPort=false, number=con.Q_flow/modCom.modCom[1].comPro.PEle/nCom)
    "Real value describing current COP"
  Modelica.Blocks.Interaction.Show.RealValue dCOPRel(use_numberPort=false,
      number=(COP.number - inpDat.y[6])/inpDat.y[6]*100)
    "Realative difference of current COP"
  Modelica.Blocks.Interaction.Show.RealValue PEle(
    use_numberPort=false, number=modCom.modCom[1].comPro.PEle)
    "Real value describing current power consumption"
  Modelica.Blocks.Interaction.Show.RealValue dPEleRel(use_numberPort=false,
      number=(PEle.number - inpDat.y[5])/inpDat.y[5]*100)
    "Real difference of current power consumption"
  Real inpTime = time
    "Simulation time";

protected
  model StaticEvaporator
    "Static evaporator assuming constant pinch point at evaporator's outlet"

    // Definition of medium
    //
    replaceable package Medium = Modelica.Media.R134a.R134a_ph
      constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
      "Medium of the compressor"

    // Definition of parameters describing evaporator
    //
    parameter Modelica.Units.SI.TemperatureDifference dTPin=5
      "Pinch temperature at evaporator's outlet"
    parameter Modelica.Units.SI.TemperatureDifference dTSupHea=1
      "Superheating of working fluid"

    // Definition of parameters describing assumptions
    //
    parameter Boolean allowFlowReversal = false
      "= false to simplify equations, assuming, but not enforcing, no flow reversal"

    // Definition of connecotrs
    //
    Modelica.Fluid.Interfaces.FluidPort_b port_b(
      redeclare final package Medium = Medium,
      m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
       h_outflow(start = Medium.h_default))
      "Fluid connector b (positive design flow direction is from port_a to port_b)"
    Modelica.Blocks.Interfaces.RealInput inpTAmb
      "Input of ambient temperature"

    // Definition of submodels
    //
    Modelica.Blocks.Sources.RealExpression outPEva(y=pSat)
      "Expressions describing saturation pressure at evaporator's outlet"
    Modelica.Blocks.Sources.RealExpression outTEva(y=TOut)
      "Expressions describing temperature at evaporator's outlet"

    Sources.Boundary_pT source(
      redeclare package Medium = Medium,
      use_p_in=true,
      use_T_in=true,
      nPorts=1)
      "Source with constant pressure and temperature"

    // Definition of variables describing evaporator
    //
    Medium.SaturationProperties satEva
      "Saturation properties of the evaporator's working fluid"
    Medium.ThermodynamicState staOut
      "Thermodynamic state of the working fluid  at evaporator's outlet"

    Modelica.Units.SI.AbsolutePressure pSat
      "Absolute pressure at evaporator's outlet";
    Modelica.Units.SI.Temperature TSat "Saturation temperature";
    Modelica.Units.SI.Temperature TOut "Temperature at evaporator's outlet";

    Modelica.Units.SI.Temperature TAmb "Temperature of ambient";

  equation
    // Connection of ports
    //
    connect(outPEva.y, source.p_in)
    connect(outTEva.y, source.T_in)
    connect(source.ports[1], port_b)

    TAmb = inpTAmb
      "Temperature of ambient";

    // Calculation of state properties of working fluid
    //
    satEva = Medium.setSat_T(T=TSat)
      "Saturation properties";
    staOut = Medium.setState_pT(p=pSat,T=TOut)
      "Thermodynamic state of the working fluid at evaporator's outlet";

    pSat = Medium.saturationPressure(satEva.Tsat)
      "Absolute pressure at evaporator's outlet";
    TSat = TOut - dTSupHea
      "Saturation temperature";
    TOut = TAmb - dTPin
      "Temperature at evaporator's outlet";
  end StaticEvaporator;

  model StaticCondenser
    "Static condenser assuming constant pinch point at condenser's outlet"

    // Definition of medium
    //
    replaceable package Medium = Modelica.Media.R134a.R134a_ph
      constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
      "Medium of the compressor"

    // Definition of parameters describing condenser
    //
    parameter Modelica.Units.SI.TemperatureDifference dTPin=2.5
      "Supercooling of working fluid"
    parameter Modelica.Units.SI.TemperatureDifference dTSubCool=8
      "Supercooling of working fluid"

    parameter Modelica.Units.SI.Density dSec=1000
      "Constant density of secondary fluid"
    parameter Modelica.Units.SI.SpecificHeatCapacity cpSec=4.1813e3
      "Constant specific heat capacity of secondary fluid"
    parameter Modelica.Units.SI.VolumeFlowRate V_flowSec=(0.776 + 0.781 + 0.44)
        /3/3600 "Constant volume flow of secondary fluid"

    // Definition of parameters describing assumptions
    //
    parameter Boolean allowFlowReversal = false
      "= false to simplify equations, assuming, but not enforcing, no flow reversal"

    // Definition of connecotrs
    //
    Modelica.Fluid.Interfaces.FluidPort_a port_a(
      redeclare final package Medium = Medium,
      m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
       h_outflow(start = Medium.h_default))
      "Fluid connector b (positive design flow direction is from port_a to port_b)"

    Modelica.Blocks.Interfaces.RealInput inpTRetFlo
      "Temperature return flow at heat capacity"

    // Definition of variables describing condenser
    //
    Modelica.Units.SI.AbsolutePressure pSat
      "Absolute pressure at condenser's outlet";
    Modelica.Units.SI.Temperature TSat "Saturation temperature";

    Modelica.Units.SI.Temperature TInl "Temperature at condenser's inlet";
    Modelica.Units.SI.Temperature TOut "Temperature at condenser's outlet";
    Modelica.Units.SI.SpecificEnthalpy hInl
      "Specific enthalpy at condenser's inlet";
    Modelica.Units.SI.SpecificEnthalpy hOut
      "Specific enthalpy at condenser's outlet";

    Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
    Modelica.Units.SI.HeatFlowRate Q_flow "Heat capacity";

    Modelica.Units.SI.MassFlowRate m_flowSec
      "Mass flow rate of secondary fluid";
    Modelica.Units.SI.Temperature TFlo "Temperature flow at heat capacity";
    Modelica.Units.SI.Temperature TRetFlo
      "Temperature return flow at heat capacity";

  equation
    // Connection of ports
    //
    port_a.h_outflow = inStream(port_a.h_outflow)
      "No flow reversal";
    port_a.p = pSat
      "Pressure at inlet is equal to saturation pressure";

    m_flow = port_a.m_flow
      "Mass flow rate at condenser's inlet";
    hInl = inStream(port_a.h_outflow)
      "Specific enthalpy at condenser's inlet";

    TRetFlo =inpTRetFlo
      "Temperature return flow at heat capacity";

    // Secondary side
    //
    m_flowSec = dSec*V_flowSec
      "Mass flow rate of secondary fluid";
    TFlo = TRetFlo + Q_flow/(m_flowSec*cpSec)
      "Temperature return flow at heat capacity";

    // Calculation of state properties of working fluid
    //
    TOut = TRetFlo + dTPin
      "Temperature at condenser's outlet";
    TSat = TOut + dTSubCool
      "Saturation temperature";
    pSat = Medium.saturationPressure(T=TSat)
      "Absolute pressure at condenser's outlet";

    hOut = Medium.specificEnthalpy_pT(p=pSat,T=TOut)
      "Specific enthalpy at condenser's outlet";
    hOut = hInl - Q_flow/m_flow
      "Specific enthalpy at condenser's outlet";

    TInl = Medium.temperature_ph(p=pSat,h=hInl)
      "Temperature at condenser's inlet";
  end StaticCondenser;

equation
  // Connection of main components
  //
  connect(eva.port_b, modCom.port_a)
  connect(modCom.port_b, con.port_a)
  connect(ambTemp.port, thrCol.port_b)
  connect(thrCol.port_a, modCom.heatPort)

  // Connection of signals
  //
  connect(modCom.dataBus, dataBus)
  connect(inpAmbTemp.y, ambTemp.T)
  connect(inpRotSpe.y, repMea.u)
  connect(repMea.y, dataBus.comBus.extManVarCom)
  connect(inpAmbTemp.y, eva.inpTAmb)
  connect(inpTRetFlo.y, con.inpTRetFlo)
end BaseModelStaticHeatPump;


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries;
model BaseModelStaticHeatPumpController
  "Base model to test compressors using static heat pump boundaries"

  // Definition of medium
  //
  replaceable package Medium =
    Modelica.Media.R134a.R134a_ph
    constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
    "Medium of the compressor"

  // Definition of parameters describing compressors
  //
  parameter Integer nCom = 1
    "Numer of compressors in parallel"

  // Definition of parameters describing boundary conditions
  //
  parameter Modelica.Units.SI.TemperatureDifference dTPinEva=5
    "Pinch temperature at evaporator's outlet"
  parameter Modelica.Units.SI.TemperatureDifference dTSupHea=1
    "Superheating of working fluid"

  parameter Modelica.Units.SI.TemperatureDifference dTPinCon=2.5
    "Pinch temperature at evaporator's outlet"
  parameter Modelica.Units.SI.TemperatureDifference dTSubCool=8
    "Supercooling of working fluid"

  parameter Modelica.Units.SI.Density dSec=1000
    "Constant density of secondary fluid"
  parameter Modelica.Units.SI.SpecificHeatCapacity cpSec=4.1813e3
    "Constant specific heat capacity of secondary fluid"
  parameter Modelica.Units.SI.VolumeFlowRate V_flowSec=(0.776 + 0.781 + 0.44)/3
      /3600 "Constant volume flow of secondary fluid"

  // Definition of variables describing boundary conditions
  //
  Modelica.Blocks.Sources.CombiTimeTable inpDat(
    extrapolation=Modelica.Blocks.Types.Extrapolation.NoExtrapolation,
    columns=2:7,
    timeScale=1,
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    table=[0,64,285.15,5180,308.15,900,5.755555556; 1,64,283.15,4920,308.15,910,
        5.406593407; 2,63,280.15,4370,308.15,930,4.698924731; 3,64,285.15,4980,318.15,
        1140,4.368421053; 4,64,283.15,4730,318.15,1140,4.149122807; 5,55,285.15,
        4180,328.15,1240,3.370967742; 6,64,283.15,4650,328.15,1380,3.369565217;
        7,63,280.15,4160,318.15,1610,2.583850932; 8,55,275.15,2800,308.15,790,3.544303797;
        9,106,258.15,3760,308.15,1570,2.394904459; 10,115,266.15,4850,308.15,1940,
        2.5; 11,55,275.15,2640,318.15,960,2.75; 12,111,258.15,4150,318.15,2120,1.95754717;
        13,107,270.15,4780,318.15,2210,2.162895928; 14,113,266.15,4560,318.15,2290,
        1.991266376; 15,100,266.15,3880,328.15,2240,1.732142857; 16,63,275.15,3280,
        328.15,1330,2.466165414; 17,63,280.15,4080,328.15,1400,2.914285714])
    "Static boundaries of compressor model"

  Modelica.Blocks.Sources.RealExpression inpRotSpe(y=inpDat.y[1])
    "Expressions describing rotational speed"
  Modelica.Blocks.Sources.RealExpression inpAmbTemp(y=inpDat.y[2])
    "Expressions describing ambient temperature"
  Modelica.Blocks.Sources.RealExpression inpHeaCap(y=inpDat.y[3])
    "Expressions describing heat capacity"
  Modelica.Blocks.Sources.RealExpression inpTRetFlo(y=inpDat.y[4] - 10)
    "Expressions describing return flow temperature at heat capacity"

  // Definition of subcomponents
  //
  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature ambTemp
    "Source that prescribes boundary ambient temperature"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector thrCol(m=nCom)
    "Model to split the ambient temperature"
  StaticEvaporator eva(
    redeclare final package Medium = Medium,
    final dTPin=dTPinEva,
    final dTSupHea=dTSupHea)
    "Model that describes a simple static evaporator"

  Modelica.Blocks.Continuous.LimPID PID(
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    yMax=120,
    yMin=30) "Controller of the compressor's rotational speeds"
  Modelica.Blocks.Routing.Replicator repMea(nout=nCom)
    "Replicating the current value of the manipulated variables"
  ModularCompressors.ModularCompressorsSensors modCom(
    nCom=nCom,
    redeclare package Medium = Medium,
    redeclare model SimpleCompressor =
        SimpleCompressors.RotaryCompressors.RotaryCompressor,
    show_staEff=true,
    show_qua=true,
    m_flow_start=0.05,
    VDis=fill(13.2e-6,nCom),
    useInpFil=fill(false,nCom),
    h_out_start=400e3,
    redeclare replaceable model EngineEfficiency =
        Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare replaceable model VolumetricEfficiency =
        Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
    redeclare replaceable model IsentropicEfficiency =
        Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll)
    "Model that describes modular compressors in parallel"

  StaticCondenser con(
    redeclare package Medium = Medium,
    dSec=dSec,
    cpSec=cpSec,
    V_flowSec=V_flowSec,
    dTSubCool=dTSubCool,
    dTPin=dTPinCon)
    "Model that describes a simple static condenser"

  Controls.Interfaces.ModularHeatPumpControlBus dataBus(
    nCom=nCom) "Connector that contains all control signals"

  // Definition of further variables
  //
  Modelica.Blocks.Interaction.Show.RealValue COP(
    use_numberPort=false, number=con.Q_flow/modCom.modCom[1].comPro.PEle/nCom)
    "Real value describing current COP"
  Modelica.Blocks.Interaction.Show.RealValue dCOPRel(use_numberPort=false,
      number=(COP.number - inpDat.y[6])/inpDat.y[6]*100)
    "Realative difference of current COP"
  Modelica.Blocks.Interaction.Show.RealValue PEle(
    use_numberPort=false, number=modCom.modCom[1].comPro.PEle)
    "Real value describing current power consumption"
  Modelica.Blocks.Interaction.Show.RealValue dPEleRel(use_numberPort=false,
      number=(PEle.number - inpDat.y[5])/inpDat.y[5]*100)
    "Real difference of current power consumption"
  Real inpTime = time
    "Simulation time";

protected
  model StaticEvaporator
    "Static evaporator assuming constant pinch point at evaporator's outlet"

    // Definition of medium
    //
    replaceable package Medium = Modelica.Media.R134a.R134a_ph
      constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
      "Medium of the compressor"

    // Definition of parameters describing evaporator
    //
    parameter Modelica.Units.SI.TemperatureDifference dTPin=5
      "Pinch temperature at evaporator's outlet"
    parameter Modelica.Units.SI.TemperatureDifference dTSupHea=1
      "Superheating of working fluid"

    // Definition of parameters describing assumptions
    //
    parameter Boolean allowFlowReversal = false
      "= false to simplify equations, assuming, but not enforcing, no flow reversal"

    // Definition of connecotrs
    //
    Modelica.Fluid.Interfaces.FluidPort_b port_b(
      redeclare final package Medium = Medium,
      m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
       h_outflow(start = Medium.h_default))
      "Fluid connector b (positive design flow direction is from port_a to port_b)"
    Modelica.Blocks.Interfaces.RealInput inpTAmb
      "Input of ambient temperature"

    // Definition of submodels
    //
    Modelica.Blocks.Sources.RealExpression outPEva(y=pSat)
      "Expressions describing saturation pressure at evaporator's outlet"
    Modelica.Blocks.Sources.RealExpression outTEva(y=TOut)
      "Expressions describing temperature at evaporator's outlet"

    Sources.Boundary_pT source(
      redeclare package Medium = Medium,
      use_p_in=true,
      use_T_in=true,
      nPorts=1)
      "Source with constant pressure and temperature"

    // Definition of variables describing evaporator
    //
    Medium.SaturationProperties satEva
      "Saturation properties of the evaporator's working fluid"
    Medium.ThermodynamicState staOut
      "Thermodynamic state of the working fluid  at evaporator's outlet"

    Modelica.Units.SI.AbsolutePressure pSat
      "Absolute pressure at evaporator's outlet";
    Modelica.Units.SI.Temperature TSat "Saturation temperature";
    Modelica.Units.SI.Temperature TOut "Temperature at evaporator's outlet";

    Modelica.Units.SI.Temperature TAmb "Temperature of ambient";

  equation
    // Connection of ports
    //
    connect(outPEva.y, source.p_in)
    connect(outTEva.y, source.T_in)
    connect(source.ports[1], port_b)

    TAmb = inpTAmb
      "Temperature of ambient";

    // Calculation of state properties of working fluid
    //
    satEva = Medium.setSat_T(T=TSat)
      "Saturation properties";
    staOut = Medium.setState_pT(p=pSat,T=TOut)
      "Thermodynamic state of the working fluid at evaporator's outlet";

    pSat = Medium.saturationPressure(satEva.Tsat)
      "Absolute pressure at evaporator's outlet";
    TSat = TOut - dTSupHea
      "Saturation temperature";
    TOut = TAmb - dTPin
      "Temperature at evaporator's outlet";
  end StaticEvaporator;

  model StaticCondenser
    "Static condenser assuming constant pinch point at condenser's outlet"

    // Definition of medium
    //
    replaceable package Medium = Modelica.Media.R134a.R134a_ph
      constrainedby Modelica.Media.Interfaces.PartialTwoPhaseMedium
      "Medium of the compressor"

    // Definition of parameters describing condenser
    //
    parameter Modelica.Units.SI.TemperatureDifference dTPin=2.5
      "Supercooling of working fluid"
    parameter Modelica.Units.SI.TemperatureDifference dTSubCool=8
      "Supercooling of working fluid"

    parameter Modelica.Units.SI.Density dSec=1000
      "Constant density of secondary fluid"
    parameter Modelica.Units.SI.SpecificHeatCapacity cpSec=4.1813e3
      "Constant specific heat capacity of secondary fluid"
    parameter Modelica.Units.SI.VolumeFlowRate V_flowSec=(0.776 + 0.781 + 0.44)
        /3/3600 "Constant volume flow of secondary fluid"

    // Definition of parameters describing assumptions
    //
    parameter Boolean allowFlowReversal = false
      "= false to simplify equations, assuming, but not enforcing, no flow reversal"

    // Definition of connecotrs
    //
    Modelica.Fluid.Interfaces.FluidPort_a port_a(
      redeclare final package Medium = Medium,
      m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
       h_outflow(start = Medium.h_default))
      "Fluid connector b (positive design flow direction is from port_a to port_b)"

    Modelica.Blocks.Interfaces.RealInput inpTRetFlo
      "Temperature return flow at heat capacity"
    Modelica.Blocks.Interfaces.RealOutput outQFlo
      "Heat capacity"

    // Definition of variables describing condenser
    //
    Modelica.Units.SI.AbsolutePressure pSat
      "Absolute pressure at condenser's outlet";
    Modelica.Units.SI.Temperature TSat "Saturation temperature";

    Modelica.Units.SI.Temperature TInl "Temperature at condenser's inlet";
    Modelica.Units.SI.Temperature TOut "Temperature at condenser's outlet";
    Modelica.Units.SI.SpecificEnthalpy hInl
      "Specific enthalpy at condenser's inlet";
    Modelica.Units.SI.SpecificEnthalpy hOut
      "Specific enthalpy at condenser's outlet";

    Modelica.Units.SI.MassFlowRate m_flow "Mass flow rate";
    Modelica.Units.SI.HeatFlowRate Q_flow "Heat capacity";

    Modelica.Units.SI.MassFlowRate m_flowSec
      "Mass flow rate of secondary fluid";
    Modelica.Units.SI.Temperature TFlo "Temperature flow at heat capacity";
    Modelica.Units.SI.Temperature TRetFlo
      "Temperature return flow at heat capacity";

  equation
    // Connection of ports
    //
    port_a.h_outflow = inStream(port_a.h_outflow)
      "No flow reversal";
    port_a.p = pSat
      "Pressure at inlet is equal to saturation pressure";

    m_flow = port_a.m_flow
      "Mass flow rate at condenser's inlet";
    hInl = inStream(port_a.h_outflow)
      "Specific enthalpy at condenser's inlet";

    TRetFlo = inpTRetFlo
      "Temperature return flow at heat capacity";
    outQFlo = Q_flow
      "Heat capacity";

    // Secondary side
    //
    m_flowSec = dSec*V_flowSec
      "Mass flow rate of secondary fluid";
    TFlo = TRetFlo + Q_flow/(m_flowSec*cpSec)
      "Temperature return flow at heat capacity";

    // Calculation of state properties of working fluid
    //
    TOut = TRetFlo + dTPin
      "Temperature at condenser's outlet";
    TSat = TOut + dTSubCool
      "Saturation temperature";
    pSat = Medium.saturationPressure(T=TSat)
      "Absolute pressure at condenser's outlet";

    hOut = Medium.specificEnthalpy_pT(p=pSat,T=TOut)
      "Specific enthalpy at condenser's outlet";
    hOut = hInl - Q_flow/m_flow
      "Specific enthalpy at condenser's outlet";

    TInl = Medium.temperature_ph(p=pSat,h=hInl)
      "Temperature at condenser's inlet";
  end StaticCondenser;

equation
  // Connection of main components
  //
  connect(eva.port_b, modCom.port_a)
  connect(modCom.port_b, con.port_a)
  connect(ambTemp.port, thrCol.port_b)
  connect(thrCol.port_a, modCom.heatPort)

  // Connection of signals
  //
  connect(modCom.dataBus, dataBus)
  connect(inpAmbTemp.y, ambTemp.T)
  connect(repMea.y, dataBus.comBus.extManVarCom)
  connect(inpAmbTemp.y, eva.inpTAmb)
  connect(inpTRetFlo.y, con.inpTRetFlo)
  connect(PID.y, repMea.u)
  connect(con.outQFlo, PID.u_m)
  connect(PID.u_s, inpHeaCap.y)
end BaseModelStaticHeatPumpController;


within AixLib.Fluid.Movers.Compressors.Validation;
package StaticHeatPumpBoundaries "This package contains models to validate the comprosser models using
  static heat pump boundary conditions"
  extends Modelica.Icons.ExamplesPackage;
end StaticHeatPumpBoundaries;


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries;
package SpecifiedModels "Package that contains validation models of different static boundary models"
  extends Modelica.Icons.ExamplesPackage;
end SpecifiedModels;


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries.SpecifiedModels;
model RefrigerantR134aScrollCompressor
  "Static boundaries of a scroll-compressor using R134a"
  extends BaseModelStaticBoundaries(
    replaceable package Medium =
      Modelica.Media.R134a.R134a_ph,
    modCom(
      redeclare model EngineEfficiency =
        EngineEfficiency,
      redeclare model VolumetricEfficiency =
        VolumetricEfficiency,
      redeclare model IsentropicEfficiency =
        IsentropicEfficiency));
  extends Modelica.Icons.Example;

protected
  model EngineEfficiency
    "Fitted engine efficiency"
    extends Utilities.EngineEfficiency.PartialEngineEfficiency(
      useIseWor = false);
  equation
     etaEng = 0.8704+0.001295*rotSpe+0.05194*piPre-8.006e-06*rotSpe^2-
       0.0001272*rotSpe*piPre-0.01146*piPre^2+1.059e-06*rotSpe^2*piPre-
       2.265e-06*rotSpe*piPre^2+0.0008853*piPre^3;
  end EngineEfficiency;

  model VolumetricEfficiency
    "Fitted volumetric efficiency"
    extends Utilities.VolumetricEfficiency.PartialVolumetricEfficiency;
  equation
    lamH = 0.5828+0.0303*rotSpe-0.1727*piPre-0.000588*rotSpe^2+
      0.003072*rotSpe*piPre+0.01238*piPre^2+3.434e-06*rotSpe^3-
      1.496e-05*rotSpe^2*piPre -0.0001785*rotSpe*piPre^2;
  end VolumetricEfficiency;

  model IsentropicEfficiency
    "Fitted isentropic efficiency"
    extends Utilities.IsentropicEfficiency.PartialIsentropicEfficiency;
  equation
    etaIse = (-3.565 + 0.2464*rotSpe + 1.227*piPre - 0.007986*rotSpe^2+
    0.03947*rotSpe*piPre-0.9075*piPre^2+0.0001086*rotSpe^3-
     0.0006588*rotSpe^2*piPre +0.0001482*rotSpe*piPre^2 +
      0.1721*piPre^3-5.291e-07*rotSpe^4+3.353e-06*rotSpe^3*piPre+
      1.037e-05*rotSpe^2*piPre^2 - 0.0001854*rotSpe*piPre^3-0.01102*piPre^4)*1.05;
  end IsentropicEfficiency;
end RefrigerantR134aScrollCompressor;


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries.SpecifiedModels;
model RefrigerantR410aScrollCompressor
  "Static heat pump boundaries of a scroll-compressor using R410a"
  extends BaseModelStaticHeatPump(
    nCom = 1,
    replaceable package Medium =
      Modelica.Media.R134a.R134a_ph,
    modCom(
      redeclare model EngineEfficiency =
          Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
      redeclare model VolumetricEfficiency =
          Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
      redeclare model IsentropicEfficiency =
          Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll),
    inpDat(smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments));
  extends Modelica.Icons.Example;
end RefrigerantR410aScrollCompressor;


within AixLib.Fluid.Movers.Compressors.Validation.StaticHeatPumpBoundaries.SpecifiedModels;
model RefrigerantR410aScrollCompressorController
  "Static boundaries of a scroll-compressor using R410a"
  extends BaseModelStaticHeatPumpController(
    nCom = 1,
    replaceable package Medium =
      Modelica.Media.R134a.R134a_ph,
    modCom(
      redeclare model EngineEfficiency =
          Utilities.EngineEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
      redeclare model VolumetricEfficiency =
          Utilities.VolumetricEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
      redeclare model IsentropicEfficiency =
          Utilities.IsentropicEfficiency.SpecifiedEfficiencies.Generic_VarRef_VarDisVol_RotaryScroll,
      useInpFil={true},
      risTim={0.1}),
    inpDat(smoothness=Modelica.Blocks.Types.Smoothness.ContinuousDerivative),
    PID(
      yMax=120,
      yMin=10,
      k=1));
  extends Modelica.Icons.Example;
end RefrigerantR410aScrollCompressorController;


Generic data record for movers

within AixLib.Fluid.Movers.Data;
record Generic "Generic data record for movers"
  extends Modelica.Icons.Record;

  // Pressure requires default values to avoid in Dymola the message
  // Failed to expand the variable pressure.V_flow.
  parameter AixLib.Fluid.Movers.BaseClasses.Characteristics.flowParameters pressure(
    V_flow = {0, 0},
    dp =     {0, 0}) "Volume flow rate vs. total pressure rise"
  final parameter Modelica.Units.SI.VolumeFlowRate V_flow_max=
    if havePressureCurve
      then (pressure.V_flow[end]
                -(pressure.V_flow[end] - pressure.V_flow[end - 1])
                /(pressure.dp[end] - pressure.dp[end - 1])
                * pressure.dp[end])
    else 0
      "Volume flow rate on the curve when pressure rise is zero";
  final parameter Modelica.Units.SI.PressureDifference dpMax(
    displayUnit="Pa")=
    if havePressureCurve
      then (pressure.dp[1]
                -(pressure.dp[1] - pressure.dp[2])
                /(pressure.V_flow[1] - pressure.V_flow[2])
                * pressure.V_flow[1])
    else 0
      "Pressure rise on the curve when flow rate is zero";

  // Efficiency computation choices
  parameter AixLib.Fluid.Movers.BaseClasses.Types.HydraulicEfficiencyMethod etaHydMet=
    if havePressureCurve
    then AixLib.Fluid.Movers.BaseClasses.Types.HydraulicEfficiencyMethod.EulerNumber
    else AixLib.Fluid.Movers.BaseClasses.Types.HydraulicEfficiencyMethod.NotProvided
    "Efficiency computation method for the hydraulic efficiency etaHyd"
  parameter AixLib.Fluid.Movers.BaseClasses.Types.MotorEfficiencyMethod etaMotMet=
    if powerOrEfficiencyIsHydraulic and havePressureCurve
    then AixLib.Fluid.Movers.BaseClasses.Types.MotorEfficiencyMethod.GenericCurve
    else AixLib.Fluid.Movers.BaseClasses.Types.MotorEfficiencyMethod.NotProvided
    "Efficiency computation method for the motor efficiency etaMot"

  parameter Boolean powerOrEfficiencyIsHydraulic=true
    "=true if hydraulic power or efficiency is provided, instead of total"

  // Arrays for efficiency values
  parameter
    AixLib.Fluid.Movers.BaseClasses.Characteristics.efficiencyParameters
    efficiency(
      V_flow={0},
      eta={0.7}) "Total or hydraulic efficiency vs. volumetric flow rate"
  parameter
    AixLib.Fluid.Movers.BaseClasses.Characteristics.efficiencyParameters
    motorEfficiency(
      V_flow={0},
      eta={0.7})
    "Motor efficiency vs. volumetric flow rate"
  parameter
    AixLib.Fluid.Movers.BaseClasses.Characteristics.efficiencyParameters_yMot
    motorEfficiency_yMot(y={0}, eta={0.7})
    "Motor efficiency vs. part load ratio yMot, where yMot = WHyd/WMot_nominal"

  // Power curve
  //   It requires default values to suppress Dymola message
  //   "Failed to expand the variable Power.V_flow"
  parameter AixLib.Fluid.Movers.BaseClasses.Characteristics.powerParameters power(
    V_flow={0},
    P={0})
    "Power (either consumed or hydraulic) vs. volumetric flow rate"

  // Peak condition
  parameter AixLib.Fluid.Movers.BaseClasses.Euler.peak peak(
    V_flow=peak_internal.V_flow,
    dp=peak_internal.dp,
    eta=peak_internal.eta)
    "Volume flow rate, pressure rise, and efficiency (either total or hydraulic) at peak condition"
  final parameter AixLib.Fluid.Movers.BaseClasses.Euler.peak peak_internal=
    AixLib.Fluid.Movers.BaseClasses.Euler.getPeak(pressure=pressure,power=power)
    "Internal peak variable";
  // The getPeak() function automatically handles the estimation of peak point
  //   when insufficient information is provided from the pressure curve.

  // Motor
  parameter Boolean motorCooledByFluid=true
    "If true, then motor heat is added to fluid stream"
  parameter Modelica.Units.SI.Power WMot_nominal=
    if max(power.P)>Modelica.Constants.eps
    then
      if powerOrEfficiencyIsHydraulic
        then max(power.P)*1.2
      else max(power.P)
    else
      if havePressureCurve
        then V_flow_max/2 * dpMax/2 /0.7*1.2
      else 0
    "Rated motor power"
  parameter Modelica.Units.SI.Efficiency etaMot_max(max=1)= 0.7
    "Maximum motor efficiency"
  final parameter
    AixLib.Fluid.Movers.BaseClasses.Characteristics.efficiencyParameters_yMot
      motorEfficiency_yMot_generic=
        AixLib.Fluid.Movers.BaseClasses.Characteristics.motorEfficiencyCurve(
          P_nominal=WMot_nominal,
          eta_max=etaMot_max)
    "Motor efficiency  vs. part load ratio"
  final parameter Boolean haveWMot_nominal=WMot_nominal > Modelica.Constants.eps
    "= true, if the rated motor power is provided";

  // Speed
  parameter Real speed_nominal(
    final min=0,
    final unit="1") = 1 "Nominal rotational speed for flow characteristic"

  parameter Real constantSpeed(final min=0, final unit="1") = 1
    "Normalized speed set point, used if inputType = AixLib.Fluid.Types.InputType.Constant"

  parameter Real[:] speeds(each final min = 0, each final unit="1") = {1}
    "Vector of normalized speed set points, used if inputType = AixLib.Fluid.Types.InputType.Stages"

  // Set a parameter in order for
  // (a) FlowControlled_m_flow and FlowControlled_dp to be able to set a reasonable
  //     default pressure curve if it is not specified here, and
  // (b) SpeedControlled_y to be able to issue an assert
  //     if no pressure curve is specified.
  final parameter Boolean havePressureCurve=
    sum(pressure.V_flow) > Modelica.Constants.eps and
    sum(pressure.dp) > Modelica.Constants.eps
    "= true, if default record values are being used";
end Generic;


within AixLib.Fluid.Movers;
package Data "Package containing data for real pumps/fans"
extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Package of fan performance data

within AixLib.Fluid.Movers.Data;
package Fans "Package of fan performance data"
  extends Modelica.Icons.Package;
end Fans;


within AixLib.Fluid.Movers.Data.Fans;
package Greenheck "Package with performance data for fans of Greenheck"
  extends Modelica.Icons.Package;
end Greenheck;


Package containing data for pumps

within AixLib.Fluid.Movers.Data;
package Pumps "Package containing data for pumps"
  extends Modelica.Icons.Package;
end Pumps;


within AixLib.Fluid.Movers.Data.Pumps;
package Wilo "Package with performance data for Wilo pumps"
  extends Modelica.Icons.Package;
end Wilo;


within AixLib.Fluid.Movers.DpControlledMovers;
model DpControlled_dp "Pump or fan including pressure control (constant or variable)"
  extends AixLib.Fluid.Interfaces.LumpedVolumeDeclarations(
    final mSenFac=1);
  extends AixLib.Fluid.Interfaces.PartialTwoPortInterface(
    m_flow_nominal(final min=Modelica.Constants.small),
    port_a(
      h_outflow(start=h_outflow_start)),
    port_b(
      h_outflow(start=h_outflow_start),
      p(start=p_start),
      final m_flow(max = if allowFlowReversal then +Modelica.Constants.inf else 0)));

  replaceable parameter AixLib.Fluid.Movers.Data.Generic per(pressure=pressureCurve_default) "Record with performance data"

  parameter Modelica.Units.SI.PressureDifference dp_nominal(
    min=0,
    displayUnit="Pa") = if rho_default < 500 then 500 else 10000 "Nominal pressure raise, used to normalized the filter if use_inputFilter=true,
        to set default values of constantHead and heads, and
        and for default pressure curve if not specified in record per"
  parameter AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType ctrlType=AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType.dpTotal "Type of mover control"
  parameter AixLib.Fluid.Movers.BaseClasses.Characteristics.flowParameters pressureCurve_default(
      V_flow=m_flow_nominal/rho_default*{0,1,1.5,2},
      dp=dp_nominal*{1.3,1,0.75,0})
    "General mover curve: volume flow rate vs. total pressure head"
  parameter AixLib.Fluid.Movers.BaseClasses.Characteristics.flowParameters pressureCurve_dpConst(
      V_flow=m_flow_nominal/rho_default*{0,1,1.5,2},
      dp=dp_nominal*{1,1,0.75,0})
    "dpConst control: volume flow rate vs. total pressure head"
  parameter AixLib.Fluid.Movers.BaseClasses.Characteristics.flowParameters pressureCurve_dpVar(
      V_flow=m_flow_nominal/rho_default*{0,1,1.5,2},
      dp=dp_nominal*{0.5,1,0.75,0})
    "dpVar control: volume flow rate vs. total pressure head"

  parameter Boolean addPowerToMedium=true
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)";
  parameter Boolean nominalValuesDefineDefaultPressureCurve = false
    "Set to true to avoid warning if m_flow_nominal and dp_nominal are used to construct the default pressure curve";
  parameter Boolean prescribeSystemPressure=false
    "=true, to control mover such that pressure difference is obtained across two remote points in system"
  parameter Modelica.Units.SI.Time tauMov=1
    "Time constant in mover (pump or fan) of fluid volume for nominal flow, used if energy or mass balance is dynamic"

  // Classes used to implement the filtered speed
  parameter Boolean use_inputFilter=true
    "= true, if speed is filtered with a 2nd order CriticalDamping filter"
  parameter Modelica.Units.SI.Time riseTime=30
    "Rise time of the filter (time to reach 99.6 % of the speed)"
  parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real y_start(min=0, max=1, unit="1")=0
    "Initial value of speed"

  // Sensor parameters
  parameter Modelica.Units.SI.PressureDifference dp_start=0
    "Initial value of pressure raise"
  parameter Modelica.Units.SI.Time tauSen=0
    "Time constant at nominal flow rate (use tau=0 for steady-state sensor, but see user guide for potential problems)"
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (InitialState and InitialOutput are identical)"
  parameter Modelica.Media.Interfaces.Types.Density d_start=Medium.density(Medium.setState_pTX(
      senVolFlo.p_start,
      senVolFlo.T_start,
      senVolFlo.X_start)) "Initial or guess value of density"

  // Table parameters
  parameter Modelica.Blocks.Types.Smoothness smoothness=Modelica.Blocks.Types.Smoothness.LinearSegments
    "Smoothness of table interpolation"
  parameter Boolean verboseExtrapolation=false
    "= true, if warning messages are to be printed if table input is outside the definition range"

  Modelica.Blocks.Interfaces.RealInput dpMea(
    final quantity="PressureDifference",
    final displayUnit="Pa",
    final unit="Pa") if prescribeSystemPressure
    "Measurement of pressure difference between two points where the set point should be obtained"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heatPort
    "Heat dissipation to environment"

  AixLib.Fluid.Sensors.VolumeFlowRate senVolFlo(
    redeclare final package Medium = Medium,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_small=m_flow_small,
    final tau=tauSen,
    final initType=initType,
    final d_start=d_start,
    final T_start=T_start,
    final p_start=p_start,
    final X_start=X_start)
    "Sensor to measure volume flow rate"

  Modelica.Blocks.Tables.CombiTable1Dv pressureCurveSelected(
    final tableOnFile=false,
    final table=if (ctrlType == AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType.dpConst)
         then [cat(1, pressureCurve_dpConst.V_flow),cat(1,
        pressureCurve_dpConst.dp)] elseif (ctrlType == AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType.dpVar)
         then [cat(1, pressureCurve_dpVar.V_flow),cat(1, pressureCurve_dpVar.dp)]
         else [cat(1, per.pressure.V_flow),cat(1, per.pressure.dp)],
    final tableName="NoName",
    final fileName="NoName",
    final verboseRead=true,
    final columns=2:size(pressureCurveSelected.table, 2),
    final smoothness=smoothness,
    final extrapolation=Modelica.Blocks.Types.Extrapolation.HoldLastPoint,
    u(each final unit="m3/s"),
    y(each final unit="Pa"),
    final verboseExtrapolation=verboseExtrapolation)
    "Table with points of selected curve to calculate dp from V_flow"

  AixLib.Fluid.Movers.FlowControlled_dp mov(
    redeclare final package Medium = Medium,
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final allowFlowReversal=allowFlowReversal,
    final m_flow_nominal=m_flow_nominal,
    final m_flow_small=m_flow_small,
    final show_T=false,
    final per=per,
    final inputType=AixLib.Fluid.Types.InputType.Continuous,
    final addPowerToMedium=addPowerToMedium,
    final nominalValuesDefineDefaultPressureCurve=nominalValuesDefineDefaultPressureCurve,
    final tau=tauMov,
    final use_inputFilter=use_inputFilter,
    final riseTime=riseTime,
    final init=init,
    final dp_start=dp_start,
    final dp_nominal=dp_nominal,
    final constantHead=dp_nominal,
    final heads=dp_nominal*{(per.speeds[i]/per.speeds[end])^2 for i in 1:size(per.speeds, 1)},
    final prescribeSystemPressure=prescribeSystemPressure)
    "Mover: pump or fan"

  Modelica.Blocks.Interfaces.RealOutput P(final quantity="Power", final unit="W")
    "Electrical power consumed"
  Modelica.Blocks.Interfaces.RealOutput y_actual(final unit="1")
    "Actual normalised pump speed that is used for computations"
  Modelica.Blocks.Interfaces.RealOutput dp_actual(final unit="Pa")
    "Pressure difference between the mover inlet and outlet"

protected
  final parameter Modelica.Units.SI.Density rho_default=Medium.density_pTX(
      p=Medium.p_default,
      T=Medium.T_default,
      X=Medium.X_default) "Default medium density";
  final parameter Medium.ThermodynamicState sta_start=Medium.setState_pTX(
      T=T_start,
      p=p_start,
      X=X_start)
    "Medium state at start values";

  final parameter Modelica.Units.SI.SpecificEnthalpy h_outflow_start=
      Medium.specificEnthalpy(sta_start) "Start value for outflowing enthalpy";

  final parameter Modelica.Units.SI.VolumeFlowRate V_flow_min=min(min(
      pressureCurve_default.V_flow), min(min(pressureCurve_dpConst.V_flow), min(
      pressureCurve_dpVar.V_flow))) "Get minimum of three vectors";
  final parameter Modelica.Units.SI.VolumeFlowRate V_flow_max=max(max(
      pressureCurve_default.V_flow), max(max(pressureCurve_dpConst.V_flow), max(
      pressureCurve_dpVar.V_flow))) "Get maximum of three vectors";

  constant Integer n_sup_pts = 100
    "Supporting points";
  final parameter Modelica.Units.SI.PressureDifference dps_default[:]=array(
      Modelica.Math.Vectors.interpolate(
      pressureCurve_default.V_flow,
      pressureCurve_default.dp,
      Vi) for Vi in V_flow_min:(V_flow_max - V_flow_min)/n_sup_pts:V_flow_max)
    "Vector (equally spaced) with pressure heads (default curve) on the basis of n_sup_pts supporting points";
  final parameter Modelica.Units.SI.PressureDifference dps_dpConst[:]=array(
      Modelica.Math.Vectors.interpolate(
      pressureCurve_dpConst.V_flow,
      pressureCurve_dpConst.dp,
      Vi) for Vi in V_flow_min:(V_flow_max - V_flow_min)/n_sup_pts:V_flow_max)
    "Vector (equally spaced) with pressure heads (dpConst curve) on the basis of n_sup_pts supporting points";
  final parameter Modelica.Units.SI.PressureDifference dps_dpVar[:]=array(
      Modelica.Math.Vectors.interpolate(
      pressureCurve_dpVar.V_flow,
      pressureCurve_dpVar.dp,
      Vi) for Vi in V_flow_min:(V_flow_max - V_flow_min)/n_sup_pts:V_flow_max)
    "Vector (equally spaced) with pressure heads (dpVar curve) on the basis of n_sup_pts supporting points";

  function checkDpCurves
    input Modelica.Units.SI.PressureDifference dps_default[:]
      "Reference vector containing pressure head points";
    input Modelica.Units.SI.PressureDifference dps_other[:]
      "Comparing vector containing pressure head points";
    input Integer n_sup_pts(min=2) "Supporting points";
    output Boolean dps_error "Use a boolean to avoid multiple assertion errors to be printed";
  algorithm
    dps_error := false;
    for i in 1:1:n_sup_pts loop
     if dps_error == false and dps_other[i]<=dps_default[i] then
       dps_error :=false;
     else
       dps_error :=true;
     end if;
    end for;
  end checkDpCurves;

initial equation
  assert(pressureCurveSelected.n==1,
    "\n+++++++++++++++++++++++++++++++++++++++++++\nNumber of outputs of table component "+getInstanceName()+".pressureCurveSelected must equal 1, but they are "+String(pressureCurveSelected.n)+".\n+++++++++++++++++++++++++++++++++++++++++++",
    AssertionLevel.error);
  assert(pressureCurveSelected.table[1, 1] == 0.0,
    "\n+++++++++++++++++++++++++++++++++++++++++++\nParameterization error in component ("+getInstanceName()+".pressureCurveSelected):\nThe mover's (pump or fan) curve must have first point at V_flow = 0.0 m3/s.\n+++++++++++++++++++++++++++++++++++++++++++",
    AssertionLevel.error);
  assert(pressureCurveSelected.table[size(pressureCurveSelected.table, 1), size(pressureCurveSelected.table, 2)] == 0.0,
    "\n+++++++++++++++++++++++++++++++++++++++++++\nParameterization error in component ("+getInstanceName()+".pressureCurveSelected):\nThe mover's (pump or fan) curve must have last point at dp = 0.0 Pa.\n+++++++++++++++++++++++++++++++++++++++++++",
    AssertionLevel.error);
  // Check on the basis of n supporting points if both controlled curves are correct parametrized so that they lie below the default curve.
  assert(checkDpCurves(dps_default, dps_dpConst, n_sup_pts)==false,
    "\n+++++++++++++++++++++++++++++++++++++++++++\nParameterization error in component ("+getInstanceName()+".pressureCurve_dpConst):\nThe dp values of the curve must be less or equal the default/total mover's curve.\n+++++++++++++++++++++++++++++++++++++++++++",
     AssertionLevel.error);
  assert(checkDpCurves(dps_default, dps_dpVar, n_sup_pts)==false,
    "\n+++++++++++++++++++++++++++++++++++++++++++\nParameterization error in component ("+getInstanceName()+".pressureCurve_dpVar):\nThe dp values of the curve must be less or equal the default/total mover's curve.\n+++++++++++++++++++++++++++++++++++++++++++",
    AssertionLevel.error);

equation
  connect(mov.port_b, port_b)
  connect(port_a, senVolFlo.port_a)
  connect(senVolFlo.port_b, mov.port_a)
  connect(senVolFlo.V_flow, pressureCurveSelected.u[1])
  connect(dpMea, mov.dpMea)
  connect(mov.heatPort, heatPort)
  connect(mov.P, P)
  connect(mov.y_actual, y_actual)
  connect(mov.dp_actual, dp_actual)
  connect(pressureCurveSelected.y[1], mov.dp_in)
end DpControlled_dp;


Medium model

within AixLib.Fluid.Movers.DpControlledMovers.Examples;
model DpConst
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water "Medium model";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=1.0
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_max=2*m_flow_nominal
    "To describe max point of mover's characteristic curve.";
  parameter Modelica.Units.SI.PressureDifference dp_nominal=100000 "Nominal pressure raise, used to normalized the filter if use_inputFilter=true,
        to set default values of constantHead and heads, and
        and for default pressure curve if not specified in record per";

  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    p=101325,
    T=293.15,
    nPorts=1)

  AixLib.Fluid.Actuators.Valves.TwoWayLinear val(
    redeclare package Medium = Medium,
    from_dp=true,
    m_flow_nominal=m_flow_nominal_max,
    dpValve_nominal=0.5*dp_nominal,
    y_start=rampValve.offset)
                      "Pressure drop"
  AixLib.Fluid.Sensors.MassFlowRate masFloRat(redeclare package Medium = Medium)
  AixLib.Fluid.Movers.DpControlledMovers.DpControlled_dp dpControlled_dp(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    redeclare Data.Generic per(pressure=dpControlled_dp.pressureCurve_default, motorCooledByFluid=false),
    dp_nominal=dp_nominal,
    ctrlType=AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType.dpConst)
  AixLib.Fluid.FixedResistances.PressureDrop dp(
    m_flow_nominal=m_flow_nominal_max,
    redeclare package Medium = Medium,
    dp_nominal=0.5*dp_nominal,
    from_dp=true) "Pressure drop"

  Modelica.Blocks.Sources.Ramp rampValve(
    height=1,
    duration=1800,
    offset=0,
    startTime=900)
  AixLib.Fluid.Delays.DelayFirstOrder vol(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal_max,
    nPorts=2)
  Modelica.Thermal.HeatTransfer.Sources.FixedTemperature fixedTemperature(T=293.15)

  Modelica.Blocks.Continuous.Integrator integrator(u(final quantity="Power", final unit="W"), y(final quantity="Energy", final unit="J", final displayUnit="kW.h"))
  Modelica.Blocks.Interfaces.RealOutput elEnergy(final quantity="Energy", final unit="J", final displayUnit="kW.h") "Cumulated electrical power"
equation

  connect(dpControlled_dp.port_b,val. port_a)
  connect(dp.port_b, dpControlled_dp.port_a)
  connect(val.port_b, masFloRat.port_a)
  connect(sou.ports[1], dp.port_a)
  connect(rampValve.y,val. y)
  connect(masFloRat.port_b, vol.ports[1])
  connect(vol.ports[2], dp.port_a)
  connect(fixedTemperature.port, vol.heatPort)
  connect(dpControlled_dp.P, integrator.u)
  connect(integrator.y, elEnergy)
end DpConst;


within AixLib.Fluid.Movers.DpControlledMovers.Examples;
model DpVar
  extends DpConst(dpControlled_dp(ctrlType=AixLib.Fluid.Movers.DpControlledMovers.Types.CtrlType.dpVar));
end DpVar;


Flow machine with feedback control

within AixLib.Fluid.Movers.Examples;
model ClosedLoop_y "Flow machine with feedback control"
  extends Modelica.Icons.Example;

  package Medium = AixLib.Media.Air;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=0.1
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.PressureDifference dp_nominal=500
    "Nominal pressure difference";

  Modelica.Blocks.Sources.Pulse y(
    offset=0.25,
    startTime=0,
    amplitude=0.5,
    period=15*60) "Input signal"
  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    use_p_in=false,
    p=101325,
    T=293.15,
    nPorts=2)
  AixLib.Fluid.FixedResistances.PressureDrop dp1(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=dp_nominal/2) "Pressure drop"
  AixLib.Fluid.FixedResistances.PressureDrop dp2(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=dp_nominal/2) "Pressure drop"
  AixLib.Fluid.Movers.SpeedControlled_y fan(
      redeclare package Medium = Medium,
      per(pressure(V_flow={0,m_flow_nominal,2*m_flow_nominal}/1.2,
                   dp={2*dp_nominal,dp_nominal,0})),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Fan"
  AixLib.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium =
        Medium)
  AixLib.Controls.Continuous.LimPID conPID(
    Td=1,
    k=0.5,
    Ti=15)
  Modelica.Blocks.Math.Gain gain1(k=1/m_flow_nominal)
equation
  connect(sou.ports[1], senMasFlo.port_a)
  connect(senMasFlo.port_b, dp1.port_a)
  connect(dp1.port_b, fan.port_a)
  connect(fan.port_b, dp2.port_a)
  connect(dp2.port_b, sou.ports[2])
  connect(senMasFlo.m_flow, gain1.u)
  connect(gain1.y, conPID.u_m)
  connect(y.y, conPID.u_s)
  connect(conPID.y, fan.y)
end ClosedLoop_y;


Example model of movers using a real input for setting the stage. This example demonstrates the use of a RealInput
connector for a mover model.

within AixLib.Fluid.Movers.Examples;
model MoverContinuous
  "Example model of movers using a real input for setting the stage"
  extends MoverParameter(
    pump_m_flow(inputType=AixLib.Fluid.Types.InputType.Continuous),
    pump_y(inputType=AixLib.Fluid.Types.InputType.Continuous),
    pump_dp(inputType=AixLib.Fluid.Types.InputType.Continuous));
  Modelica.Blocks.Sources.Ramp ramp(duration=1) "Ramp input for all movers"
  Modelica.Blocks.Math.Gain gai_m_flow(k=m_flow_nominal)
    "Nominal mass flow rate"
  Modelica.Blocks.Math.Gain gai_dp(k=dp_nominal) "Nominal pressure drop"
equation
  connect(gai_dp.y, pump_dp.dp_in)
  connect(gai_m_flow.y, pump_m_flow.m_flow_in)
  connect(gai_m_flow.u, ramp.y)
  connect(gai_dp.u, ramp.y)
  connect(pump_y.y, ramp.y)
end MoverContinuous;


within AixLib.Fluid.Movers.Examples;
model MoverParameter
  "Example model of movers using a parameter for setting the stage"
  extends Modelica.Icons.Example;
  package Medium = AixLib.Media.Water;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=2
    "Nominal mass flow rate";

  AixLib.Fluid.Movers.FlowControlled_m_flow pump_m_flow(
    redeclare package Medium = Medium,
    nominalValuesDefineDefaultPressureCurve=true,
    m_flow_nominal=m_flow_nominal,
    use_inputFilter=false,
    massFlowRates={0,0.5,1}*m_flow_nominal,
    inputType=AixLib.Fluid.Types.InputType.Constant,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump with m_flow input"

  AixLib.Fluid.Sources.Boundary_pT sou(
    redeclare package Medium = Medium,
    nPorts=3) "Fluid source"

  AixLib.Fluid.Sources.Boundary_pT sin(redeclare package Medium = Medium,
      nPorts=3) "Fluid sink"
  AixLib.Fluid.Movers.SpeedControlled_y pump_y(
    redeclare package Medium = Medium,
    redeclare AixLib.Fluid.Movers.Data.Pumps.Wilo.Stratos25slash1to4 per(
        speeds={0,0.5,1}, constantSpeed=1),
    use_inputFilter=false,
    inputType=AixLib.Fluid.Types.InputType.Constant,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump with normalised speed input"
  AixLib.Fluid.Movers.FlowControlled_dp pump_dp(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    redeclare AixLib.Fluid.Movers.Data.Pumps.Wilo.Stratos25slash1to4 per,
    use_inputFilter=false,
    heads={0,0.5,1}*dp_nominal,
    inputType=AixLib.Fluid.Types.InputType.Constant,
    dp_nominal=dp_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump with pressure head input"
  AixLib.Fluid.FixedResistances.PressureDrop res(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=dp_nominal)
    "Pressure drop component for avoiding singular system"
  parameter Modelica.Units.SI.PressureDifference dp_nominal=10000
    "Nominal pressure raise";
equation
  connect(sou.ports[1], pump_m_flow.port_a)
  connect(pump_m_flow.port_b, sin.ports[1])
  connect(res.port_a, pump_dp.port_b)
  connect(pump_y.port_b, sin.ports[2])
  connect(res.port_b, sin.ports[3])
  connect(pump_dp.port_a, sou.ports[2])
  connect(pump_y.port_a, sou.ports[3])
end MoverParameter;


within AixLib.Fluid.Movers.Examples;
model MoverStages
  "Example model of movers using an integer input for setting the stage"
  extends AixLib.Fluid.Movers.Examples.MoverParameter(
    pump_m_flow(inputType=AixLib.Fluid.Types.InputType.Stages),
    pump_y(inputType=AixLib.Fluid.Types.InputType.Stages),
    pump_dp(inputType=AixLib.Fluid.Types.InputType.Stages));
  package Medium = AixLib.Media.Water;

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=2
    "Nominal mass flow rate";

  Modelica.Blocks.Sources.IntegerTable integerTable(table=[0,1; 0.3,2; 0.6,3])
    "Integer step input, 1 is off, 2 is on"
  parameter Modelica.Units.SI.PressureDifference dp_nominal=10000
    "Nominal pressure raise";
equation
  connect(integerTable.y, pump_m_flow.stage)
  connect(integerTable.y, pump_y.stage)
  connect(integerTable.y, pump_dp.stage)
end MoverStages;


within AixLib.Fluid.Movers;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;