Calculates cooling capacity at given temperature and flow fraction for water source DX coils. This model calculates cooling capacity and EIR at off-designed conditions for water source DX coils.
  The difference between air source and water source DX coils is that water source DX coils require
  two additional modifer curves for total cooling capacity and EIR
  as a function of water mass flowrate at the condensers.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block CapacityWaterCooled
  "Calculates cooling capacity at given temperature and flow fraction for water source DX coils"
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCapacity(
  final use_mCon_flow=true,
  redeclare Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.BaseClasses.Stage sta[nSta]);

protected
  Real[nSta] ffCon(each min=0)
    "Water flow fraction: ratio of actual water flow rate by rated mass flow rate at the condenser";

   Real cap_FFCon[nSta](each min=0, each nominal=1, each start=1)
    "Cooling capacity modification factor as a function of water flow fraction at the condenser";

  Real EIR_FFCon[nSta](each min=0, each nominal=1, each start=1)
    "EIR modification factor as a function of water flow fraction at the condenser";
  Real corFacCon[nSta](each min=0, each max=1, each nominal=1, each start=1)
    "Correction factor that is one inside the valid water flow fraction, and attains zero below the valid water flow fraction at the condenser";
  Modelica.Blocks.Interfaces.RealInput mCon_flow_internal
    "Internal connector, needed as mCon_flow can be conditionally removed";
initial algorithm
  // Verify correctness of performance curves, and write warning if error is bigger than 10%
   for iSta in 1:nSta loop

     Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
       Buildings.Fluid.Utilities.extendedPolynomial(
         x=1,
         c=sta[iSta].perCur.capFunFFCon,
         xMin=sta[iSta].perCur.ffConMin,
         xMax=sta[iSta].perCur.ffConMax),
         msg="Capacity as a function of normalized water mass flow rate at the condenser",
         curveName="sta[" + String(iSta) + "].perCur.capFunFFCon");

     Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
       Buildings.Fluid.Utilities.extendedPolynomial(
         x=1,
         c=sta[iSta].perCur.EIRFunFF,
         xMin=sta[iSta].perCur.ffConMin,
         xMax=sta[iSta].perCur.ffConMax),
         msg="EIR as a function of normalized water mass flow rate at the condenser",
         curveName="sta[" + String(iSta) + "].perCur.EIRFunFFCon");
   end for;

equation

   if use_mCon_flow then
     connect(mCon_flow_internal, mCon_flow);
   else
     mCon_flow_internal = 0;
   end if;

    // Modelica requires to evaluate the when() block for each element in iSta=1...nSta.
    // But we only want to check the stage that is currently running.
    // Hence, the test starts with stage == iSta.

if stage > 0 then
    for iSta in 1:nSta loop

    // Compute performance
    ffCon[iSta]=Buildings.Utilities.Math.Functions.smoothMax(
      x1=mCon_flow_internal,
      x2=m_flow_small,
      deltaX=m_flow_small/10)/sta[iSta].nomVal.mCon_flow_nominal;
  //-------------------------Cooling capacity modifiers----------------------------//

    cap_FFCon[iSta] = Buildings.Fluid.Utilities.extendedPolynomial(
      x=ffCon[iSta],
      c=sta[iSta].perCur.capFunFFCon,
      xMin=sta[iSta].perCur.ffConMin,
      xMax=sta[iSta].perCur.ffConMax);
    //-----------------------Energy Input Ratio modifiers--------------------------//
    EIR_FFCon[iSta] = Buildings.Fluid.Utilities.extendedPolynomial(
       x=ffCon[iSta],
       c=sta[iSta].perCur.EIRFunFFCon,
       xMin=sta[iSta].perCur.ffConMin,
       xMax=sta[iSta].perCur.ffConMax)
        "Cooling capacity modification factor as function of flow fraction";
    //------------ Correction factor for flow rate outside of validity of data ---//
    corFacCon[iSta] =Buildings.Utilities.Math.Functions.smoothHeaviside(
       x=ffCon[iSta] - sta[iSta].perCur.ffConMin/4,
       delta=max(Modelica.Constants.eps, sta[iSta].perCur.ffConMin/8));

    Q_flow[iSta] = corFac[iSta]*corFacCon[iSta]*cap_T[iSta]*cap_FF[iSta]*cap_FFCon[iSta]*sta[iSta].nomVal.Q_flow_nominal;
    EIR[iSta]    = corFac[iSta]*corFacCon[iSta]*EIR_T[iSta]*EIR_FF[iSta]*EIR_FFCon[iSta]/sta[iSta].nomVal.COP_nominal;
    end for;
  else //cooling coil off
   ffCon     = fill(0, nSta);
   cap_FFCon = fill(0, nSta);
   EIR_FFCon = fill(0, nSta);
   corFacCon = fill(0, nSta);
   Q_flow = fill(0, nSta);
   EIR    = fill(0, nSta);
  end if;
end CapacityWaterCooled;


Calculates rate of condensation. This block computes the water mass flow rate that condenses.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block Condensation "Calculates rate of condensation"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput Q_flow(
    max=0,
    unit="W") "Heat flow"
  Modelica.Blocks.Interfaces.RealInput SHR(
    min=0,
    max=1) "Sensible heat ratio"
  Modelica.Blocks.Interfaces.RealOutput mWat_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Mass flow rate of water condensed at cooling coil"
equation
  mWat_flow = (1-SHR)*Q_flow/Buildings.Utilities.Psychrometrics.Constants.h_fg;
end Condensation;


Selects results from dry or wet coil. This block smoothly transitions the results from the dry coil and
the wet coil computation.
The independent variable for the transition is the difference between
the water mass fractions at the apparatus dew point, as computed by the wet coil model,
and the coil inlet mass fraction.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block DryWetSelector "Selects results from dry or wet coil"

  constant Modelica.Units.SI.MassFraction deltaX=0.0001
    "Range of x where transition between dry and wet coil occurs";
  Modelica.Blocks.Interfaces.RealInput XEvaIn "Inlet air mass fraction"
  Modelica.Blocks.Interfaces.RealInput XADP "Mass fraction at ADP"

  Modelica.Blocks.Interfaces.RealInput EIRWet "Energy Input Ratio"
  Modelica.Blocks.Interfaces.RealInput QWet_flow(
    max=0,
    unit="W") "Total cooling capacity"
  Modelica.Blocks.Interfaces.RealInput SHRWet(
    min=0,
    max=1.0)
    "Sensible Heat Ratio: Ratio of sensible heat load to total heat load"
  Modelica.Blocks.Interfaces.RealInput mWetWat_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Mass flow rate of water condensed at cooling coil"
  Modelica.Blocks.Interfaces.RealInput EIRDry "Energy Input Ratio"
  Modelica.Blocks.Interfaces.RealInput QDry_flow(max=0, unit="W")
    "Total cooling capacity"
  Modelica.Blocks.Interfaces.RealOutput EIR "Energy Input Ratio"
  Modelica.Blocks.Interfaces.RealOutput Q_flow(
    max=0,
    unit="W") "Total cooling capacity"
  Modelica.Blocks.Interfaces.RealOutput SHR(
    min=0,
    max=1.0)
    "Sensible Heat Ratio: Ratio of sensible heat load to total heat load"
  Modelica.Blocks.Interfaces.RealOutput mWat_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Mass flow rate of water condensed at cooling coil"

 output Real fraDry(min=0, max=1)
    "Fraction of results that are taken from the dry coil model";
 output Real fraWet(min=0, max=1)
    "Fraction of results that are taken from the wet coil model";
protected
  output Modelica.Units.SI.MassFraction dX(min=-1, max=1)
    "Difference between apparatus dew point mass fraction of wet coil and inlet air mass fraction";
equation
  dX = XADP-XEvaIn;
  fraDry=Buildings.Utilities.Math.Functions.spliceFunction(
    pos=+1,
    neg=0,
    x= dX+deltaX,
    deltax= deltaX);
  fraWet=1-fraDry;
  EIR       = fraDry * EIRDry    + fraWet * EIRWet;
  Q_flow    = fraDry * QDry_flow + fraWet * QWet_flow;
  SHR       = fraDry             + fraWet * SHRWet;
  mWat_flow =                      fraWet * mWetWat_flow;
end DryWetSelector;


DX cooling coil operation

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
model DXCooling "DX cooling coil operation "
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCoilInterface;
  replaceable package Medium =
      Modelica.Media.Interfaces.PartialCondensingGases "Medium model"

  constant Boolean variableSpeedCoil
    "Flag, set to true for coil with variable speed";

  WetCoil wetCoi(
    redeclare final package Medium = Medium,
    final variableSpeedCoil = variableSpeedCoil,
    datCoi=datCoi,
    use_mCon_flow=use_mCon_flow) "Wet coil condition"
  DXSystems.BaseClasses.DryCoil dryCoi(
    redeclare final package Medium = Medium,
    final variableSpeedCoil = variableSpeedCoil,
    datCoi=datCoi,
    use_mCon_flow=use_mCon_flow) "Dry coil condition"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.DryWetSelector dryWet
    "Actual coil condition"
  Modelica.Blocks.Interfaces.RealOutput mWat_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Mass flow rate of water condensed at cooling coil"
  Modelica.Blocks.Interfaces.RealOutput SHR(
    min=0,
    max=1.0)
    "Sensible Heat Ratio: Ratio of sensible heat load to total heat load"
  Modelica.Blocks.Interfaces.RealInput XEvaIn "Inlet air mass fraction"
  Modelica.Blocks.Interfaces.RealInput p "Pressure at inlet of coil"
  Modelica.Blocks.Interfaces.RealInput hEvaIn
    "Specific enthalpy of air entering the coil"
equation

  connect(TConIn, wetCoi.TConIn)
  connect(TConIn, dryCoi.TConIn)
  connect(m_flow, wetCoi.m_flow)
  connect(m_flow, dryCoi.m_flow)
  connect(TEvaIn, wetCoi.TEvaIn)
  connect(TEvaIn, dryCoi.TEvaIn)
  connect(p, wetCoi.p)
  connect(XEvaIn, wetCoi.XEvaIn)
  connect(hEvaIn, wetCoi.hEvaIn)
  connect(speRat, wetCoi.speRat)
  connect(speRat, dryCoi.speRat)

  connect(XEvaIn, dryWet.XEvaIn)
  connect(stage, dryCoi.stage)
  connect(stage, wetCoi.stage)
  connect(dryWet.EIRWet, wetCoi.EIR)
  connect(wetCoi.Q_flow, dryWet.QWet_flow)
  connect(wetCoi.SHR, dryWet.SHRWet)
  connect(wetCoi.mWat_flow, dryWet.mWetWat_flow)
  connect(dryCoi.EIR, dryWet.EIRDry)
  connect(dryCoi.Q_flow, dryWet.QDry_flow)
  connect(dryWet.EIR, EIR)
  connect(dryWet.Q_flow, Q_flow)
  connect(dryWet.SHR, SHR)
  connect(dryWet.mWat_flow, mWat_flow)
  connect(wetCoi.XADP, dryWet.XADP)
  connect(mCon_flow, wetCoi.mCon_flow)
  connect(mCon_flow, dryCoi.mCon_flow)
end DXCooling;


A partial block for essential parameters for cooling DX coils. This partial block declares parameters that are required by most classes for cooling DX coils
in the package

Buildings.Fluid.DXSystems.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial block EssentialParameters
  "A partial block for essential parameters for cooling DX coils"

 replaceable parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi
    "Performance data"

protected
  parameter Integer nSta=datCoi.nSta "Number of stages";
end EssentialParameters;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
model Evaporation
  "Model that computes evaporation of water that accumulated on the coil surface"
  extends Modelica.Blocks.Icons.Block;
  replaceable package Medium =
    Modelica.Media.Interfaces.PartialCondensingGases "Medium model"

  parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues
    nomVal "Nominal values"

  parameter Modelica.Units.SI.MassFlowRate mAir_flow_small(min=0) = 0.1*abs(
    nomVal.m_flow_nominal)
    "Small mass flow rate for regularization of zero flow"

  final parameter Modelica.Units.SI.Mass mMax(min=0, fixed=false)
    "Maximum mass of water that can accumulate on the coil";

  parameter Boolean computeReevaporation=true
    "Set to true to compute reevaporation of water that accumulated on coil";

  ////////////////////////////////////////////////////////////////////////////////
  // Input and output signals
  Modelica.Blocks.Interfaces.BooleanInput on
    "Control signal, true if compressor is on"

  Modelica.Blocks.Interfaces.RealInput mWat_flow(final quantity="MassFlowRate",
                                                 final unit = "kg/s")
    "Water flow rate added into the medium"

  Modelica.Blocks.Interfaces.RealInput mAir_flow(final quantity="MassFlowRate",
                                                 final unit = "kg/s")
    "Air mass flow rate"

  Modelica.Blocks.Interfaces.RealInput XEvaOut(min=0, max=1, unit="1")
    "Water mass fraction"

  Modelica.Blocks.Interfaces.RealInput TEvaOut(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Air temperature"

  Modelica.Blocks.Interfaces.RealOutput mTotWat_flow(final quantity="MassFlowRate",
                                                     final unit = "kg/s")
    "Total moisture mass flow rate into the air stream"

  Modelica.Units.SI.Mass m(
    nominal=-5000*1400/2257E3,
    start=0,
    fixed=true) "Mass of water that accumulated on the coil";

  Modelica.Units.SI.MassFlowRate mEva_flow(start=0)
    "Moisture mass flow rate that evaporates into air stream";
  ////////////////////////////////////////////////////////////////////////////////
  // Protected parameters and variables
protected
  final parameter Modelica.Units.SI.HeatFlowRate QSen_flow_nominal(max=0, fixed=
       false) "Nominal sensible heat flow rate (negative number)";
  final parameter Modelica.Units.SI.HeatFlowRate QLat_flow_nominal(max=0, fixed=
       false) "Nominal latent heat flow rate (negative number)";
  final parameter Modelica.Units.SI.MassFraction XEvaIn_nominal(fixed=false)
    "Mass fraction at nominal inlet conditions";
  final parameter Modelica.Units.SI.MassFraction XEvaOut_nominal(fixed=false)
    "Mass fraction at nominal outlet conditions";
  final parameter Modelica.Units.SI.MassFraction XiSatRefOut_nominal(fixed=
        false)
    "Water vapor mass fraction at saturation, referenced to outlet mass flow rate";
  final parameter Modelica.Units.SI.Temperature TEvaOut_nominal(fixed=false)
    "Dry bulb temperature at nominal outlet conditions";
  final parameter Modelica.Units.SI.Temperature TEvaWetBulOut_nominal(fixed=
        false) "Wet bulb temperature at nominal outlet conditions";
  final parameter Modelica.Units.SI.MassFraction XEvaWetBulOut_nominal(fixed=
        false) "Water vapor mass fraction at nominal outlet wet bulb condition";
  final parameter Modelica.Units.SI.MassFraction dX_nominal(
    min=-1,
    max=0,
    fixed=false) "Driving potential for mass transfer";

  final parameter Modelica.Units.SI.SpecificEnthalpy h_fg(fixed=false)
    "Latent heat of vaporization";
  final parameter Real gammaMax(min=0, fixed=false) "Maximum value for gamma";
  final parameter Real logArg(min=0, fixed=false)
    "Argument for the log function";
  final parameter Real K(min=0, fixed=false)
    "Coefficient used for convective mass transfer";
  final parameter Real K2(min=0, fixed=false)
    "Coefficient used for convective mass transfer";

  Modelica.Units.SI.MassFraction XEvaWetBulOut
    "Water vapor mass fraction at wet bulb conditions at air inlet";

  Modelica.Units.SI.MassFraction XiSatRefOut
    "Water vapor mass fraction at saturation, referenced to outlet mass flow rate";

   // off = not on is required because Dymola 2013 fails during model
   // check if on, which is an input connector, is used in the edge() function
  Boolean off=not on "Signal, true when component is off";

  Modelica.Units.SI.Temperature TEvaWetBulOut "Wet bulb temperature at coil";
  Modelica.Units.SI.MassFraction dX(min=-1, max=0)
    "Difference in water vapor concentration that drives mass transfer";

  constant Modelica.Units.SI.SpecificHeatCapacity cpAir_nominal=Buildings.Utilities.Psychrometrics.Constants.cpAir
    "Specific heat capacity of air";
  constant Modelica.Units.SI.SpecificHeatCapacity cpSte_nominal=Buildings.Utilities.Psychrometrics.Constants.cpSte
    "Specific heat capacity of water vapor";
  constant Modelica.Units.SI.SpecificHeatCapacity cpWatLiq_nominal=Buildings.Utilities.Psychrometrics.Constants.cpWatLiq
    "Specific heat capacity of liquid water";
  constant Modelica.Units.SI.Temperature T_ref=Buildings.Utilities.Psychrometrics.Constants.T_ref
    "Reference temperature for psychrometric calculations";
initial equation
  QSen_flow_nominal=nomVal.SHR_nominal * nomVal.Q_flow_nominal;
  QLat_flow_nominal=nomVal.Q_flow_nominal-QSen_flow_nominal;
  h_fg = Medium.enthalpyOfVaporization(nomVal.TEvaIn_nominal);

  mMax = -QLat_flow_nominal * nomVal.tWet/h_fg;

  XEvaIn_nominal=Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
     pSat=Medium.saturationPressure(nomVal.TEvaIn_nominal),
     p=nomVal.p_nominal,
     phi=nomVal.phiIn_nominal);
  XEvaOut_nominal = XEvaIn_nominal + QLat_flow_nominal/nomVal.m_flow_nominal/h_fg;

  // Compute outlet air temperature
  TEvaOut_nominal =
  (nomVal.TEvaIn_nominal*Medium.specificHeatCapacityCp(
      Medium.setState_pTX(p=nomVal.p_nominal,
                          T=nomVal.TEvaIn_nominal,
                          X=cat(1, {XEvaIn_nominal, 1-XEvaIn_nominal})))
     + QSen_flow_nominal/nomVal.m_flow_nominal)
     / Medium.specificHeatCapacityCp(
      Medium.setState_pTX(p=nomVal.p_nominal,
                          T=nomVal.TEvaIn_nominal,
                          X=cat(1, {XEvaOut_nominal, 1-XEvaOut_nominal})));
  // Compute wet bulb temperature.
  // The computation of the wet bulb temperature requires an iterative
  // solution. It therefore cannot be done in a function.
  // The block Buildings.Utilities.Psychrometrics.TWetBul_TDryBulXi
  // implements the equation below, but it cannot
  // be used here because blocks cannot be used to assign parameter
  // values.
  XEvaWetBulOut_nominal   = Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
      pSat = Buildings.Utilities.Psychrometrics.Functions.saturationPressureLiquid(TEvaWetBulOut_nominal),
      p =    nomVal.p_nominal,
      phi =  1);

  XiSatRefOut_nominal=(1-XEvaOut_nominal)*XEvaWetBulOut_nominal/(1-XEvaWetBulOut_nominal);
    (TEvaWetBulOut_nominal-T_ref) * (
              (1-XEvaOut_nominal) * cpAir_nominal +
              XiSatRefOut_nominal * cpSte_nominal +
              (XEvaOut_nominal-XiSatRefOut_nominal) * cpWatLiq_nominal) =
    (TEvaOut_nominal-T_ref) * (
              (1-XEvaOut_nominal) * cpAir_nominal +
              XEvaOut_nominal * cpSte_nominal)  +
    (XEvaOut_nominal-XiSatRefOut_nominal) * Buildings.Utilities.Psychrometrics.Constants.h_fg;

  // Potential difference in moisture concentration that drives mass transfer at nominal condition
  dX_nominal = XEvaOut_nominal-XEvaWetBulOut_nominal;
  assert(
    dX_nominal < 0,
    "*** Warning: In DX coil model, dX_nominal = " + String(dX_nominal) + "
    This means that the coil is not dehumidifying air at the nominal conditions.
    Check nominal parameters.
    " +
      Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.nominalValuesToString(
      nomVal),
    AssertionLevel.warning);

  gammaMax = 0.8 * nomVal.m_flow_nominal * dX_nominal * h_fg / QLat_flow_nominal;

  // If gamma is bigger than a maximum value, write a warning and then
  // use the smaller value.
  assert(nomVal.gamma <= gammaMax,
  "*** Warning: In DX coil model, gamma is too large for these coil conditions.
    Instead of gamma = " + String(nomVal.gamma) + ", a value of " + String(gammaMax) + ", which
    corresponds to a mass transfer effectiveness of 0.8, will be used.
    Coil nominal performance data are:
    nomVal.m_flow_nominal = " + String(nomVal.m_flow_nominal) + "
    dX_nominal = XEvaOut_nominal-XEvaWetBulOut_nominal = " + String(XEvaOut_nominal) + " - " +
      String(XEvaWetBulOut_nominal) + " = " + String(dX_nominal) + "
    QLat_flow_nominal  = " + String(QLat_flow_nominal) + "\n",
   AssertionLevel.warning);

  logArg = 1-min(nomVal.gamma, gammaMax)*QLat_flow_nominal/nomVal.m_flow_nominal/h_fg/dX_nominal;

  K = -Modelica.Math.log(logArg);
  K2 = K/mMax*nomVal.m_flow_nominal^(-0.2);

  assert(QLat_flow_nominal < 0, "QLat_nominal must be a negative number. Check parameters.");

  assert(K > 0, "Require K>0 but received " + String(K) + "
    The parameter are:
    QSen_flow_nominal     = " + String(QSen_flow_nominal) + "
    QLat_flow_nominal     = " + String(QLat_flow_nominal) + "
    XEvaOut_nominal        = " + String(XEvaOut_nominal) + "
   " +
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.nominalValuesToString(
    nomVal) + "
  Check parameters. Maybe the sensible heat ratio is too big, or the mass flow rate is too small.");

equation
  // When the coil switches off, set accumulated water to
  // lower value of actual accumulated water or maximum water content
  if computeReevaporation then
    when edge(off) then
      reinit(m, min(m, mMax));
    end when;

    if on then
      dX = 0;
      mEva_flow = 0;
      mTotWat_flow = mWat_flow;
      der(m) = -mWat_flow;
      TEvaWetBulOut = 293.15;
      XEvaWetBulOut = 0;
      XiSatRefOut = 0;
    else
      // Compute wet bulb temperature.
      // The computation of the wet bulb temperature requires an iterative
      // solution. It therefore cannot be done in a function.
      // The block Buildings.Utilities.Psychrometrics.TWetBul_TDryBulXi
      // implements the equation below, but it is not used here
      // because otherwise, in each branch of the if-then construct,
      // an iteration would be done. This would be inefficient because
      // the wet bulb conditions are only needed in this branch.

      XiSatRefOut=(1-XEvaOut)*XEvaWetBulOut/(1-XEvaWetBulOut);
      XEvaWetBulOut  = Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
        pSat = Buildings.Utilities.Psychrometrics.Functions.saturationPressureLiquid(TEvaWetBulOut),
        p =    nomVal.p_nominal,
        phi =  1);
      (TEvaWetBulOut-T_ref) * (
                (1-XEvaOut) * cpAir_nominal +
                XiSatRefOut * cpSte_nominal +
                (XEvaOut-XiSatRefOut) * cpWatLiq_nominal) =
      (TEvaOut-T_ref) * (
                (1-XEvaOut) * cpAir_nominal +
                XEvaOut * cpSte_nominal)  +
      (XEvaOut-XiSatRefOut) * Buildings.Utilities.Psychrometrics.Constants.h_fg;

      dX = smooth(1, noEvent(
         Buildings.Utilities.Math.Functions.spliceFunction(
         pos=XEvaOut,
         neg=XEvaWetBulOut,
         x=abs(mAir_flow)-nomVal.m_flow_nominal/2,
         deltax=nomVal.m_flow_nominal/3)))
        - XEvaWetBulOut;
      mEva_flow = -dX * smooth(1, noEvent(
        Buildings.Utilities.Math.Functions.spliceFunction(
         pos=if abs(mAir_flow) > mAir_flow_small/3 then
            abs(mAir_flow) * (1-Modelica.Math.exp(-K2*m*abs(mAir_flow)^(-0.2))) else 0,
         neg=K2*mAir_flow_small^(-0.2)*m*mAir_flow^2,
         x=abs(mAir_flow)- 2*mAir_flow_small/3,
         deltax=2*mAir_flow_small/6)));
      der(m) = -mEva_flow;
      mTotWat_flow = mWat_flow + mEva_flow;
    end if;

  else // The model is configured to not compute reevaporation
    dX = 0;
    mEva_flow = 0;
    mTotWat_flow = mWat_flow;
    m = 0;
    TEvaWetBulOut = 293.15;
    XEvaWetBulOut = 0;
  end if;
end Evaporation;


Electrical power consumed by the unit. This block calculates total electrical energy consumed by the unit using
the rate of cooling and the energy input ratio <i>EIR</i>.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block InputPower
  "Electrical power consumed by the unit"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput Q_flow(
    final quantity="Power",
    final unit="W")
    "Cooling capacity of the coil"

  Modelica.Blocks.Interfaces.RealInput EIR
    "Energy input ratio"

  Modelica.Blocks.Interfaces.RealInput SHR(
    final min=0,
    final max=1)
    "Sensible heat ratio"

  Modelica.Blocks.Interfaces.RealOutput P(
    final quantity="Power",
    final unit="W")
    "Electrical power consumed by the unit"

  Modelica.Blocks.Interfaces.RealOutput QSen_flow(
    final quantity="Power",
    final unit="W")
    "Sensible heat flow rate"

  Modelica.Blocks.Interfaces.RealOutput QLat_flow(
    final quantity="Power",
    final unit="W")
    "Latent heat flow rate"

protected
  Modelica.Blocks.Math.Product proQ
    "Multiply SHR by total heat transfer rate to get sensible heat flow rate"

  Modelica.Blocks.Math.Add add(
    final k1=-1)
    "Subtract sensible heat transfer rate from total heat transfer rate to get
    latent heat flow rate"

  Modelica.Blocks.Math.Product proP
    "Multiply EIR by heat transferred to medium to get power consumption"

  Modelica.Blocks.Math.Gain gain(
    final k=-1)
    "Multiply by -1 to get positive value for energy consumption"

equation
  connect(SHR, proQ.u2)
  connect(Q_flow, proQ.u1)
  connect(proQ.y, QSen_flow)
  connect(add.y, QLat_flow)
  connect(Q_flow, add.u2)
  connect(proQ.y, add.u1)
  connect(EIR,proP. u1)
  connect(Q_flow,proP. u2)
  connect(gain.y, P)
  connect(proP.y, gain.u)
end InputPower;


within Buildings.Fluid.DXSystems.Cooling;
package BaseClasses "Package with base classes for Buildings.Fluid.DXSystems.Cooling"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Calculates performance curve value at given temperature and mass flow rate.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial block PartialCapacity
  "Calculates performance curve value at given temperature and mass flow rate"
  extends Modelica.Blocks.Icons.Block;

  constant Boolean use_mCon_flow
    "Set to true to enable connector for the condenser mass flow rate";

  Modelica.Blocks.Interfaces.IntegerInput stage(final min=0)
    "Stage of coil, or 0/1 for variable-speed coil"
  Modelica.Blocks.Interfaces.RealInput TConIn(
    quantity="ThermodynamicTemperature",
    unit="K",
    displayUnit="degC") "Temperature of air entering the condenser coil "
  Modelica.Blocks.Interfaces.RealInput m_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Air mass flow rate at the evaporator"
  Modelica.Blocks.Interfaces.RealInput TEvaIn(
    quantity="ThermodynamicTemperature",
    unit="K",
    displayUnit="degC")
    "Temperature of air entering the evaporator (wet bulb for wet coil and dry bulb for dry coil)"
  Modelica.Blocks.Interfaces.RealInput mCon_flow(
    quantity="MassFlowRate",
    unit="kg/s") if use_mCon_flow "Water mass flow rate at the condenser"

  parameter Integer nSta(min=1)
    "Number of coil stages (not counting the off stage)";

 replaceable parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage sta[nSta]
     "Performance data for this stage";
  output Real[nSta] ff(each min=0)
    "Air flow fraction: ratio of actual air flow rate by rated mass flow rate";

  Modelica.Blocks.Interfaces.RealOutput Q_flow[nSta](
    each max=0,
    each unit="W") "Total cooling capacity"

  Modelica.Blocks.Interfaces.RealOutput EIR[nSta](each min=0)
    "Energy Input Ratio"

//------------------------------Cooling capacity---------------------------------//
  Real cap_T[nSta](each min=0, each nominal=1, each start=1)
    "Cooling capacity modification factor as a function of temperature";
  Real cap_FF[nSta](each min=0, each nominal=1, each start=1)
    "Cooling capacity modification factor as a function of flow fraction";

//----------------------------Energy Input Ratio---------------------------------//
  Real EIR_T[nSta](each min=0, each nominal=1, each start=1)
    "EIR modification factor as a function of temperature";
  Real EIR_FF[nSta](each min=0, each nominal=1, each start=1)
    "EIR modification factor as a function of flow fraction";
  Real corFac[nSta](each min=0, each max=1, each nominal=1, each start=1)
    "Correction factor that is one inside the valid flow fraction, and attains zero below the valid flow fraction";

protected
  final parameter Modelica.Units.SI.MassFlowRate m_flow_small=1E-4*sta[nSta].nomVal.m_flow_nominal
    "Small mass flow rate for regularization";

  Boolean checkBoundsTEva[nSta]
    "Flag, used to check for out of bounds data";
  Boolean checkBoundsTCon[nSta]
    "Flag, used to check for out of bounds data";

initial algorithm
  // Verify correctness of performance curves, and write warning if error is bigger than 10%
   for iSta in 1:nSta loop
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
      Buildings.Utilities.Math.Functions.biquadratic(
        a=sta[iSta].perCur.capFunT,
        x1=Modelica.Units.Conversions.to_degC(sta[iSta].nomVal.TEvaIn_nominal),
        x2=Modelica.Units.Conversions.to_degC(sta[iSta].nomVal.TConIn_nominal)),
      msg="Capacity as a function of temperature ",
      curveName="sta[" + String(iSta) + "].perCur.capFunT");

     Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
       Buildings.Fluid.Utilities.extendedPolynomial(
         x=1,
         c=sta[iSta].perCur.capFunFF,
         xMin=sta[iSta].perCur.ffMin,
         xMax=sta[iSta].perCur.ffMax),
         msg="Capacity as a function of normalized mass flow rate ",
         curveName="sta[" + String(iSta) + "].perCur.capFunFF");

    Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
      Buildings.Utilities.Math.Functions.biquadratic(
        a=sta[iSta].perCur.EIRFunT,
        x1=Modelica.Units.Conversions.to_degC(sta[iSta].nomVal.TEvaIn_nominal),
        x2=Modelica.Units.Conversions.to_degC(sta[iSta].nomVal.TConIn_nominal)),
      msg="EIR as a function of temperature ",
      curveName="sta[" + String(iSta) + "].perCur.EIRFunT");

    Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.warnIfPerformanceOutOfBounds(
       Buildings.Fluid.Utilities.extendedPolynomial(
         x=1,
         c=sta[iSta].perCur.EIRFunFF,
         xMin=sta[iSta].perCur.ffMin,
         xMax=sta[iSta].perCur.ffMax),
         msg="EIR as a function of normalized mass flow rate ",
         curveName="sta[" + String(iSta) + "].perCur.EIRFunFF");
   end for;

  checkBoundsTEva := fill(true, nSta);
  checkBoundsTCon := fill(true, nSta);

equation
    // Modelica requires to evaluate the when() block for each element in iSta=1...nSta.
    // But we only want to check the stage that is currently running.
    // Hence, the test starts with stage == iSta.
    for iSta in 1:nSta loop
   // Check whether data are outside of bounds
      when ( stage == iSta and pre(checkBoundsTEva[stage])) then
      assert(
        not (TEvaIn > sta[stage].perCur.TEvaInMax or TEvaIn < sta[stage].perCur.TEvaInMin),
        "*** Warning: Evaporator temperature TEvaIn is out of bounds in DX coil model at time = "
           + String(time) + ".
    stage     = " + String(iSta) + "
    TEvaInMin = " + String(sta[iSta].perCur.TEvaInMin) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(sta[iSta].perCur.TEvaInMin)) + " degC)
    TEvaIn    = " + String(TEvaIn) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(TEvaIn)) + " degC)
    TEvaInMax = " + String(sta[iSta].perCur.TEvaInMax) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(sta[iSta].perCur.TEvaInMax)) + " degC)
    Extrapolation can introduce large errors.
    This warning will only be reported once for each stage.",
        level=AssertionLevel.warning);
        checkBoundsTEva[iSta] = false;
      end when;
      when ( stage == iSta and pre(checkBoundsTCon[stage])) then
      assert(
        not (TConIn > sta[stage].perCur.TConInMax or TConIn < sta[stage].perCur.TConInMin),
        "*** Warning: Condenser temperature TConIn is out of bounds in DX coil model at time = "
           + String(time) + ".
    stage     = " + String(iSta) + "
    TConInMin = " + String(sta[iSta].perCur.TConInMin) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(sta[iSta].perCur.TConInMin)) + " degC)
    TConIn    = " + String(TConIn) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(TConIn)) + " degC)
    TConInMax = " + String(sta[iSta].perCur.TConInMax) + " Kelvin (" + String(
          Modelica.Units.Conversions.to_degC(sta[iSta].perCur.TConInMax)) + " degC)
    Extrapolation can introduce large errors.
    This warning will only be reported once for each stage.",
        level=AssertionLevel.warning);
        checkBoundsTCon[iSta] = false;
      end when;
    end for;

if stage > 0 then
    for iSta in 1:nSta loop

    // Compute performance
    ff[iSta]=Buildings.Utilities.Math.Functions.smoothMax(
      x1=m_flow,
      x2=m_flow_small,
      deltaX=m_flow_small/10)/sta[iSta].nomVal.m_flow_nominal;
  //-------------------------Cooling capacity modifiers----------------------------//
    // Compute the DX coil capacity fractions, using a biquadratic curve.
    // Since the regression for capacity can have negative values
    // (for unreasonable temperatures), we constrain its return value to be
    // non-negative.
    cap_T[iSta] =Buildings.Utilities.Math.Functions.smoothMax(
        x1=Buildings.Utilities.Math.Functions.biquadratic(
          a=sta[iSta].perCur.capFunT,
          x1=Modelica.Units.Conversions.to_degC(TEvaIn),
          x2=Modelica.Units.Conversions.to_degC(TConIn)),
        x2=0.001,
        deltaX=0.0001)
        "Cooling capacity modification factor as function of temperature";
    cap_FF[iSta] = Buildings.Fluid.Utilities.extendedPolynomial(
      x=ff[iSta],
      c=sta[iSta].perCur.capFunFF,
      xMin=sta[iSta].perCur.ffMin,
      xMax=sta[iSta].perCur.ffMax);
    //-----------------------Energy Input Ratio modifiers--------------------------//
    EIR_T[iSta] =Buildings.Utilities.Math.Functions.smoothMax(
        x1=Buildings.Utilities.Math.Functions.biquadratic(
          a=sta[iSta].perCur.EIRFunT,
          x1=Modelica.Units.Conversions.to_degC(TEvaIn),
          x2=Modelica.Units.Conversions.to_degC(TConIn)),
        x2=0.001,
        deltaX=0.0001);
    EIR_FF[iSta] = Buildings.Fluid.Utilities.extendedPolynomial(
       x=ff[iSta],
       c=sta[iSta].perCur.EIRFunFF,
       xMin=sta[iSta].perCur.ffMin,
       xMax=sta[iSta].perCur.ffMax)
        "Cooling capacity modification factor as function of flow fraction";
    //------------ Correction factor for flow rate outside of validity of data ---//
    corFac[iSta] =Buildings.Utilities.Math.Functions.smoothHeaviside(
       x=ff[iSta] - sta[iSta].perCur.ffMin/4,
       delta=max(Modelica.Constants.eps, sta[iSta].perCur.ffMin/8));

    end for;
  else //cooling coil off
   ff     = fill(0, nSta);
   cap_T  = fill(0, nSta);
   cap_FF = fill(0, nSta);
   EIR_T  = fill(0, nSta);
   EIR_FF = fill(0, nSta);
   corFac = fill(0, nSta);
  end if;
end PartialCapacity;


Partial block for dry and wet coil conditions. This partial block is the base class for

Buildings.Fluid.DXSystems.BaseClasses.DryCoil and

Buildings.Fluid.DXSystems.Cooling.BaseClasses.WetCoil.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial block PartialCoilCondition
  "Partial block for dry and wet coil conditions"
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCoilInterface;

  constant Boolean variableSpeedCoil
    "Flag, set to true for coil with variable speed";

  replaceable
    Buildings.Fluid.DXSystems.BaseClasses.CapacityAirSource coiCap
    constrainedby
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCapacity(
      sta=datCoi.sta,
      nSta=datCoi.nSta) "Performance data"

protected
  DXSystems.Cooling.BaseClasses.SpeedShift speShiEIR(
    final variableSpeedCoil=variableSpeedCoil,
    final nSta=nSta,
    final speSet=datCoi.sta.spe) "Interpolates EIR"
  DXSystems.Cooling.BaseClasses.SpeedShift speShiQ_flow(
    final variableSpeedCoil=variableSpeedCoil,
    final nSta=nSta,
    final speSet=datCoi.sta.spe) "Interpolates Q_flow"
equation
  connect(coiCap.EIR, speShiEIR.u)
  connect(coiCap.Q_flow, speShiQ_flow.u)
  connect(speShiEIR.y, EIR)
  connect(speRat, speShiEIR.speRat)
  connect(speRat, speShiQ_flow.speRat)
  connect(speShiQ_flow.y, Q_flow)
  connect(stage, speShiQ_flow.stage)
  connect(speShiEIR.stage, stage)
  connect(coiCap.m_flow, m_flow)
  connect(coiCap.TConIn, TConIn)
  connect(coiCap.stage, stage)
end PartialCoilCondition;


Partial block for DX coil. This partial block declares the inputs and outputs that are common for

Buildings.Fluid.DXSystems.BaseClasses.DryCoil and

Buildings.Fluid.DXSystems.Cooling.BaseClasses.DXCooling.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial block PartialCoilInterface "Partial block for DX coil"
  extends Modelica.Blocks.Icons.Block;
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.EssentialParameters;

  constant Boolean use_mCon_flow "Set to true to enable connector for the condenser mass flow rate";

  Modelica.Blocks.Interfaces.IntegerInput stage
    "Stage of coil, or 0/1 for variable-speed coil"
  Modelica.Blocks.Interfaces.RealInput speRat "Speed ratio"
  Modelica.Blocks.Interfaces.RealInput m_flow "Air mass flow rate"
  Modelica.Blocks.Interfaces.RealInput TEvaIn
    "Temperature of air entering the cooling coil"
  Modelica.Blocks.Interfaces.RealInput TConIn(
    unit="K",
    displayUnit="degC")
    "Outside air dry bulb temperature for an air cooled condenser or wetbulb temperature for an evaporative cooled condenser"
  Modelica.Blocks.Interfaces.RealOutput EIR "Energy Input Ratio"
  Modelica.Blocks.Interfaces.RealOutput Q_flow(
    max=0,
    unit="W") "Total cooling capacity"

  Modelica.Blocks.Interfaces.RealInput mCon_flow if use_mCon_flow
    "Water mass flow rate at condensers for water source DX units"
end PartialCoilInterface;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial model PartialDXCoil
  "Partial model for air or water cooled DX cooling coil"
  extends Buildings.Fluid.DXSystems.Cooling.BaseClasses.EssentialParameters;
  extends Buildings.Fluid.Interfaces.TwoPortHeatMassExchanger(
    redeclare replaceable package Medium =
        Modelica.Media.Interfaces.PartialCondensingGases,
    final m_flow_nominal = datCoi.sta[nSta].nomVal.m_flow_nominal);

  constant Boolean use_mCon_flow
    "Set to true to enable connector for the condenser mass flow rate";

  parameter Boolean computeReevaporation=true
    "Set to true to compute reevaporation of water that accumulated on coil"

  Modelica.Blocks.Interfaces.RealInput TOut(
    final unit="K",
    displayUnit="degC")
    "Outside air dry bulb temperature for an air cooled condenser or wetbulb temperature for an evaporative cooled condenser"

  Modelica.Blocks.Interfaces.RealInput mCon_flow(
    final quantity="MassFlowRate",
    final unit="kg/s") if use_mCon_flow
    "Water mass flow rate for condenser"

  Modelica.Blocks.Interfaces.RealOutput P(
    final quantity="Power",
    final unit="W")
    "Electrical power consumed by the unit"

  Modelica.Blocks.Interfaces.RealOutput QSen_flow(
    final quantity="Power",
    final unit="W")
    "Sensible heat flow rate"

  replaceable Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCoilInterface dxCoi
    constrainedby
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCoilInterface(
    datCoi=datCoi,
    final use_mCon_flow=use_mCon_flow)
    "DX coil"

protected
  constant String substanceName="water"
    "Name of species substance";
  parameter Integer i_x(fixed=false)
    "Index of substance";

  // Flow reversal is not needed. Also, if ff < ffMin/4, then
  // Q_flow and EIR are set the zero. Hence, it is safe to assume
  // forward flow, which will avoid an event

  Modelica.Units.SI.SpecificEnthalpy hIn=inStream(port_a.h_outflow)
    "Enthalpy of air entering the DX coil";

  Modelica.Units.SI.Temperature TIn=Medium.temperature_phX(
    p=port_a.p,
    h=hIn,
    X=XIn)
    "Dry bulb temperature of air entering the DX coil";

  Modelica.Units.SI.MassFraction XIn[Medium.nXi]=inStream(
    port_a.Xi_outflow)
    "Mass fraction/absolute humidity of air entering the DX coil";

  Modelica.Blocks.Sources.RealExpression T(
    final y=TIn)
    "Inlet air temperature"

  Modelica.Blocks.Sources.RealExpression m(
    final y=port_a.m_flow) "Inlet air mass flow rate"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TVol
    "Temperature of the control volume"

  Buildings.HeatTransfer.Sources.PrescribedHeatFlow q
    "Heat extracted by coil"

initial algorithm
  // Make sure that |Q_flow_nominal[nSta]| >= |Q_flow_nominal[i]| for all stages because the data
  // of nSta are used in the evaporation model
  for i in 1:(nSta-1) loop
    assert(datCoi.sta[i].nomVal.Q_flow_nominal >= datCoi.sta[nSta].nomVal.Q_flow_nominal,
    "Error in DX coil performance data: Q_flow_nominal of the highest stage must have
    the biggest value in magnitude. Obtained " + Modelica.Math.Vectors.toString(
    {datCoi.sta[i].nomVal.Q_flow_nominal for i in 1:nSta}, "Q_flow_nominal"));
   end for;

  // Compute index of species vector that carries the substance name
  i_x :=-1;
    for i in 1:Medium.nXi loop
      if Modelica.Utilities.Strings.isEqual(string1=Medium.substanceNames[i],
                                            string2=substanceName,
                                            caseSensitive=false) then
        i_x :=i;
      end if;
    end for;
  assert(i_x > 0, "Substance '" + substanceName + "' is not present in medium '"
                  + Medium.mediumName + "'.\n"
                  + "Change medium model to one that has '" + substanceName + "' as a substance.");

equation
  connect(m.y,dxCoi. m_flow)

  connect(q.port, vol.heatPort)
  connect(TVol.port, q.port)

  connect(mCon_flow, dxCoi.mCon_flow)
end PartialDXCoil;


Partial model for DX cooling coil

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial model PartialDXCoolingCoil
  "Partial model for DX cooling coil"
  extends Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialDXCoil(
    redeclare Buildings.Fluid.DXSystems.Cooling.BaseClasses.DXCooling
      dxCoi(redeclare final package Medium = Medium,
      redeclare Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi),
    redeclare final Buildings.Fluid.MixingVolumes.MixingVolumeMoistAir vol(
      prescribedHeatFlowRate=true),
    redeclare Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi);

  Modelica.Blocks.Interfaces.RealOutput QLat_flow(
    final quantity="Power",
    final unit="W")
    "Latent heat flow rate"

  Buildings.Fluid.DXSystems.Cooling.BaseClasses.Evaporation watVapEva(
    redeclare final package Medium = Medium,
    nomVal=datCoi.sta[nSta].nomVal,
    final computeReevaporation=computeReevaporation)
    "Model that computes evaporation of water that accumulated on the coil surface"

protected
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.InputPower pwr
    "Electrical power consumed by the unit"

  Modelica.Blocks.Sources.RealExpression X(
    final y=XIn[i_x])
    "Inlet air mass fraction"

  Modelica.Blocks.Sources.RealExpression h(
    final y=hIn)
    "Inlet air specific enthalpy"

  Modelica.Blocks.Sources.RealExpression p(
    final y=port_a.p)
    "Inlet air pressure"

equation
  connect(p.y,dxCoi.p)
  connect(dxCoi.SHR, pwr.SHR)
  connect(dxCoi.mWat_flow, watVapEva.mWat_flow)
  connect(pwr.QLat_flow, QLat_flow)
  connect(X.y,dxCoi.XEvaIn)
  connect(h.y,dxCoi.hEvaIn)
  connect(T.y,dxCoi.TEvaIn)
  connect(vol.X_w, watVapEva.XEvaOut)
  connect(TOut,dxCoi.TConIn)
  connect(watVapEva.mTotWat_flow, vol.mWat_flow)
  connect(pwr.P, P)
  connect(pwr.QSen_flow, QSen_flow)
  connect(dxCoi.Q_flow, q.Q_flow)
  connect(T.y, watVapEva.TEvaOut)
  connect(m.y, watVapEva.mAir_flow)
  connect(dxCoi.EIR, pwr.EIR)
  connect(dxCoi.Q_flow, pwr.Q_flow)
end PartialDXCoolingCoil;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
partial block PartialSurfaceCondition
  "Partial block for apparatus dew and dry point calculation"
  extends Modelica.Blocks.Icons.Block;
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.EssentialParameters;
  replaceable package Medium =
      Modelica.Media.Interfaces.PartialCondensingGases "Medium model"

  constant Boolean variableSpeedCoil "Flag, set to true to interpolate data";

  final parameter Modelica.Units.SI.MassFlowRate m_flow_small=datCoi.m_flow_small
    "Small mass flow rate for the evaporator, used for regularization";
  final parameter Modelica.Units.SI.AngularVelocity maxSpe(displayUnit="1/min")=
       datCoi.sta[nSta].spe "Maximum rotational speed";
  Modelica.Blocks.Interfaces.RealInput speRat "Speed index"
  Modelica.Blocks.Interfaces.RealInput Q_flow(
    quantity="Power",
    unit="W") "Cooling capacity of the coil"
  Modelica.Blocks.Interfaces.RealInput m_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Evaporator air mass flow rate"
  Modelica.Blocks.Interfaces.RealInput p(
    quantity="Pressure",
    unit="Pa") "Evaporator air static pressure"
  Modelica.Blocks.Interfaces.RealInput XEvaIn
    "Evaporator inlet air mass fraction"                         //(start=0.005, min=0, max=1.0)
  Modelica.Blocks.Interfaces.RealInput hEvaIn(
    quantity="SpecificEnergy",
    unit="J/kg") "Evaporator air inlet specific enthalpy"

  Modelica.Blocks.Interfaces.IntegerInput stage
    "Stage of coil, or 0/1 for variable-speed coil"

  output Real bypass(
    start=0.25,
    min=0,
    max=1.0) "Bypass factor";
  output Modelica.Units.SI.AngularVelocity spe(displayUnit="1/min")
    "Rotational speed";
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.UACp uacp[nSta](
      per=datCoi.sta.nomVal,
      redeclare final package Medium = Medium) "Calculates UA/Cp of the coil"

protected
  output Modelica.Units.SI.MassFlowRate m_flow_nonzero
    "Evaporator air mass flow rate, bounded away from zero";
  output Modelica.Units.SI.SpecificEnthalpy delta_h(start=40000, min=0.0)
    "Enthalpy required to be removed from the inlet air to attain apparatus dry point condition";
  output Real UAcp(
    min=0,
    fixed=false) "UA/Cp of coil";

equation
  if variableSpeedCoil or stage <> 0 then
    // Small mass flow rate to avoid division by zero
    m_flow_nonzero = Buildings.Utilities.Math.Functions.smoothMax(
      x1=m_flow,
      x2=m_flow_small,
      deltaX=0.1*m_flow_small);
    spe = speRat*maxSpe;

    UAcp = if variableSpeedCoil
      then Buildings.Utilities.Math.Functions.smoothMax(
        x1=Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.speedShift(
             spe=spe,
             speSet={datCoi.sta[iSpe].spe for iSpe in 1:nSta},
             u={uacp[iSpe].UAcp for iSpe in 1:nSta}),
             x2=uacp[nSta].UAcp/1E3,
             deltaX=uacp[nSta].UAcp/1E4)
      else uacp[stage].UAcp;

    bypass = Buildings.Utilities.Math.Functions.smoothLimit(
      x = Modelica.Math.exp(-UAcp / m_flow_nonzero),
      l = 0.01,
      u = 0.99,
      deltaX = 0.001);
   delta_h = Buildings.Utilities.Math.Functions.smoothMin(
      x1=-Q_flow/m_flow_nonzero/(1 - bypass),
      x2=0.999*hEvaIn,
      deltaX=0.0001);
  else
    m_flow_nonzero = 0;
    spe            = 0;
    UAcp           = 0;
    bypass         = 0;
    delta_h        = 0;
  end if;
end PartialSurfaceCondition;


Base class for water source DX coils

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
model PartialWaterCooledDXCoil "Base class for water source DX coils"
  extends Buildings.BaseClasses.BaseIcon;
  extends Buildings.Fluid.DXSystems.Cooling.BaseClasses.EssentialParameters(
      redeclare Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi);

  replaceable package MediumEva =
      Modelica.Media.Interfaces.PartialMedium "Medium for evaporator"
  replaceable package MediumCon =
      Modelica.Media.Interfaces.PartialMedium "Medium for condenser"

  constant Boolean homotopyInitialization = true "= true, use homotopy method"

  parameter Boolean allowFlowReversalEva = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for evaporator"
  parameter Boolean allowFlowReversalCon = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal for condenser"

  parameter Modelica.Units.SI.PressureDifference dpEva_nominal(displayUnit="Pa")
    "Pressure difference over evaporator at nominal flow rate"
  parameter Modelica.Units.SI.PressureDifference dpCon_nominal(displayUnit="Pa")
    "Pressure difference over condenser at nominal flow rate"

  parameter Boolean from_dpEva=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Boolean from_dpCon=false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"

  parameter Boolean linearizeFlowResistanceEva=false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Boolean linearizeFlowResistanceCon=false
    "= true, use linear relation between m_flow and dp for any flow rate"

  parameter Real deltaMEva(final unit="1")=0.1
    "Fraction of nominal flow rate where flow transitions to laminar"
  parameter Real deltaMCon(final unit="1")=0.1
    "Fraction of nominal flow rate where flow transitions to laminar"

  parameter Modelica.Units.SI.Time tauEva=60
    "Time constant at nominal flow rate (used if energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState)"
  parameter Modelica.Units.SI.Time tauCon=60
    "Time constant at nominal flow rate (used if energyDynamics <> Modelica.Fluid.Types.Dynamics.SteadyState)"

  parameter Boolean computeReevaporation=true
    "Set to true to compute reevaporation of water that accumulated on coil";

  // Initialization
  parameter MediumEva.AbsolutePressure pEva_start = MediumEva.p_default
    "Start value of pressure"
  parameter MediumEva.Temperature TEva_start = MediumEva.T_default
    "Start value of temperature"
  parameter MediumEva.MassFraction XEva_start[MediumEva.nX] = MediumEva.X_default
    "Start value of mass fractions m_i/m"
  parameter MediumEva.ExtraProperty CEva_start[MediumEva.nC](
    final quantity=MediumEva.extraPropertiesNames)=fill(0, MediumEva.nC)
    "Start value of trace substances"
  parameter MediumEva.ExtraProperty CEva_nominal[MediumEva.nC](
    final quantity=MediumEva.extraPropertiesNames) = fill(1E-2, MediumEva.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"

  parameter MediumCon.AbsolutePressure pCon_start = MediumCon.p_default
    "Start value of pressure"
  parameter MediumCon.Temperature TCon_start = MediumCon.T_default
    "Start value of temperature"
  parameter MediumCon.MassFraction XCon_start[MediumCon.nX] = MediumCon.X_default
    "Start value of mass fractions m_i/m"
  parameter MediumCon.ExtraProperty CCon_start[MediumCon.nC](
    final quantity=MediumCon.extraPropertiesNames)=fill(0, MediumCon.nC)
    "Start value of trace substances"
  parameter MediumCon.ExtraProperty CCon_nominal[MediumCon.nC](
    final quantity=MediumCon.extraPropertiesNames) = fill(1E-2, MediumCon.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"

  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"

  // Diagnostics
  parameter Boolean show_T = false
    "= true, if actual temperature at port is computed"

  Modelica.Blocks.Interfaces.RealOutput P(quantity="Power", unit="W")
    "Electrical power consumed by the unit"
  Modelica.Blocks.Interfaces.RealOutput QEvaSen_flow(quantity="Power", unit="W")
    "Sensible heat flow rate in evaporators"
  Modelica.Blocks.Interfaces.RealOutput QEvaLat_flow(quantity="Power", unit="W")
    "Latent heat flow rate in evaporators"

  // Ports
  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare final package Medium = MediumEva,
    m_flow(min=if allowFlowReversalEva then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumEva.h_default))
    "Fluid connector for evaporator inlet (positive design flow direction is from port_a1 to port_b1)"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(
    redeclare final package Medium = MediumEva,
    m_flow(max=if allowFlowReversalEva then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumEva.h_default))
    "Fluid connector b1 (positive design flow direction is from port_a1 to port_b1)"

  Modelica.Fluid.Interfaces.FluidPort_a portCon_a(
    redeclare final package Medium = MediumCon,
    m_flow(min=if allowFlowReversalCon then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumCon.h_default))
    "Fluid connector a of condenser (positive design flow direction is from port_a2 to port_b2)"
  Modelica.Fluid.Interfaces.FluidPort_b portCon_b(
    redeclare final package Medium = MediumCon,
    m_flow(max=if allowFlowReversalCon then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumCon.h_default))
    "Fluid connector b of condenser (positive design flow direction is from port_a2 to port_b2)"

  // Components
  replaceable Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialDXCoolingCoil eva
    constrainedby
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialDXCoolingCoil(
      redeclare final package Medium = MediumEva,
      redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi=datCoi,
      dxCoi(
      redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi=datCoi,
      wetCoi(redeclare final Buildings.Fluid.DXSystems.Cooling.BaseClasses.CapacityWaterCooled coiCap,
        redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi=datCoi,
        appDewPt(
          redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi=datCoi,
          uacp(redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.BaseClasses.NominalValues per))),
      dryCoi(
        redeclare final Buildings.Fluid.DXSystems.Cooling.BaseClasses.CapacityWaterCooled coiCap,
        redeclare final Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.DXCoil datCoi=datCoi)),
      final use_mCon_flow=true,
      final dp_nominal=dpEva_nominal,
      final allowFlowReversal=allowFlowReversalEva,
      final show_T=false,
      final from_dp=from_dpEva,
      final linearizeFlowResistance=linearizeFlowResistanceEva,
      final deltaM=deltaMEva,
      final m_flow_small=mEva_flow_small,
      final tau=tauEva,
      final homotopyInitialization=homotopyInitialization,
      final energyDynamics=energyDynamics,
      final p_start=pEva_start,
      final T_start=TEva_start,
      final X_start=XEva_start,
      final C_start=CEva_start,
      final computeReevaporation=computeReevaporation,
      watVapEva(
        nomVal=Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=datCoi.sta[nSta].nomVal.Q_flow_nominal,
          COP_nominal=datCoi.sta[nSta].nomVal.COP_nominal,
          SHR_nominal=datCoi.sta[nSta].nomVal.SHR_nominal,
          m_flow_nominal=datCoi.sta[nSta].nomVal.m_flow_nominal,
          TEvaIn_nominal=datCoi.sta[nSta].nomVal.TEvaIn_nominal,
          TConIn_nominal=datCoi.sta[nSta].nomVal.TConIn_nominal,
          phiIn_nominal=datCoi.sta[nSta].nomVal.phiIn_nominal,
          p_nominal=datCoi.sta[nSta].nomVal.p_nominal,
          tWet=datCoi.sta[nSta].nomVal.tWet,
          gamma=datCoi.sta[nSta].nomVal.gamma)))
      "Direct evaporative coil"

  Buildings.Fluid.HeatExchangers.HeaterCooler_u watCooCon(
    redeclare package Medium=MediumCon,
    final m_flow_nominal = datCoi.sta[nSta].nomVal.mCon_flow_nominal,
    final Q_flow_nominal=-datCoi.sta[nSta].nomVal.Q_flow_nominal*(1+1/datCoi.sta[nSta].nomVal.COP_nominal),
    final allowFlowReversal=allowFlowReversalCon,
    final show_T=false,
    final from_dp=from_dpCon,
    final linearizeFlowResistance=linearizeFlowResistanceCon,
    final dp_nominal = dpCon_nominal,
    final deltaM=deltaMCon,
    final m_flow_small=mCon_flow_small,
    final tau=tauCon,
    final homotopyInitialization=homotopyInitialization,
    final energyDynamics=energyDynamics,
    final p_start=pCon_start,
    final T_start=TCon_start,
    final X_start=XCon_start,
    final C_start=CCon_start)
    "Water source condenser"

  // Variables
  Modelica.Units.SI.Temperature TConEnt=MediumCon.temperature(
      MediumCon.setState_phX(portCon_a.p, inStream(portCon_a.h_outflow)))
    "Temperature of fluid entering the condenser";

  MediumEva.ThermodynamicState sta_a1=MediumEva.setState_phX(
      port_a.p,
      noEvent(actualStream(port_a.h_outflow)),
      noEvent(actualStream(port_a.Xi_outflow))) if show_T
    "Medium properties in port_a1";
  MediumEva.ThermodynamicState sta_b1=MediumEva.setState_phX(
      port_b.p,
      noEvent(actualStream(port_b.h_outflow)),
      noEvent(actualStream(port_b.Xi_outflow))) if show_T
    "Medium properties in port_b1";
  MediumCon.ThermodynamicState sta_a2=MediumCon.setState_phX(
      portCon_a.p,
      noEvent(actualStream(portCon_a.h_outflow)),
      noEvent(actualStream(portCon_a.Xi_outflow))) if show_T
    "Medium properties in port_a2";
  MediumCon.ThermodynamicState sta_b2=MediumCon.setState_phX(
      portCon_b.p,
      noEvent(actualStream(portCon_b.h_outflow)),
      noEvent(actualStream(portCon_b.Xi_outflow))) if show_T
    "Medium properties in port_b2";

protected
  final parameter MediumEva.MassFlowRate mEva_flow_small(min=0) = datCoi.m_flow_small
    "Small mass flow rate for regularization of zero flow at evaporator"
  parameter MediumCon.MassFlowRate mCon_flow_small(min=0) = 1E-4*abs(datCoi.sta[nSta].nomVal.mCon_flow_nominal)
    "Small mass flow rate for regularization of zero flow at condenser"

  Modelica.Blocks.Sources.RealExpression u(final y=(-eva.dxCoi.Q_flow + eva.P)/(
        -datCoi.sta[nSta].nomVal.Q_flow_nominal*(1 + 1/datCoi.sta[nSta].nomVal.COP_nominal)))
    "Signal of total heat flow removed by condenser"

  Sensors.MassFlowRate senMasFloCon(redeclare final package Medium = MediumCon)
    "Mass flow through condenser"

  Modelica.Blocks.Sources.RealExpression TConEntWat(final y=TConEnt)
    "Temperature of water entering condenser"

initial equation
  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);

equation
  connect(u.y, watCooCon.u)
  connect(eva.port_b, port_b)
  connect(eva.port_a, port_a)
  connect(watCooCon.port_b, portCon_b)
  connect(eva.P, P)
  connect(eva.QSen_flow, QEvaSen_flow)
  connect(eva.QLat_flow, QEvaLat_flow)
  connect(watCooCon.port_a, senMasFloCon.port_b)
  connect(senMasFloCon.m_flow, eva.mCon_flow)
  connect(TConEntWat.y, eva.TOut)
  connect(portCon_a, senMasFloCon.port_a)
end PartialWaterCooledDXCoil;


Calculates the sensible heat ratio

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block SensibleHeatRatio "Calculates the sensible heat ratio"
  extends Modelica.Blocks.Icons.Block;
  replaceable package Medium =
      Modelica.Media.Interfaces.PartialCondensingGases "Medium model"
  Modelica.Blocks.Interfaces.BooleanInput on
    "Set to true to enable compressor, or false to disable compressor"
  Modelica.Blocks.Interfaces.RealInput p "Pressure at inlet of coil"
  Modelica.Blocks.Interfaces.RealInput TEvaIn
    "Temperature of air entering the cooling coil"
  Modelica.Blocks.Interfaces.RealInput XADP(
    min=0,
    max=1.0) "Humidity mass fraction of air at ADP"
  Modelica.Blocks.Interfaces.RealInput hADP(
    nominal=40000,
    quantity="SpecificEnergy",
    unit="J/kg") "Specific enthalpy of air at ADP"
  Modelica.Blocks.Interfaces.RealInput hEvaIn
    "Specific enthalpy of air entering the coil"
  Modelica.Blocks.Interfaces.RealOutput SHR(
    min=0,
    max=1.0)
    "Sensible Heat Ratio: Ratio of sensible heat load to total heat load"

protected
  Modelica.Units.SI.SpecificEnthalpy h_TEvaIn_XADP
    "Enthalpy at inlet air temperature and humidity mass fraction at ADP";
  Real entRat "Enthalpy ratio";
  parameter Modelica.Units.SI.SpecificEnthalpy epsH=100
    "Small value for enthalpy to avoid division by zero";
equation
//===================================Sensible heat ratio calculation===========================================//
  //Coil on-off condition
  if on then
   //Calculate enthalpy at inlet air temperature and absolute humidity at ADP i.e. h_TEvaIn_wADP
    h_TEvaIn_XADP = Medium.specificEnthalpy_pTX(
      p=p,
      T=TEvaIn,
      X=cat(1, {XADP}, {1-XADP}));
    //Calculate Sensible Heat Ratio
    entRat = (h_TEvaIn_XADP - hADP)/
      Buildings.Utilities.Math.Functions.smoothMax(
        x1 =     epsH,
        x2 =     hEvaIn - hADP,
        deltaX = 0.1*epsH);
    SHR = Buildings.Utilities.Math.Functions.smoothMin(
      x1=entRat,
      x2=0.999,
      deltaX=0.0001)
      "To restrict the value of SHR in case of zero mass flow rate or dry coil condition";
  else  //Coil off
    h_TEvaIn_XADP = 0;
    entRat        = 1;
    SHR           = 0;
  end if;
end SensibleHeatRatio;


Selects the lower specified speed ratio for multispeed model. This blocks outputs the normalized speed of the compressor,
whereas the highest stage is assigned a normalized speed of one,
and all other stages are proportional to their actual speed.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block SpeedSelect
  "Selects the lower specified speed ratio for multispeed model"
  extends Modelica.Blocks.Icons.Block;

  parameter Integer nSta(min=1) "Number of standard compressor speeds";
  parameter Real speSet[nSta] "Array of standard compressor speeds";
  Modelica.Blocks.Interfaces.IntegerInput stage
    "Stage of cooling coil (0: off, 1: first stage, 2: second stage...)"
  Modelica.Blocks.Interfaces.RealOutput speRat "Standard speed ratio"
protected
  final parameter Real speRatNor[nSta](
    each min=0,
    each max=1)={speSet[i]/speSet[nSta] for i in 1:nSta}
    "Array of normalized speed ratios for the compressor";

equation
 assert(stage >= 0 and stage <= nSta, "Compressor speed is out of range.
  Model has " + String(nSta) + " speeds, but received control signal " +
  String(stage));
 speRat =if stage == 0 then 0 else speRatNor[stage];
end SpeedSelect;


Interpolates values between speeds. This block uses the

Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.speedShift function
to interpolate the input array.
Depending on input speed ratio and speed set array the input array u is interpolated.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
block SpeedShift "Interpolates values between speeds"
  parameter Integer nSta "Number of standard compressor speeds";
  parameter Modelica.Units.SI.AngularVelocity speSet[nSta](each displayUnit=
        "1/min") "Compressor speeds";
  constant Boolean variableSpeedCoil "Flag, set to true to interpolate data";

  Modelica.Blocks.Interfaces.RealInput speRat "Speed ratio"
  Modelica.Blocks.Interfaces.RealInput u[nSta] "Array to be interpolated"
  Modelica.Blocks.Interfaces.RealOutput y "Interpolated value"
  Modelica.Blocks.Interfaces.IntegerInput stage
    "Stage of coil, or 0/1 for variable-speed coil"
equation
  if variableSpeedCoil then
    y=Buildings.Fluid.DXSystems.Cooling.BaseClasses.Functions.speedShift(
      spe=speRat*speSet[nSta],
      speSet=speSet,
      u=u);
  else
    y = if stage == 0 then 0  else u[stage];
  end if;
end SpeedShift;


Calculates UA/Cp of the coil

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
model UACp "Calculates UA/Cp of the coil"
  extends Modelica.Blocks.Icons.Block;

  constant Boolean homotopyInitialization = true "= true, use homotopy method"

  replaceable package Medium = Buildings.Media.Air constrainedby
    Modelica.Media.Interfaces.PartialCondensingGases "Medium model"
  replaceable parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues per
     constrainedby
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues
     "Performance data"

  final parameter Modelica.Units.SI.MassFraction XEvaIn_nominal=
      Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
      pSat=Medium.saturationPressure(per.TEvaIn_nominal),
      p=per.p_nominal,
      phi=per.phiIn_nominal) "Rated/Nominal mass fraction of air entering coil";
  final parameter Modelica.Units.SI.SpecificEnthalpy hEvaIn_nominal=
      Medium.specificEnthalpy_pTX(
      p=per.p_nominal,
      T=per.TEvaIn_nominal,
      X=cat(
        1,
        {XEvaIn_nominal},
        {1 - sum({XEvaIn_nominal})}))
    "Rated enthalpy of air entering cooling coil";
  final parameter Modelica.Units.SI.SpecificEnthalpy hOut_nominal=
      hEvaIn_nominal + per.Q_flow_nominal/per.m_flow_nominal
    "Rated enthalpy of air exiting cooling coil";
  final parameter Modelica.Units.SI.Temperature TOut_nominal=per.TEvaIn_nominal
       + (per.SHR_nominal*per.Q_flow_nominal)/(per.m_flow_nominal*Cp_nominal)
    "Dry-bulb temperature of the air leaving the cooling coil at nominal condition";
  final parameter Modelica.Units.SI.MassFraction XEvaOut_nominal(
    start=0.005,
    min=0,
    max=1.0) = XEvaIn_nominal + (hOut_nominal - hEvaIn_nominal)*(1 - per.SHR_nominal)
    /Medium.enthalpyOfCondensingGas(T=per.TEvaIn_nominal)
    "Rated/Nominal mass fraction of air leaving the coil";
  final parameter Modelica.Units.SI.SpecificHeatCapacity Cp_nominal=
      Medium.specificHeatCapacityCp(Medium.setState_pTX(
      p=per.p_nominal,
      T=per.TEvaIn_nominal,
      X=cat(
        1,
        {XEvaIn_nominal},
        {1 - sum({XEvaIn_nominal})})))
    "Specific heat of air at specified nominal condition"

  final parameter Modelica.Units.SI.MassFraction XADP_nominal(
    start=0.008,
    min=0,
    max=1.0,
    fixed=false)
    "Rated/Nominal mass fraction of air at coil apparatus dew point";
  final parameter Modelica.Units.SI.Temperature TADP_nominal(start=273.15 + 10,
      fixed=false) "Coil apparatus dew point temperature";
  final parameter Modelica.Units.SI.SpecificEnthalpy hADP_nominal(fixed=false)
    "Enthalpy of air at coil apparatus dew point (at rated condition)";
  final parameter Real bypass_nominal(
    start=0.25,
    min=0,
    max=1.0,
    fixed=false) "Bypass factor for nominal condition";
  final parameter Real UAcp(
    min=0,
    unit="kg/s",
    fixed=false) "UA/Cp of coil";

protected
  constant Real phiADP_nominal = 1.0 "Realtive humidity at ADP";
  final parameter Modelica.Units.SI.AbsolutePressure psat_ADP_nominal(start=
        1250, fixed=false) "Saturation pressure";

initial equation
//------------------------Apparatus Dew Point (ADP) calculations---------------------//
  //Solve Eq. 1 , 2 and 3 for air properties (XADP_nominal and TADP_nominal)
  //of saturated air at coil apparatus dew point
//---------------------------------------Eq.1---------------------------------------//
  (XEvaIn_nominal - XEvaOut_nominal)*(per.TEvaIn_nominal - TADP_nominal)
     =(XEvaIn_nominal  - XADP_nominal)*(per.TEvaIn_nominal - TOut_nominal);
//---------------------------------------Eq.2---------------------------------------//
  if homotopyInitialization then
    psat_ADP_nominal=homotopy(
      actual=Buildings.Utilities.Psychrometrics.Functions.saturationPressureLiquid(TADP_nominal),
      simplified=1252.393+83.933*(TADP_nominal-283.15));
  else // do not use homotopy
    psat_ADP_nominal=Buildings.Utilities.Psychrometrics.Functions.saturationPressureLiquid(TADP_nominal);
  end if;
  //  Taylor series
  //  psat_ADP_nominal=1252.393+83.933*(TADP_nominal-283.15);
  //  Non-linear equation
  //  psat_ADP_nominal =  Buildings.Utilities.Psychrometrics.Functions.saturationPressureLiquid(TADP_nominal);
//---------------------------------------Eq.3---------------------------------------//
  if homotopyInitialization then
    XADP_nominal=homotopy(
      actual=Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
        pSat=psat_ADP_nominal,
        p=per.p_nominal,
        phi=phiADP_nominal),
      simplified=0.007572544+6.19495*(10^(-6))*(psat_ADP_nominal-1228));

  else // do not use homotopy
    XADP_nominal=Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
        pSat=psat_ADP_nominal,
        p=per.p_nominal,
        phi=phiADP_nominal);
  end if;
//-----------------------------------uACp calculations-----------------------------//
  hADP_nominal = Medium.specificEnthalpy_pTX(
              p=per.p_nominal,
              T=TADP_nominal,
              X=cat(1,{XADP_nominal}, {1-sum({XADP_nominal})}));
  bypass_nominal=Buildings.Utilities.Math.Functions.smoothLimit(
              x=(hOut_nominal-hADP_nominal)/(hEvaIn_nominal-hADP_nominal),
              l=1e-3,
              u=0.999,
              deltaX=1e-4);
  UAcp = -per.m_flow_nominal * Modelica.Math.log(bypass_nominal);

  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);
end UACp;


Calculates wet coil condition

within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
model WetCoil "Calculates wet coil condition "
  extends
    Buildings.Fluid.DXSystems.Cooling.BaseClasses.PartialCoilCondition;
  replaceable package Medium =
      Modelica.Media.Interfaces.PartialCondensingGases "Medium model"
  Modelica.Blocks.Interfaces.RealOutput TADP(
    quantity="ThermodynamicTemperature",
    unit="K",
    start=288.15,
    min=273.15,
    max=373.15) "Dry bulb temperature of air at ADP"
  Modelica.Blocks.Interfaces.RealOutput SHR(
    min=0,
    max=1.0)
    "Sensible Heat Ratio: Ratio of sensible heat load to total heat load"
  Modelica.Blocks.Interfaces.RealOutput mWat_flow(
    quantity="MassFlowRate",
    unit="kg/s") "Mass flow rate of water condensed at cooling coil"

  Buildings.Utilities.Psychrometrics.TWetBul_TDryBulXi wetBul(
    redeclare package Medium = Medium) "Calculates wet-bulb temperature"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.ApparatusDewPoint appDewPt(
    redeclare package Medium = Medium,
    datCoi=datCoi,
    final variableSpeedCoil=variableSpeedCoil)
    "Calculates air properties at apparatus dew point (ADP) at existing air-flow conditions"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.SensibleHeatRatio shr(
    redeclare package Medium = Medium) "Calculates sensible heat ratio"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.Condensation conRat
   "Calculates rate of condensation"
protected
  Modelica.Blocks.Math.IntegerToBoolean onSwi(final threshold=1)
    "On/off switch"
public
  Modelica.Blocks.Interfaces.RealOutput XADP
    "Humidity mass fraction of air at  apparatus dew point"
  Modelica.Blocks.Interfaces.RealInput XEvaIn "Inlet air mass fraction"
  Modelica.Blocks.Interfaces.RealInput p "Pressure at inlet of coil"
  Modelica.Blocks.Interfaces.RealInput hEvaIn
    "Specific enthalpy of air entering the coil"
equation

  connect(appDewPt.TADP, TADP)
  connect(XEvaIn, appDewPt.XEvaIn)
  connect(p, appDewPt.p)
  connect(m_flow, appDewPt.m_flow)
  connect(p, wetBul.p)
  connect(XEvaIn, wetBul.Xi[1])
  connect(speRat, appDewPt.speRat)
  connect(appDewPt.XADP, shr.XADP)
  connect(appDewPt.hADP, shr.hADP)
  connect(shr.SHR, SHR)
  connect(p, shr.p)
  connect(TEvaIn, wetBul.TDryBul)
  connect(TEvaIn, shr.TEvaIn)
  connect(hEvaIn, shr.hEvaIn)
  connect(hEvaIn, appDewPt.hEvaIn)
  connect(conRat.mWat_flow, mWat_flow)
  connect(shr.SHR, conRat.SHR)
  connect(speShiQ_flow.y, conRat.Q_flow)
  connect(speShiQ_flow.y, appDewPt.Q_flow)
  connect(onSwi.y, shr.on)
  connect(onSwi.u, stage)
  connect(wetBul.TWetBul,coiCap.TEvaIn)
  connect(appDewPt.XADP, XADP)
  connect(appDewPt.stage, stage)
  connect(mCon_flow,coiCap.mCon_flow)
end WetCoil;


Test model for ApparatusDewPoint

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model ApparatusDewPoint "Test model for ApparatusDewPoint"
  extends Modelica.Icons.Example;
  parameter Integer nSta=4 "Number of standard compressor speeds";
  package Medium =
      Buildings.Media.Air;
  parameter Real minSpeRat(min=0,max=1) = 0.2 "Minimum speed ratio";
  parameter Real speRatDeaBan= 0.05 "Deadband for minimum speed ratio";
  Modelica.Blocks.Sources.Constant p(
    k=101325) "Pressure"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.ApparatusDewPoint adp(
    redeclare package Medium = Medium,
    datCoi=datCoi,
    variableSpeedCoil=true)
    "Calculates air properties at apparatus dew point condition"
  Modelica.Blocks.Sources.Ramp m_flow(
    duration=600,
    height=1.35,
    startTime=600) "Mass flow rate of air"
  Modelica.Blocks.Sources.Ramp XEvaIn(
    duration=600,
    height=0.004,
    startTime=1800,
    offset=0.011) "Inlet air mass fraction"
  Modelica.Blocks.Sources.Ramp Q_flow(
    duration=600,
    startTime=600,
    height=-20000) "Cooling rate"
  Modelica.Blocks.Sources.TimeTable speRat(
    offset=0,
    startTime=0,
    table=[0.0,0.00; 600,0.25; 1800,0.5; 2700,0.75]) "Speed ratio "
  parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi(nSta=4, sta={
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=900/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-12000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=0.9),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1200/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-18000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.2),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1800/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-21000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.5),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_II_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=2400/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-30000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.8),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_III_AirCooled())})
    "Coil data"
protected
  Modelica.Blocks.Logical.Hysteresis deaBan(
     uLow=minSpeRat - speRatDeaBan/2,
     uHigh=minSpeRat + speRatDeaBan/2) "Speed ratio deadband"
  Modelica.Blocks.Math.BooleanToInteger onSwi(
    final integerTrue=1,
    final integerFalse=0) "On/off switch"
public
  Modelica.Blocks.Sources.Constant hEvaIn(k=Medium.specificEnthalpy(
        Medium.setState_pTX(
        p=101325,
        T=30 + 273.15,
        X={0.015}))) "Air enthalpy at inlet"
equation
  connect(Q_flow.y, adp.Q_flow)
  connect(p.y, adp.p)
  connect(m_flow.y, adp.m_flow)
  connect(XEvaIn.y, adp.XEvaIn)
  connect(speRat.y, adp.speRat)
  connect(speRat.y, deaBan.u)
  connect(deaBan.y, onSwi.u)
  connect(onSwi.y, adp.stage)
  connect(hEvaIn.y, adp.hEvaIn)
end ApparatusDewPoint;


Test model for ApparatusDryPoint

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model ApparatusDryPoint "Test model for ApparatusDryPoint"
  extends Modelica.Icons.Example;
  parameter Integer nSta=4;
  package Medium =
      Buildings.Media.Air;
  parameter Real minSpeRat(min=0,max=1) = 0.2 "Minimum speed ratio";
  parameter Real speRatDeaBan= 0.05 "Deadband for minimum speed ratio";
  Modelica.Blocks.Sources.Constant p(
    k=101325) "Pressure"
  Modelica.Blocks.Sources.Constant hEvaIn(k=Medium.specificEnthalpy(
        Medium.setState_pTX(
        p=101325,
        T=30 + 273.15,
        X={0.015}))) "Air enthalpy at inlet"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.ApparatusDryPoint appDryPt(
    redeclare package Medium = Medium,
    datCoi=datCoi,
    variableSpeedCoil=true) "Dry point condition"
  Modelica.Blocks.Sources.Ramp m_flow(
    duration=600,
    height=1.35,
    startTime=900) "Mass flow rate of air"
  Modelica.Blocks.Sources.Ramp Q_flow(
    duration=600,
    height=-20000,
    offset=-2,
    startTime=900) "Heat extracted from air"
  Modelica.Blocks.Sources.TimeTable speRat(
    table=[0.0,0.0; 900,0.25; 1800,0.50; 2700,0.75],
    offset=0.25,
    startTime=900) "Speed ratio "
  parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi(
    nSta=4,
    sta={
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=900/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-12000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=0.9),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1200/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-18000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.2),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1800/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-21000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.5),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_II_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=2400/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-30000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.8),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_III_AirCooled())})
    "Coil data"
protected
  Modelica.Blocks.Logical.Hysteresis deaBan(
     uLow=minSpeRat - speRatDeaBan/2,
     uHigh=minSpeRat + speRatDeaBan/2) "Speed ratio deadband"
  Modelica.Blocks.Math.BooleanToInteger onSwi(
    final integerTrue=1,
    final integerFalse=0) "On/off switch"
public
  Modelica.Blocks.Sources.Ramp XEvaIn(
    duration=600,
    height=0.004,
    startTime=1800,
    offset=0.011) "Inlet air mass fraction"
equation
  connect(p.y, appDryPt.p)
  connect(hEvaIn.y, appDryPt.hEvaIn)
  connect(m_flow.y, appDryPt.m_flow)
  connect(Q_flow.y, appDryPt.Q_flow)
  connect(speRat.y, appDryPt.speRat)
  connect(speRat.y,deaBan. u)
  connect(deaBan.y,onSwi. u)
  connect(onSwi.y, appDryPt.stage)
  connect(XEvaIn.y, appDryPt.XEvaIn)
end ApparatusDryPoint;


Test model for Condensation block

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model Condensation "Test model for Condensation block"
 package Medium =
      Buildings.Media.Air;
 extends Modelica.Icons.Example;
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.Condensation mWat
   "Calculates rate of condensation"
  Modelica.Blocks.Sources.Ramp Q_flow(
    height=-20000,
    startTime=600,
    offset=0,
    duration=2400) "Heat flow"
  Modelica.Blocks.Sources.Ramp shr(
    startTime=1800,
    height=1,
    offset=0,
    duration=1200) "Sensible heat ratio"
equation

  connect(Q_flow.y, mWat.Q_flow)
  connect(shr.y, mWat.SHR)
end Condensation;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model CoolingCapacityWaterCooled "Test model for CoolingCapacityWaterCooled"

  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Air;
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.CapacityWaterCooled
    cooCap(sta={sta},
    nSta=1) "Cooling capacity calculation"
  Modelica.Blocks.Sources.Ramp m_flow(
    duration=2400,
    startTime=600,
    height=sta.nomVal.m_flow_nominal,
    offset=0) "Mass flow rate of air"
  Modelica.Blocks.Sources.Ramp TWetBulIn(
    duration=2400,
    startTime=600,
    height=10,
    offset=273.15 + 19.4) "Air wet bulb temperature entering the coil"
  Modelica.Blocks.Sources.IntegerStep onOff(startTime=600)
    "Compressor on-off signal"
  Modelica.Blocks.Sources.Ramp TConIn(
    duration=2400,
    startTime=600,
    height=5,
    offset=273.15 + 30)
    "Condenser inlet temperature (Outside drybulb temperature)"
  parameter
  Buildings.Fluid.DXSystems.Cooling.WaterSource.Data.Generic.BaseClasses.Stage
   sta(nomVal(
    Q_flow_nominal=-21000,COP_nominal=3,SHR_nominal=0.8,
    m_flow_nominal=1.5,mCon_flow_nominal=1),
  perCur=Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_WaterCooled(),
    spe=188.49555921539) "Performance data"

  Modelica.Blocks.Sources.Ramp mCon_flow(
    duration=2400,
    startTime=600,
    offset=0,
    height=sta.nomVal.mCon_flow_nominal)
    "Mass flow rate of water at the condenser"
equation
  connect(TConIn.y, cooCap.TConIn)
  connect(m_flow.y, cooCap.m_flow)
  connect(onOff.y, cooCap.stage)
  connect(TWetBulIn.y, cooCap.TEvaIn)
  connect(mCon_flow.y, cooCap.mCon_flow)
end CoolingCapacityWaterCooled;


Test model for DryWetSelector. This example illustrates working of DryWetSelector block

Buildings.Fluid.DXSystems.Cooling.BaseClasses.DryWetSelector.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model DryWetSelector "Test model for DryWetSelector"

extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Ramp XADP(
    duration=20,
    startTime=20,
    height=-0.002,
    offset=0.006) "Mass fraction at ADP"
  Modelica.Blocks.Sources.Ramp XEvaIn(
    startTime=20,
    height=0.002,
    offset=0.004,
    duration=20) "Inlet mass-fraction"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.DryWetSelector dryWet
    "Averages dry and wet coil conditions"
  Modelica.Blocks.Sources.Constant mWetWat_flow(k=0.01)
  Modelica.Blocks.Sources.Constant SHRWet(k=0.5)
  Modelica.Blocks.Sources.Constant QWet_flow(k=-3000)
  Modelica.Blocks.Sources.Constant EIRWet(k=0.3)
  Modelica.Blocks.Sources.Constant QDry_flow(k=-2000)
  Modelica.Blocks.Sources.Constant EIRDry(k=0.2)
equation
  connect(XEvaIn.y, dryWet.XEvaIn)
  connect(XADP.y, dryWet.XADP)
  connect(mWetWat_flow.y, dryWet.mWetWat_flow)
  connect(SHRWet.y, dryWet.SHRWet)
  connect(QWet_flow.y, dryWet.QWet_flow)
  connect(EIRWet.y, dryWet.EIRWet)
  connect(QDry_flow.y, dryWet.QDry_flow)
  connect(EIRDry.y, dryWet.EIRDry)
end DryWetSelector;


Test model for DXCooling

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model DXCooling "Test model for DXCooling"
  extends Modelica.Icons.Example;
  package Medium =
      Buildings.Media.Air;
  Modelica.Blocks.Sources.Constant p(
    k=101325) "pressure"
  Modelica.Blocks.Sources.Constant TConIn(
    k=273.15 + 35)
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.DXCooling dxCoo(
   redeclare package Medium = Medium,
   datCoi=datCoi,
   variableSpeedCoil=true,
   use_mCon_flow=false,
   wetCoi(redeclare
        Buildings.Fluid.DXSystems.BaseClasses.CapacityAirSource
        coiCap),
    dryCoi(redeclare
        Buildings.Fluid.DXSystems.BaseClasses.CapacityAirSource
        coiCap))
  Modelica.Blocks.Sources.IntegerStep onOff(
    startTime=600) "Compressor on-off signal"
  Modelica.Blocks.Sources.Ramp m_flow(
    duration=600,
    startTime=1200,
    height=1.05) "Mass flow rate of air"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    duration=600,
    startTime=2400,
    height=-5,
    offset=273.15 + 29) "Dry bulb temperature of air entering the coil"
  Modelica.Blocks.Sources.Ramp XEvaIn(
    duration=600,
    startTime=2400,
    height=-0.002,
    offset=0.012) "Inlet mass-fraction"
  Modelica.Blocks.Sources.Ramp hEvaIn(
    duration=600,
    startTime=2400,
    offset=60000,
    height=-10000) "Specific enthalpy of air entering the coil"
  Modelica.Blocks.Sources.TimeTable speRat(table=[0.0,0.0; 900,0.25; 1800,0.50;
        2700,0.75]) "Speed ratio "
  parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi(sta={
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=900/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-12000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=0.9),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1200/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-18000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.2),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1800/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-21000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.5),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=2400/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-30000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.8),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_III_AirCooled())},
      nSta=4) "Coil data"
equation
  connect(TConIn.y, dxCoo.TConIn)
  connect(p.y, dxCoo.p)
  connect(m_flow.y, dxCoo.m_flow)
  connect(TEvaIn.y, dxCoo.TEvaIn)
  connect(XEvaIn.y, dxCoo.XEvaIn)
  connect(hEvaIn.y, dxCoo.hEvaIn)
  connect(speRat.y, dxCoo.speRat)
  connect(onOff.y, dxCoo.stage)
end DXCooling;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model EvaporationFlowReversal
  "Test model for evaporation with zero flow and flow reversal"
  extends Modelica.Icons.Example;
  package Medium =Buildings.Media.Air;

  parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues
    nomVal(
    Q_flow_nominal=-5000,
    COP_nominal=3,
    SHR_nominal=0.8,
    m_flow_nominal=5000/1006/10) "Nominal values for DX coil"

  parameter Modelica.Units.SI.MassFraction XEvaIn_nominal=
      Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
      pSat=Medium.saturationPressure(nomVal.TEvaIn_nominal),
      p=nomVal.p_nominal,
      phi=nomVal.phiIn_nominal) "Mass fraction at nominal inlet conditions";

  parameter Modelica.Units.SI.MassFraction XEvaOut_nominal=XEvaIn_nominal + (1
       - nomVal.SHR_nominal)*nomVal.Q_flow_nominal/nomVal.m_flow_nominal/
      Medium.enthalpyOfVaporization(293.15) "Nominal air outlet humidity";

  Evaporation eva(redeclare package Medium = Medium, nomVal=nomVal,
    m(start=0.55, fixed=true)) "Evaporation model"
  Modelica.Blocks.Sources.BooleanConstant offSignal(k=false)
  Modelica.Blocks.Sources.TimeTable mAir_flow(table=[0,1; 300,1; 900,-1; 1200,-1;
        1500,0; 1800,0]) "Air flow rate"
  Modelica.Blocks.Sources.Constant TEva(k=nomVal.TEvaIn_nominal)
    "Inlet Temperature"
  Modelica.Blocks.Continuous.Integrator int
    "Mass of water that evaporates into air stream"
  Modelica.Blocks.Sources.Constant mWat_flow(k=0)
    "Water flow rate added into the medium from the coil model (without reevaporation flow rate)"
  Modelica.Blocks.Math.Gain gain(k=nomVal.m_flow_nominal)
  Modelica.Blocks.Sources.Constant XEvaIn(k=XEvaIn_nominal)
    "Inlet water vapor mass fraction"
equation

  connect(offSignal.y, eva.on)
  connect(mWat_flow.y, eva.mWat_flow)
  connect(mAir_flow.y, gain.u)
  connect(gain.y, eva.mAir_flow)
  connect(eva.mTotWat_flow, int.u)
  connect(XEvaIn.y, eva.XEvaOut)
  connect(TEva.y, eva.TEvaOut)
end EvaporationFlowReversal;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model EvaporationPulse "Test model for evaporation with pulse signal"
  extends Modelica.Icons.Example;
  package Medium =Buildings.Media.Air;

  parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues
    nomVal(
    Q_flow_nominal=-5000,
    COP_nominal=3,
    SHR_nominal=0.8,
    m_flow_nominal=5000/1006/10) "Nominal values for DX coil"

  parameter Modelica.Units.SI.MassFraction XEvaIn_nominal=
      Buildings.Utilities.Psychrometrics.Functions.X_pSatpphi(
      pSat=Medium.saturationPressure(nomVal.TEvaIn_nominal),
      p=nomVal.p_nominal,
      phi=nomVal.phiIn_nominal) "Mass fraction at nominal inlet conditions";

  parameter Modelica.Units.SI.MassFraction XEvaOut_nominal=XEvaIn_nominal + (1
       - nomVal.SHR_nominal)*nomVal.Q_flow_nominal/nomVal.m_flow_nominal/
      Medium.enthalpyOfVaporization(293.15) "Nominal air outlet humidity";

  Modelica.Blocks.Sources.Pulse pulSho(period=30*60)
    "Control signal for short-cycling coil"
  Evaporation evaSho(redeclare package Medium = Medium, nomVal=nomVal)
    "Evaporation model"
  Modelica.Blocks.Math.RealToBoolean realToBoolean
  Modelica.Blocks.Sources.Constant mAir_flow(k=nomVal.m_flow_nominal)
    "Air flow rate"
  Modelica.Blocks.Sources.Constant TIn(k=nomVal.TEvaIn_nominal)
    "Inlet temperature"
  Modelica.Blocks.Continuous.Integrator intSho
    "Mass of water that evaporates into air stream"
  Evaporation evaNor(redeclare package Medium = Medium, nomVal=nomVal)
    "Evaporation model"
  Modelica.Blocks.Continuous.Integrator intNor
    "Mass of water that evaporates into air stream"
  Modelica.Blocks.Sources.Pulse pulNor(period=3600)
    "Control signal for normal-cycling coil"
  Modelica.Blocks.Math.RealToBoolean realToBoolean1
  Modelica.Blocks.Math.Gain mWat_flow(k=nomVal.Q_flow_nominal*(1 - nomVal.SHR_nominal)
        /Medium.enthalpyOfVaporization(293.15))
    "Water mass flow rate from air to coil surface"
  Modelica.Blocks.Math.Gain mWat_flow1(k=nomVal.Q_flow_nominal*(1 - nomVal.SHR_nominal)
        /Medium.enthalpyOfVaporization(293.15))
    "Water mass flow rate from air to coil surface"
  Modelica.Blocks.Sources.Constant XEvaIn(k=XEvaIn_nominal)
    "Inlet water vapor mass fraction"
equation

  connect(pulSho.y, realToBoolean.u)
  connect(realToBoolean.y, evaSho.on)
  connect(evaSho.mAir_flow, mAir_flow.y)
  connect(evaNor.mAir_flow, mAir_flow.y)
  connect(pulNor.y, realToBoolean1.u)
  connect(realToBoolean1.y, evaNor.on)
  connect(pulNor.y, mWat_flow1.u)
  connect(mWat_flow1.y, evaNor.mWat_flow)
  connect(pulSho.y, mWat_flow.u)
  connect(mWat_flow.y, evaSho.mWat_flow)
  connect(XEvaIn.y, evaSho.XEvaOut)
  connect(XEvaIn.y, evaNor.XEvaOut)
  connect(evaNor.mTotWat_flow, intNor.u)
  connect(evaSho.mTotWat_flow, intSho.u)
  connect(TIn.y, evaSho.TEvaOut)
  connect(TIn.y, evaNor.TEvaOut)
end EvaporationPulse;


Test model for InputPower. This example illustrates working of InputPower block

Buildings.Fluid.DXSystems.Cooling.BaseClasses.InputPower.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model InputPower "Test model for InputPower"
extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Ramp SHR(
    height=0.5,
    duration=60,
    offset=0.5,
    startTime=0) "Sensible heat ratio"
  Modelica.Blocks.Sources.Ramp EIR(
    height=-0.083,
    duration=60,
    offset=0.333,
    startTime=0) "Energy input ratio"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.InputPower pwr
    "Calculates electrical power consumed by the unit"
  Modelica.Blocks.Sources.Ramp Q_flow(
    height=-20000,
    duration=60,
    startTime=0) "Cooling rate"
equation
  connect(EIR.y, pwr.EIR)
  connect(Q_flow.y, pwr.Q_flow)
  connect(SHR.y, pwr.SHR)
end InputPower;


within Buildings.Fluid.DXSystems.Cooling.BaseClasses;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for SensibleHeatRatio

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model SensibleHeatRatio "Test model for SensibleHeatRatio"
 extends Modelica.Icons.Example;
 package Medium =
      Buildings.Media.Air;
  Modelica.Blocks.Sources.Constant p(
    k=101325) "Pressure"
  Modelica.Blocks.Sources.BooleanStep onOff(
    startTime=600) "Compressor on-off signal"
  Modelica.Blocks.Sources.Ramp hEvaIn(
    duration=600,
    startTime=2400,
    offset=60000,
    height=-10000) "Specific enthalpy of air entering the coil"
  Modelica.Blocks.Sources.Ramp TEvaIn(
    duration=600,
    startTime=2400,
    height=-5,
    offset=273.15 + 29) "Inlet air temperature"
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.SensibleHeatRatio shr(
    redeclare package Medium = Medium)
  Modelica.Blocks.Sources.Constant XADP(k=0.01) "Mass fraction"
  Modelica.Blocks.Sources.Constant hADP(k=35000) "Specific enthalpy"
equation
  connect(onOff.y, shr.on)
  connect(hEvaIn.y, shr.hEvaIn)
  connect(TEvaIn.y, shr.TEvaIn)
  connect(p.y, shr.p)
  connect(XADP.y, shr.XADP)
  connect(hADP.y, shr.hADP)
end SensibleHeatRatio;


Test model for speed select. This example illustrates working of SpeedSelect block

Buildings.Fluid.DXSystems.Cooling.BaseClasses.SpeedSelect.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model SpeedSelect "Test model for speed select"
  extends Modelica.Icons.Example;
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.SpeedSelect speSel(
    nSta=datCoi.nSta,
    speSet=datCoi.sta.spe) "Normalizes the input speed"
  parameter
    Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil
    datCoi(nSta=4, sta={
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=900/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-12000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=0.9),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1200/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-18000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.2),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1800/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-21000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.5),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_II_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=2400/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-30000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.8),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_III_AirCooled())})
    "Coil data"
  Modelica.Blocks.Sources.IntegerTable sta(table=[0,0; 10,1; 20,2; 30,3; 40,4;
        50,0]) "Stage of compressor"
equation

  connect(sta.y, speSel.stage)
end SpeedSelect;


Test model for SpeedShift block. This example illustrates working of SpeedShift block

Buildings.Fluid.DXSystems.Cooling.BaseClasses.SpeedShift.

within Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples;
model SpeedShift "Test model for SpeedShift block"
 extends Modelica.Icons.Example;
 parameter Integer nSta=4 "Number of standard compressor speeds";
  Buildings.Fluid.DXSystems.Cooling.BaseClasses.SpeedShift speShi(
    nSta=nSta,
    speSet=datCoi.sta.spe,
    variableSpeedCoil=true)
  Modelica.Blocks.Sources.Constant u[nSta](k={10,20,30,40}) "Inputs"
  Modelica.Blocks.Sources.TimeTable speRat(table=[0.0,0.25; 900,0.50; 1800,0.50;
        2700,0.75; 3600,0.75]) "Speed ratio "
  parameter Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.DXCoil datCoi(nSta=4, sta={
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=900/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-12000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=0.9),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1200/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-18000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.2),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_I_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=1800/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-21000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.5),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_II_AirCooled()),
        Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.Stage(
        spe=2400/60,
        nomVal=
          Buildings.Fluid.DXSystems.Cooling.AirSource.Data.Generic.BaseClasses.NominalValues(
          Q_flow_nominal=-30000,
          COP_nominal=3,
          SHR_nominal=0.8,
          m_flow_nominal=1.8),
        perCur=
          Buildings.Fluid.DXSystems.Cooling.BaseClasses.Examples.PerformanceCurves.Curve_III_AirCooled())})
    "Coil data"
  Modelica.Blocks.Logical.GreaterThreshold greaterThreshold(threshold=0.1)
  Modelica.Blocks.Math.BooleanToInteger booleanToInteger
equation

  connect(u.y, speShi.u)
  connect(speRat.y, speShi.speRat)
  connect(speRat.y, greaterThreshold.u)
  connect(greaterThreshold.y, booleanToInteger.u)
  connect(booleanToInteger.y, speShi.stage)
end SpeedShift;