within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model HeatExchanger
  "Model that demonstrates use of a waterside economizer with outlet temperature control"
  extends Modelica.Icons.Example;

  package MediumW = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=1000*0.01035
    "Nominal mass flow rate at evaporator";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=1000*0.01035
    "Nominal mass flow rate at condenser";
  parameter Modelica.Units.SI.Pressure dp1_nominal=60000
    "Nominal pressure difference on medium 1 side";
  parameter Modelica.Units.SI.Pressure dp2_nominal=60000
    "Nominal pressure difference on medium 2 side";
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet hex1(
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    eta=0.8,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    T_start=273.15 + 10,
    use_controller=true,
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    Ti=40,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    k=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Water-to-water heat exchanger with built-in PID controller to control the temperature at port_b2"

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet hex2(
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    eta=0.8,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    T_start=273.15 + 10,
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    use_controller=false)
    "Water-to-water heat exchanger without built-in controllers to control the temperature at port_b2"
  Buildings.Fluid.Sources.Boundary_pT sin1(
     nPorts=2,
     redeclare package Medium = MediumW)
     "Sink on medium 1 side"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    use_T_in=true,
    nPorts=2,
    redeclare package Medium = MediumW,
    m_flow=2*m1_flow_nominal,
    T=298.15)
    "Source on medium 1 side"
  Modelica.Blocks.Sources.TimeTable TCon_in(
    table=[0,273.15 + 12.78;
           7200,273.15 + 12.78;
           7200,273.15 + 18.33;
           14400,273.15 + 18.33;
           14400,273.15 + 26.67],
    offset=0,
    startTime=0)
    "Condenser inlet temperature"
  Buildings.Fluid.Sources.Boundary_pT sin2(
     nPorts=2,
     redeclare package Medium = MediumW)
     "Sink on medium 2 side"
  Buildings.Fluid.Sources.MassFlowSource_T sou2_2(
    nPorts=1,
    redeclare package Medium = MediumW,
    m_flow=m2_flow_nominal,
    use_T_in=true)
    "Source on medium 2 side"
  Modelica.Blocks.Sources.Constant TEva_in(k=273.15 + 25.28)
    "Evaporator inlet temperature"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSen1(
    m_flow_nominal=m2_flow_nominal,
    redeclare package Medium = MediumW)
    "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSen2(
    redeclare package Medium = MediumW,
    m_flow_nominal=m2_flow_nominal)
    "Temperature sensor"
  Modelica.Blocks.Sources.Constant TSet(
    k(unit="K",displayUnit="degC")=273.15+16.56)
    "Leaving chilled water temperature setpoint"
  Buildings.Fluid.Sources.MassFlowSource_T sou2_1(
    nPorts=1,
    redeclare package Medium = MediumW,
    m_flow=m2_flow_nominal,
    use_T_in=true)
    "Source on medium 2 side"
  Modelica.Blocks.Sources.Constant TEva_in1( k=273.15 + 25.28)
    "Evaporator inlet temperature"
equation
  connect(TSet.y, hex1.TSet)
  connect(sou1.ports[1], hex1.port_a1)
  connect(hex1.port_b1, sin1.ports[1])
  connect(TCon_in.y,sou1. T_in)
  connect(sou2_2.T_in, TEva_in.y)
  connect(hex1.port_b2, TSen1.port_a)
  connect(TSen1.port_b, sin2.ports[1])
  connect(sou1.ports[2], hex2.port_a1)
  connect(hex2.port_b2, TSen2.port_a)
  connect(TSen2.port_b, sin2.ports[2])
  connect(hex2.port_b1, sin1.ports[2])
  connect(hex2.port_a2, sou2_2.ports[1])
  connect(hex1.port_a2, sou2_1.ports[1])
  connect(TEva_in1.y, sou2_1.T_in)
end HeatExchanger;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model HeatExchanger_ResetController
  "Model that demonstrates use of a waterside economizer with outlet temperature control and temperature controller is reset after a predefined time period"
  extends Modelica.Icons.Example;

  package MediumW = Buildings.Media.Water "Medium model";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal=1000*0.01035
    "Nominal mass flow rate at evaporator";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal=1000*0.01035
    "Nominal mass flow rate at condenser";
  parameter Modelica.Units.SI.Pressure dp1_nominal=60000
    "Nominal pressure difference on medium 1 side";
  parameter Modelica.Units.SI.Pressure dp2_nominal=60000
    "Nominal pressure difference on medium 2 side";
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet hex1(
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    eta=0.8,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    T_start=273.15 + 10,
    use_controller=true,
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    Ti=40,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    k=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=0)
    "Water-to-water heat exchanger with built-in PID controller to control the temperature at port_b2"

  Buildings.Fluid.Sources.Boundary_pT sin1(
     nPorts=3,
     redeclare package Medium = MediumW)
     "Sink on medium 1 side"
  Fluid.Sources.Boundary_pT sou1(
    p=MediumW.p_default + 60E3,
    use_T_in=true,
    nPorts=3,
    redeclare package Medium = MediumW,
    T=298.15)
    "Source on medium 1 side"
  Modelica.Blocks.Sources.TimeTable TCon_in(
    table=[0,273.15 + 12.78;
           7200,273.15 + 12.78;
           7200,273.15 + 18.33;
           14400,273.15 + 18.33;
           14400,273.15 + 26.67],
    offset=0,
    startTime=0)
    "Condenser inlet temperature"
  Buildings.Fluid.Sources.Boundary_pT sin2(
     nPorts=3,
     redeclare package Medium = MediumW)
     "Sink on medium 2 side"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSen1(
    m_flow_nominal=m2_flow_nominal,
    redeclare package Medium = MediumW)
    "Temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSen2(
    redeclare package Medium = MediumW,
    m_flow_nominal=m2_flow_nominal)
    "Temperature sensor"
  Modelica.Blocks.Sources.Constant TSet(
    k(unit="K",displayUnit="degC")=273.15+16.56)
    "Leaving chilled water temperature setpoint"
  Fluid.Sources.Boundary_pT sou2_1(
    p=MediumW.p_default + 50E3,
    nPorts=3,
    redeclare package Medium = MediumW,
    use_T_in=true)
    "Source on medium 2 side"
  Modelica.Blocks.Sources.Constant TEva_in(k=273.15 + 25.28)
    "Evaporator inlet temperature"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet hex2(
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    eta=0.8,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    T_start=273.15 + 10,
    use_controller=true,
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    Ti=40,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    k=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Input)
    "Water-to-water heat exchanger with built-in PID controller to control the temperature at port_b2"
  Modelica.Blocks.Sources.BooleanPulse tri(period=900)
    "Trigger controller reset"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet hex3(
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    eta=0.8,
    dp1_nominal=dp1_nominal,
    dp2_nominal=dp2_nominal,
    T_start=273.15 + 10,
    use_controller=true,
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumW,
    Ti=40,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    k=0.1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Water-to-water heat exchanger with built-in PID controller to control the temperature at port_b2"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSen3(redeclare package Medium =
        MediumW, m_flow_nominal=m2_flow_nominal)
    "Temperature sensor"
  Modelica.Blocks.Sources.Constant yRes(k=0) "Reset integrator signal"
equation
  connect(TSet.y, hex1.TSet)
  connect(sou1.ports[1], hex1.port_a1)
  connect(hex1.port_b1, sin1.ports[1])
  connect(TCon_in.y,sou1. T_in)
  connect(hex1.port_b2, TSen1.port_a)
  connect(TSen1.port_b, sin2.ports[1])
  connect(TSen2.port_b, sin2.ports[2])
  connect(hex1.port_a2, sou2_1.ports[1])
  connect(TEva_in.y, sou2_1.T_in)
  connect(TSen2.port_a, hex2.port_b2)
  connect(sou1.ports[2], hex2.port_a1)
  connect(hex2.port_b1, sin1.ports[2])
  connect(TSet.y, hex2.TSet)
  connect(tri.y, hex1.trigger)
  connect(sou2_1.ports[2], hex2.port_a2)
  connect(sin2.ports[3], TSen3.port_b)
  connect(TSen3.port_a, hex3.port_b2)
  connect(hex3.port_a1, sou1.ports[3])
  connect(hex3.port_b1, sin1.ports[3])
  connect(hex3.port_a2, sou2_1.ports[3])
  connect(TSet.y, hex3.TSet)
  connect(tri.y, hex2.trigger)
  connect(yRes.y, hex2.y_reset_in)
end HeatExchanger_ResetController;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model IntegratedPrimaryLoadSide
  "Integrated WSE on the load side in a primary-only chilled water system"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialPlant(
    sou1(nPorts=2),
    sin1(nPorts=2),
    TSet(k=273.15 + 5.56),
    TEva_in(k=273.15 + 15.28),
    sin2(nPorts=2));

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimaryLoadSide
    intWSEPri1(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    perPum=perPum,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Integrated waterside economizer on the load side of the primary-only chilled water system"

  Modelica.Blocks.Sources.Constant yPum(k=1)
    "Conrol signal for pumps"
  Modelica.Blocks.Sources.RealExpression yVal5(
    y=if onChi.y and not onWSE.y then 1 else 0)
    "On/off signal for valve 5"
  Modelica.Blocks.Sources.RealExpression yVal6(
    y=if not onChi.y and onWSE.y then 1 else 0)
    "On/off signal for valve 6"
  Buildings.Fluid.Sources.Boundary_pT sou2(
    redeclare package Medium = MediumCHW,
    nPorts=2,
    use_T_in=true) "Source on medium 2 side"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimaryLoadSide intWSEPri2(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    perPum=perPum,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=0)
    "Integrated waterside economizer on the load side of the primary-only chilled water system with PI controller reset"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup2(
    redeclare package Medium = MediumCHW,
    m_flow_nominal=mCHW_flow_nominal)
  Modelica.Blocks.Sources.BooleanPulse tri(period=1800)
    "Trigger controller reset"
  parameter Fluid.Movers.Data.Generic[numChi] perPum(each pressure=
        Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
        V_flow=mCHW_flow_nominal/1000*{0.2,0.6,1.0,1.2}, dp=dpCHW_nominal*{1.2,1.1,
        1.0,0.6})) "Pump performance data"
equation
  connect(TSet.y, intWSEPri1.TSet)
  connect(yVal5.y, intWSEPri1.yVal5)
  connect(yVal6.y, intWSEPri1.yVal6)
  connect(yPum.y, intWSEPri1.yPum[1])
  connect(intWSEPri1.port_a1, sou1.ports[1])
  connect(intWSEPri1.port_b2, TSup1.port_a)
  connect(intWSEPri1.port_b1, sin1.ports[1])
  connect(intWSEPri1.port_a2, sou2.ports[1])
  connect(TEva_in.y, sou2.T_in)
  connect(TSup2.port_a, intWSEPri2.port_b2)
  connect(intWSEPri2.port_a2, sou2.ports[2])
  connect(intWSEPri2.port_b1, sin1.ports[2])
  connect(intWSEPri2.port_a1, sou1.ports[2])
  connect(TSup2.port_b, sin2.ports[2])
  connect(TSet.y, intWSEPri2.TSet)
  connect(yVal5.y, intWSEPri2.yVal5)
  connect(yVal6.y, intWSEPri2.yVal6)
  connect(yPum.y, intWSEPri2.yPum[1])
  connect(tri.y, intWSEPri2.trigger)
  connect(intWSEPri2.on[1], onChi.y)
  connect(intWSEPri2.on[2], onWSE.y)
  connect(intWSEPri1.on[1], onChi.y)
  connect(intWSEPri1.on[2], onWSE.y)
end IntegratedPrimaryLoadSide;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model IntegratedPrimaryPlantSide
  "Integrated WSE on the plant side in a primary-only chilled water system"
  extends Modelica.Icons.Example;
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialPlant(
    sou1(nPorts=2),
    sin1(nPorts=2),
    TSet(k=273.15 + 5.56),
    TEva_in(k=273.15 + 15.28),
    sin2(nPorts=2));

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimaryPlantSide
    intWSEPri1(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Integrated waterside economizer in the primary-only chilled water system"

  Modelica.Blocks.Sources.RealExpression yVal5(
    y=if onChi.y and not onWSE.y then 1 else 0)
    "On/off signal for valve 5"
  Modelica.Blocks.Sources.RealExpression yVal6(
    y=if not onChi.y and onWSE.y then 1 else 0)
    "On/off signal for valve 6"
  Fluid.Sources.Boundary_pT sou2(
    redeclare package Medium = MediumCHW,
    p=MediumCHW.p_default + 1E5,
    nPorts=2,
    use_T_in=true) "Source on medium 2 side"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimaryPlantSide intWSEPri2(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=0)
    "Integrated waterside economizer in the primary-only chilled water system"
  Modelica.Blocks.Sources.BooleanPulse tri(period=1800)
    "Trigger controller reset"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup2(redeclare package Medium =
        MediumCHW, m_flow_nominal=mCHW_flow_nominal) "Temperature sensor"
equation
  connect(yVal5.y, intWSEPri1.yVal5)
  connect(yVal6.y, intWSEPri1.yVal6)
  connect(intWSEPri1.port_a1, sou1.ports[1])
  connect(intWSEPri1.port_b2, TSup1.port_a)
  connect(intWSEPri1.port_b1, sin1.ports[1])
  connect(intWSEPri1.port_a2, sou2.ports[1])
  connect(TEva_in.y, sou2.T_in)
  connect(TSet.y, intWSEPri1.TSet)
  connect(onChi.y, intWSEPri1.on[1])
  connect(onWSE.y, intWSEPri1.on[2])
  connect(sou1.ports[2], intWSEPri2.port_a1)
  connect(sou2.ports[2], intWSEPri2.port_a2)
  connect(intWSEPri2.port_b1, sin1.ports[2])
  connect(TSet.y, intWSEPri2.TSet)
  connect(onChi.y, intWSEPri2.on[1])
  connect(onWSE.y, intWSEPri2.on[2])
  connect(yVal5.y, intWSEPri2.yVal5)
  connect(yVal6.y, intWSEPri2.yVal6)
  connect(tri.y, intWSEPri2.trigger)
  connect(sin2.ports[2], TSup2.port_b)
  connect(TSup2.port_a, intWSEPri2.port_b2)
end IntegratedPrimaryPlantSide;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model IntegratedPrimarySecondary
  "Integrated WSE on the load side in a primary-secondary chilled water system"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialPlant(
    sou1(nPorts=2),
    sin1(nPorts=2),
    TSet(k=273.15 + 5.56),
    TEva_in(k=273.15 + 10.28),
    sin2(nPorts=2));

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimarySecondary
    intWSEPriSec1(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    perPum=perPum,
    addPowerToMedium=false,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Integrated waterside economizer on the load side of a primary-secondary chilled water system"

  Modelica.Blocks.Sources.RealExpression yVal5(
    y=if onChi.y and not onWSE.y then 1 else 0)
    "On/off signal for valve 5"
  Modelica.Blocks.Sources.RealExpression yPum(y=if onChi.y then 1 else 0)
    "Input signal for primary pump"
  Fluid.Sources.Boundary_pT sou2(
    redeclare package Medium = MediumCHW,
    p=MediumCHW.p_default + 30E3,
    nPorts=2,
    use_T_in=true) "Source on medium 2 side"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimarySecondary
    intWSEPriSec2(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    perPum=perPum,
    addPowerToMedium=false,
    show_T=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=0)
    "Integrated waterside economizer on the load side of a primary-secondary chilled water system"
  Modelica.Blocks.Sources.BooleanPulse tri(period=1800)
    "Trigger controller reset"
  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPum(each pressure=
        Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
        V_flow=mCHW_flow_nominal/1000*{0.2,0.6,1.0,1.2}, dp=dpCHW_nominal*{1.2,1.1,
        1.0,0.6})) "Pump performance data"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup2(redeclare package Medium =
        MediumCHW, m_flow_nominal=mCHW_flow_nominal) "Temperature sensor"
equation
  connect(TSet.y, intWSEPriSec1.TSet)
  connect(yVal5.y, intWSEPriSec1.yVal5)
  connect(intWSEPriSec1.port_a1, sou1.ports[1])
  connect(intWSEPriSec1.port_b2, TSup1.port_a)
  connect(intWSEPriSec1.port_b1, sin1.ports[1])
  connect(intWSEPriSec1.port_a2, sou2.ports[1])
  connect(yPum.y, intWSEPriSec1.yPum[1])
  connect(TEva_in.y, sou2.T_in)
  connect(onChi.y, intWSEPriSec1.on[1])
  connect(onWSE.y, intWSEPriSec1.on[2])
  connect(TSet.y, intWSEPriSec2.TSet)
  connect(onChi.y, intWSEPriSec2.on[1])
  connect(onWSE.y, intWSEPriSec2.on[2])
  connect(yVal5.y, intWSEPriSec2.yVal5)
  connect(yPum.y, intWSEPriSec2.yPum[1])
  connect(sou1.ports[2], intWSEPriSec2.port_a1)
  connect(sou2.ports[2], intWSEPriSec2.port_a2)
  connect(intWSEPriSec2.port_b1, sin1.ports[2])
  connect(tri.y, intWSEPriSec2.trigger)
  connect(sin2.ports[2], TSup2.port_b)
  connect(TSup2.port_a, intWSEPriSec2.port_b2)
end IntegratedPrimarySecondary;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model NonIntegrated "Non-integrated WSE  in a chilled water system"
  extends Modelica.Icons.Example;
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialPlant(
    sou1(nPorts=2),
    sin1(nPorts=2),
    TSet(k=273.15 + 5.56),
    TEva_in(k=273.15 + 15.28),
    onWSE(startTime=7200),
    sin2(nPorts=2));

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.NonIntegrated nonIntWSE1(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Non-integrated waterside economizer "

  Fluid.Sources.Boundary_pT sou2(
    redeclare package Medium = MediumCHW,
    p=MediumCHW.p_default + 50E3,
    nPorts=2,
    use_T_in=true) "Source on medium 2 side"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.NonIntegrated nonIntWSE2(
    m1_flow_chi_nominal=mCW_flow_nominal,
    m2_flow_chi_nominal=mCHW_flow_nominal,
    m1_flow_wse_nominal=mCW_flow_nominal,
    m2_flow_wse_nominal=mCHW_flow_nominal,
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    dp1_chi_nominal=dpCW_nominal,
    dp1_wse_nominal=dpCW_nominal,
    dp2_chi_nominal=dpCHW_nominal,
    dp2_wse_nominal=dpCHW_nominal,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    redeclare
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_Trane_CVHF_2567kW_11_77COP_VSD
      perChi,
    k=0.4,
    Ti=80,
    numChi=numChi,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=0) "Non-integrated waterside economizer "
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup2(redeclare package Medium =
        MediumCHW, m_flow_nominal=mCHW_flow_nominal) "Temperature sensor"
  Modelica.Blocks.Sources.BooleanPulse tri(period=1800)
    "Trigger controller reset"
equation
  connect(TSet.y, nonIntWSE1.TSet)
  connect(nonIntWSE1.port_a1, sou1.ports[1])
  connect(nonIntWSE1.port_b2, TSup1.port_a)
  connect(nonIntWSE1.port_b1, sin1.ports[1])
  connect(nonIntWSE1.port_a2, sou2.ports[1])
  connect(TEva_in.y, sou2.T_in)
  connect(onChi.y, nonIntWSE1.on[1])
  connect(onWSE.y, nonIntWSE1.on[2])
  connect(TSet.y, nonIntWSE2.TSet)
  connect(onChi.y, nonIntWSE2.on[1])
  connect(onWSE.y, nonIntWSE2.on[2])
  connect(sou1.ports[2], nonIntWSE2.port_a1)
  connect(sin1.ports[2], nonIntWSE2.port_b1)
  connect(nonIntWSE2.port_a2, sou2.ports[2])
  connect(sin2.ports[2], TSup2.port_b)
  connect(TSup2.port_a, nonIntWSE2.port_b2)
  connect(tri.y, nonIntWSE2.trigger)
end NonIntegrated;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
package Validation "Collection of models that validate the Buildings.Applications.DataCenters.ChillerCooled package"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model WatersideEconomizer
  "Validate model Buildings.Applications.DataCenters.ChillerCooled.Equipment.WatersideEconomizer"
  extends Modelica.Icons.Example;

  package MediumCHW = Buildings.Media.Water "Medium model";
  package MediumCW = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.MassFlowRate mCHW_flow_nominal=2567.1*1000/(4200*
      10) "Nominal mass flow rate at chilled water";

  parameter Modelica.Units.SI.MassFlowRate mCW_flow_nominal=2567.1*1000/(4200*
      8.5) "Nominal mass flow rate at condenser water";
  parameter Modelica.Units.SI.PressureDifference dpCHW_nominal=40000
    "Nominal pressure";
  parameter Modelica.Units.SI.PressureDifference dpCW_nominal=40000
    "Nominal pressure";
  parameter Integer numChi=1 "Number of chillers";

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.WatersideEconomizer WSE(
    redeclare package Medium1 = MediumCW,
    redeclare package Medium2 = MediumCHW,
    controllerType=Modelica.Blocks.Types.SimpleController.PI,
    k=0.4,
    Ti=80,
    m1_flow_nominal=mCW_flow_nominal,
    m2_flow_nominal=mCHW_flow_nominal,
    eta=0.8,
    dp1_nominal=dpCW_nominal,
    dp2_nominal=dpCHW_nominal,
    use_controller=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Waterside economizer"

  Buildings.Fluid.Sources.MassFlowSource_T sou2(
    redeclare package Medium = MediumCHW,
    m_flow=mCHW_flow_nominal,
    nPorts=1,
    use_T_in=true)
    "Source on medium 2 side"
  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = MediumCW, nPorts=1)
    "Sink on medium 1 side"
  Buildings.Fluid.Sources.MassFlowSource_T sou1(
    use_T_in=true,
    redeclare package Medium = MediumCW,
    m_flow=mCW_flow_nominal,
    T=298.15,
    nPorts=1)
    "Source on medium 1 side"
  Modelica.Blocks.Sources.TimeTable TCon_in(
    table=[0,273.15 + 12.78;
          7200,273.15 + 12.78;
          7200,273.15 + 18.33;
          14400,273.15 + 18.33;
          14400,273.15 + 26.67],
    offset=0,
    startTime=0)
    "Condenser inlet temperature"
  Buildings.Fluid.Sources.Boundary_pT sin2(
    nPorts=1,
    redeclare package Medium = MediumCHW)
    "Sink on medium 2 side"
  Modelica.Blocks.Sources.Constant TEva_in(
    k(unit="K",
     displayUnit="degC")=273.15 + 25.28)
    "Evaporator inlet temperature"
  Modelica.Blocks.Sources.Constant TSet(
    k(unit="K",
     displayUnit="degC") = 273.15 + 13.56)
    "Leaving chilled water temperature setpoint"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup(redeclare package Medium =
        MediumCHW, m_flow_nominal=mCHW_flow_nominal) "Temperature sensor"
  Modelica.Blocks.Sources.BooleanStep onWSE(
    startValue=true,
    startTime=7200)
    "On and off signal for the WSE"
equation
  connect(TSet.y, WSE.TSet)
  connect(WSE.port_b2, TSup.port_a)
  connect(WSE.port_a2, sou2.ports[1])
  connect(TEva_in.y, sou2.T_in)
  connect(TCon_in.y,sou1. T_in)
  connect(sin2.ports[1], TSup.port_b)
  connect(onWSE.y, WSE.on[1])
  connect(sou1.ports[1], WSE.port_a1)
  connect(WSE.port_b1, sin1.ports[1])
end WatersideEconomizer;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
package BaseClasses "Package with base classes for Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses;
partial model PartialAirHandlerControl
  "Partial model for testing air hanlders with temperature and humidity control"
  package Medium1 = Buildings.Media.Water "Medium model for water";
  package Medium2 = Buildings.Media.Air "Medium model for air";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal(min=0) = 2.9
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal(min=0) = 3.3
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.Temperature T_a1_nominal=6 + 273.15
    "Nominal water inlet temperature";
  parameter Modelica.Units.SI.Temperature T_b1_nominal=11 + 273.15
    "Nominal water outlet temperature";
  parameter Modelica.Units.SI.Temperature T_a2_nominal=26 + 273.15
    "Nominal air inlet temperature";
  parameter Modelica.Units.SI.Temperature T_b2_nominal=12 + 273.15
    "Nominal air outlet temperature";

  Buildings.Fluid.Sources.Boundary_pT sin_2(
    redeclare package Medium = Medium2,
    nPorts=1,
    use_p_in=false,
    p(displayUnit="Pa"),
    T=303.15)
    "Sink for water"
  Buildings.Fluid.Sources.Boundary_pT sou_2(
    redeclare package Medium = Medium2,
    X={0.02,1 - 0.02},
    use_T_in=true,
    use_X_in=true,
    p(displayUnit="Pa"))
    "Source for water"
  Buildings.Fluid.Sources.Boundary_pT sin_1(
    redeclare package Medium = Medium1,
    nPorts=1,
    use_p_in=false,
    p=300000,
    T=293.15)
    "Sink for air"
  Buildings.Fluid.Sources.Boundary_pT sou_1(
    redeclare package Medium = Medium1,
    use_T_in=true,
    p=300000 + 12000,
    nPorts=1)
    "Sink for air"
  Buildings.Fluid.FixedResistances.PressureDrop res_2(
    from_dp=true,
    redeclare package Medium = Medium2,
    dp_nominal=100,
    m_flow_nominal=m2_flow_nominal)
    "Flow resistance"
  Buildings.Fluid.FixedResistances.PressureDrop res_1(
    from_dp=true,
    redeclare package Medium = Medium1,
    dp_nominal=3000,
    m_flow_nominal=m1_flow_nominal)
    "Flow resistance"
  Modelica.Blocks.Sources.Constant  TSet(
    k(unit="K")=289.15)
    "Setpoint temperature"
  Modelica.Blocks.Sources.Constant relHum(k=0.8)
    "Relative humidity"
  Buildings.Utilities.Psychrometrics.X_pTphi x_pTphi(use_p_in=false)
  Modelica.Blocks.Sources.Constant temSou_2(k=T_a2_nominal)
    "Temperature boundary for source 2"
  Modelica.Blocks.Sources.Step TWat(
    offset=T_a1_nominal,
    height=3,
    startTime=1500)
   "Water temperature"
  Buildings.Fluid.Sensors.MassFractionTwoPort masFra(
    redeclare package Medium = Medium2, m_flow_nominal=m2_flow_nominal)
    "Sensor for mass fraction"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenWat1(
    redeclare package Medium = Medium1, m_flow_nominal=m2_flow_nominal)
    "Temperature sensor for water"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenAir2(
    redeclare package Medium = Medium2, m_flow_nominal=m2_flow_nominal)
    "Temperature for air"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenWat2(
    redeclare package Medium = Medium1, m_flow_nominal=m2_flow_nominal)
    "Temperature for water"
equation
  connect(sin_1.ports[1],res_1. port_b)
  connect(sin_2.ports[1],res_2. port_b)
  connect(x_pTphi.X,sou_2. X_in)
  connect(relHum.y, x_pTphi.phi)
  connect(temSou_2.y, x_pTphi.T)
  connect(temSou_2.y, sou_2.T_in)
  connect(TWat.y,sou_1. T_in)
  connect(masFra.port_b, res_2.port_a)
  connect(temSenWat1.port_a, sou_1.ports[1])
  connect(temSenAir2.port_b, masFra.port_a)
  connect(temSenWat2.port_b, res_1.port_a)
end PartialAirHandlerControl;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses;
partial model PartialAirHandlerMassFlow
  "Partial model for testing air handler at variable mass flowrate"

  package Medium1 = Buildings.Media.Water "Medium model for water";
  package Medium2 = Buildings.Media.Air "Medium model for air";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_nominal(min=0) = 2.9
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_nominal(min=0) = 3.3
    "Nominal mass flow rate";
  parameter Modelica.Units.SI.Temperature T_a1_nominal=6 + 273.15
    "Nominal water inlet temperature";
  parameter Modelica.Units.SI.Temperature T_b1_nominal=11 + 273.15
    "Nominal water outlet temperature";
  parameter Modelica.Units.SI.Temperature T_a2_nominal=26 + 273.15
    "Nominal air inlet temperature";
  parameter Modelica.Units.SI.Temperature T_b2_nominal=12 + 273.15
    "Nominal air outlet temperature";

  Buildings.Fluid.Sources.Boundary_pT sin_2(
    redeclare package Medium = Medium2,
    T=T_a2_nominal,
    nPorts=1)
    "Sink for air"
  Buildings.Fluid.Sources.Boundary_pT sou_2(
    redeclare package Medium = Medium2,
    T=T_a2_nominal,
    X={0.02,1 - 0.02},
    use_T_in=true,
    use_X_in=true)
    "Source for air"
  Buildings.Fluid.Sources.MassFlowSource_T sin_1(
    redeclare package Medium = Medium1,
    T=T_a1_nominal,
    use_m_flow_in=true,
    nPorts=1)
    "Source for water"
  Buildings.Fluid.Sources.Boundary_pT sou_1(
    redeclare package Medium = Medium1,
    use_T_in=false,
    T=T_a1_nominal,
    nPorts=1)
    "Sink for water"
  Modelica.Blocks.Sources.Constant relHum(k=0.8) "Relative humidity"
  Buildings.Utilities.Psychrometrics.X_pTphi x_pTphi(use_p_in=false)
  Modelica.Blocks.Sources.Constant temSou_2(k=T_a2_nominal)
    "Temperature boundary condition"
  Modelica.Blocks.Math.Gain mWat_flow(k=-m1_flow_nominal)
    "Water mass flow rate"
  Modelica.Blocks.Sources.TimeTable mWatGai(
    table=[0,1; 3600*0.1,1; 3600*0.2,0.1; 3600*0.3,0.1])
    "Gain for water mass flow rate"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenWat1(
    redeclare package Medium = Medium1,
    m_flow_nominal=m2_flow_nominal)
    "Temperature sensor for water"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenWat2(
    redeclare package Medium = Medium1,
    m_flow_nominal=m2_flow_nominal)
    "Temperature sensor for water"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSenAir2(
    redeclare package Medium = Medium2,
    m_flow_nominal=m2_flow_nominal)
    "Temperature for air"
equation
  connect(x_pTphi.X, sou_2.X_in)
  connect(relHum.y, x_pTphi.phi)
  connect(temSou_2.y, x_pTphi.T)
  connect(temSou_2.y, sou_2.T_in)
  connect(mWatGai.y, mWat_flow.u)
  connect(mWat_flow.y, sin_1.m_flow_in)
  connect(temSenWat1.port_a, sou_1.ports[1])
  connect(temSenAir2.port_b, sin_2.ports[1])
  connect(temSenWat2.port_b, sin_1.ports[1])
end PartialAirHandlerMassFlow;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses;
partial model PartialPlant
  "Partial examples for Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation"

  package MediumCHW = Buildings.Media.Water "Medium model";
  package MediumCW = Buildings.Media.Water "Medium model";

  parameter Modelica.Units.SI.MassFlowRate mCHW_flow_nominal=2567.1*1000/(4200*
      10) "Nominal mass flow rate at chilled water";

  parameter Modelica.Units.SI.MassFlowRate mCW_flow_nominal=2567.1*1000/(4200*
      8.5) "Nominal mass flow rate at condenser water";
  parameter Modelica.Units.SI.PressureDifference dpCHW_nominal=40000
    "Nominal pressure";
  parameter Modelica.Units.SI.PressureDifference dpCW_nominal=40000
    "Nominal pressure";
  parameter Integer numChi=1 "Number of chillers";

  Buildings.Fluid.Sources.Boundary_pT sin1(
    redeclare package Medium = MediumCW)
    "Sink on medium 1 side"
  Fluid.Sources.Boundary_pT sou1(
    p=MediumCW.p_default + 45E3,
    use_T_in=true,
    redeclare package Medium = MediumCW,
    T=298.15)
    "Source on medium 1 side"
  Modelica.Blocks.Sources.TimeTable TCon_in(
    table=[0,273.15 + 12.78;
          7200,273.15 + 12.78;
          7200,273.15 + 18.33;
          14400,273.15 + 18.33;
          14400,273.15 + 26.67],
    offset=0,
    startTime=0)
    "Condenser inlet temperature"
  Buildings.Fluid.Sources.Boundary_pT sin2(
    nPorts=1,
    redeclare package Medium = MediumCHW)
    "Sink on medium 2 side"

  Modelica.Blocks.Sources.Constant TEva_in(k=273.15 + 25.28)
    "Evaporator inlet temperature"
  Modelica.Blocks.Sources.Constant TSet(
    k(unit="K",displayUnit="degC")=273.15+15.56)
    "Leaving chilled water temperature setpoint"

  Buildings.Fluid.Sensors.TemperatureTwoPort TSup1(redeclare package Medium =
        MediumCHW, m_flow_nominal=mCHW_flow_nominal) "Temperature sensor"
  Modelica.Blocks.Sources.BooleanStep onChi(startTime=7200)
    "On and off signal for the chiller"
  Modelica.Blocks.Sources.BooleanStep onWSE(startTime=14400, startValue=true)
    "On and off signal for the WSE"
equation
  connect(TCon_in.y,sou1. T_in)
  connect(sin2.ports[1], TSup1.port_b)
end PartialPlant;


Example that demonstrates a chiller plant with integrated primary load side economizer.

within Buildings.Applications.DataCenters.ChillerCooled.Examples;
model IntegratedPrimaryLoadSideEconomizer
  "Example that demonstrates a chiller plant with integrated primary load side economizer"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PostProcess(
    freCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
      then 1 else 0),
    parMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical)
      then 1 else 0),
    fulMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
      then 1 else 0),
    PHVAC(y=cooTow[1].PFan + cooTow[2].PFan + pumCW[1].P + pumCW[2].P + sum(
          chiWSE.powChi + chiWSE.powPum) + ahu.PFan + ahu.PHea),
    PIT(y=roo.QSou.Q_flow));
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PartialDataCenter(
    redeclare Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimaryLoadSide chiWSE(
      addPowerToMedium=false,
      perPum=perPumPri),
    weaData(filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/DRYCOLD.mos")));

  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumPri(
    each pressure=Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m2_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp2_chi_nominal+dp2_wse_nominal+18000)*{1.5,1.3,1.0,0.6}))
    "Performance data for primary pumps";

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingMode
    cooModCon(
    tWai=tWai,
    deaBan1=1.1,
    deaBan2=0.5,
    deaBan3=1.1,
    deaBan4=0.5)
    "Cooling mode controller"
  Modelica.Blocks.Sources.RealExpression towTApp(y=cooTow[1].TApp_nominal)
    "Cooling tower approach temperature"
  Modelica.Blocks.Sources.RealExpression yVal5(
    y=if cooModCon.y == Integer(
    Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
    then 1 else 0)
    "On/off signal for valve 5"
  Modelica.Blocks.Sources.RealExpression yVal6(
    y=if cooModCon.y == Integer(
    Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
    then 1 else 0)
    "On/off signal for valve 6"

  Modelica.Blocks.Sources.RealExpression cooLoaChi(
    y=-chiWSE.port_a2.m_flow*4180*(chiWSE.TCHWSupWSE - TCHWSupSet.y))
    "Cooling load in chillers"
equation

  connect(pumSpeSig.y, chiWSE.yPum)
  connect(TCHWSup.port_b, ahu.port_a1)
  connect(chiWSE.TCHWSupWSE, cooModCon.TCHWSupWSE)
  connect(cooLoaChi.y, chiStaCon.QTot)
   for i in 1:numChi loop
    connect(pumCW[i].port_a, TCWSup.port_b)
   end for;
  connect(TCHWSupSet.y, cooModCon.TCHWSupSet)
  connect(towTApp.y, cooModCon.TApp)
  connect(TCHWRet.port_b, chiWSE.port_a2)
  connect(cooModCon.TCHWRetWSE, TCHWRet.T)

  connect(cooModCon.y, chiStaCon.cooMod)
  connect(cooModCon.y,intToBoo.u)
  connect(TCHWSup.T, chiStaCon.TCHWSup)
  connect(cooModCon.y, sigCha.u)
  connect(yVal5.y, chiWSE.yVal5)
  connect(yVal6.y, chiWSE.yVal6)
  connect(cooModCon.y, cooTowSpeCon.cooMod)
  connect(cooModCon.y, CWPumCon.cooMod)
  connect(weaBus.TWetBul, cooModCon.TWetBul)
end IntegratedPrimaryLoadSideEconomizer;


within Buildings.Applications.DataCenters.ChillerCooled.Examples;
model IntegratedPrimarySecondaryEconomizer
  "Example that demonstrates a chiller plant with integrated primary-secondary side economizer"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PostProcess(
    freCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
      then 1 else 0),
    parMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical)
      then 1 else 0),
    fulMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
      then 1 else 0),
    PHVAC(y=cooTow[1].PFan + cooTow[2].PFan + pumCW[1].P + pumCW[2].P + sum(
          chiWSE.powChi + chiWSE.powPum) + sum(secPum.P) + ahu.PFan + ahu.PHea),
    PIT(y=roo.QSou.Q_flow));
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PartialDataCenter(
    redeclare Buildings.Applications.DataCenters.ChillerCooled.Equipment.IntegratedPrimarySecondary chiWSE(
        addPowerToMedium=false,
        perPum=perPumPri),
    weaData(filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/DRYCOLD.mos")));

  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumSec(
    each pressure=
          Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m2_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp2_wse_nominal+dpSetPoi+18000+30000)*{1.5,1.3,1.0,0.6}))
    "Performance data for secondary chilled water pumps";
  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumPri(
    each pressure=
          Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m2_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp2_chi_nominal+dp2_wse_nominal+6000)*{1.5,1.3,1.0,0.6}))
    "Performance data for secondary chilled water pumps";

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingMode
    cooModCon(
    tWai=tWai,
    deaBan1=1.1,
    deaBan2=0.5,
    deaBan3=1.1,
    deaBan4=0.5)
    "Cooling mode controller"
  Modelica.Blocks.Sources.RealExpression towTApp(y=cooTow[1].TApp_nominal)
    "Cooling tower approach temperature"

  Modelica.Blocks.Sources.RealExpression yVal5(
    y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
    then 1 else 0) "On/off signal for valve 5"
  Modelica.Blocks.Sources.RealExpression cooLoaChi(
    y=-chiWSE.port_a2.m_flow*4180*(chiWSE.TCHWSupWSE - TCHWSupSet.y))
    "Cooling load in chillers"
  Buildings.Applications.BaseClasses.Equipment.FlowMachine_y secPum(
    redeclare package Medium = MediumW,
    dpValve_nominal=6000,
    per=perPumSec,
    addPowerToMedium=false,
    m_flow_nominal=m2_flow_chi_nominal,
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Secondary pumps"
  Buildings.Applications.DataCenters.ChillerCooled.Controls.ConstantSpeedPumpStage
    PriPumCon(tWai=0)
    "Chilled water primary pump controller"
  Modelica.Blocks.Math.Product priPumSpe[numChi] "Primary pump speed signal"
  Modelica.Blocks.Sources.RealExpression notFreCoo(y=if cooModCon.y == Integer(
        Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
         then 0 else 1) "Not free cooling mode"
equation
  connect(yVal5.y, chiWSE.yVal5)
  connect(cooLoaChi.y, chiStaCon.QTot)
  connect(TCHWSup.port_b, secPum.port_a)
  connect(secPum.port_b, ahu.port_a1)
  connect(pumSpeSig.y, secPum.u)

   for i in 1:numChi loop
    connect(pumCW[i].port_a, TCWSup.port_b)
   end for;
  connect(towTApp.y, cooModCon.TApp)
  connect(TCHWRet.port_b, chiWSE.port_a2)
  connect(cooModCon.TCHWRetWSE, TCHWRet.T)

  connect(chiWSE.TCHWSupWSE, cooModCon.TCHWSupWSE)
  connect(TCHWSupSet.y, cooModCon.TCHWSupSet)
  connect(TCHWSup.T, chiStaCon.TCHWSup)
  connect(PriPumCon.numOnChi, chiNumOn.y)
  connect(PriPumCon.cooMod, cooModCon.y)
  connect(cooTowSpeCon.cooMod, cooModCon.y)
  connect(intToBoo.u, cooModCon.y)
  connect(CWPumCon.cooMod, cooModCon.y)
  connect(cooModCon.y, sigCha.u)
  connect(cooModCon.y, chiStaCon.cooMod)
  connect(notFreCoo.y, priPumSpe[1].u1)
  connect(notFreCoo.y, priPumSpe[2].u1)
  connect(PriPumCon.y, priPumSpe.u2)
  connect(priPumSpe.y, chiWSE.yPum)
  connect(weaBus.TWetBul, cooModCon.TWetBul)
end IntegratedPrimarySecondaryEconomizer;


within Buildings.Applications.DataCenters.ChillerCooled.Examples;
model NonIntegratedPrimarySecondaryEconomizer
  "Example that demonstrates a chiller plant with non-integrated primary-secondary side economizer"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PostProcess(
    freCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
      then 1 else 0),
    parMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical)
      then 1 else 0),
    fulMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
      then 1 else 0),
    PHVAC(y=cooTow[1].PFan + cooTow[2].PFan + pumCW[1].P + pumCW[2].P + sum(
          chiWSE.powChi) + sum(priPum.P) + sum(secPum.P) + ahu.PFan + ahu.PHea),
    PIT(y=roo.QSou.Q_flow));
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PartialDataCenter(
    redeclare Buildings.Applications.DataCenters.ChillerCooled.Equipment.NonIntegrated chiWSE(
      controllerType=Modelica.Blocks.Types.SimpleController.PI,
      Ti=60),
    weaData(filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/DRYCOLD.mos")),
    CWPumCon(tWai=60),
    chiStaCon(tWai=60));

  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumSec(
    each pressure=
          Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m2_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp2_wse_nominal+dpSetPoi+18000+30000)*{1.5,1.3,1.0,0.6}))
    "Performance data for secondary chilled water pumps";
  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumPri(
    each pressure=Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m2_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp2_chi_nominal+6000)*{1.5,1.3,1.0,0.6}))
    "Performance data for secondary chilled water pumps";

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingModeNonIntegrated cooModCon(
    tWai=tWai,
    deaBan=1,
    TSwi=TCHWSet - 5)
    "Cooling mode controller"

  Buildings.Applications.BaseClasses.Equipment.FlowMachine_y secPum(
    redeclare package Medium = MediumW,
    dpValve_nominal=6000,
    per=perPumSec,
    addPowerToMedium=false,
    m_flow_nominal=m2_flow_chi_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    tau=1,
    use_riseTime=true) "Secondary pumps"
  Buildings.Applications.BaseClasses.Equipment.FlowMachine_m priPum(
    redeclare package Medium = MediumW,
    dpValve_nominal=6000,
    per=perPumPri,
    m_flow_nominal=m2_flow_chi_nominal,
    addPowerToMedium=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    tau=1,
    use_riseTime=true) "Constant speed pumps"
  Buildings.Applications.DataCenters.ChillerCooled.Controls.ConstantSpeedPumpStage
    priPumCon(tWai=0)
    "Chilled water primary pump controller"
  Modelica.Blocks.Sources.RealExpression cooLoaChi(
    y=-ahu.port_a1.m_flow*4180*(TCHWRet.T - TCHWSupSet.y))
    "Cooling load in chillers"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Buildings.Fluid.Sensors.MassFlowRate bypFlo(
    redeclare package Medium = MediumW)
    "Sensor for bypass flowrate"
equation
  for i in 1:numChi loop

    connect(chiOn[i].y, chiWSE.on[i])
  end for;
  connect(TCHWSupSet.y, cooModCon.TCHWSupSet)
  connect(chiStaCon.y, chiOn.u)
  connect(intToBoo.y, wseOn.u)
  connect(wseOn.y, chiWSE.on[numChi + 1])
  connect(secPum.port_b, ahu.port_a1)
  connect(TCHWSup.port_b, secPum.port_a)
  connect(cooLoaChi.y, chiStaCon.QTot)
  connect(TCHWSup.T, cooModCon.TCHWSup)
  connect(priPum.port_a, TCHWRet.port_b)
  connect(chiWSE.port_a2, priPum.port_b)
  connect(priPum.port_a, bypFlo.port_a)
  connect(bypFlo.port_b, TCHWSup.port_a)
  connect(TCHWSup.T, chiStaCon.TCHWSup)
  connect(cooModCon.numOnChi, chiNumOn.y)
  connect(priPumCon.cooMod, cooModCon.y)
  connect(cooModCon.y, CWPumCon.cooMod)
  connect(chiStaCon.cooMod, cooModCon.y)
  connect(cooModCon.y, intToBoo.u)
  connect(cooModCon.y, sigCha.u)
  connect(chiNumOn.y, priPumCon.numOnChi)
  connect(cooModCon.y, cooTowSpeCon.cooMod)
  connect(weaBus.TWetBul, cooModCon.TWetBul)
  connect(pumSpeSig.y, secPum.u)
  connect(priPumCon.y, priPum.u)
end NonIntegratedPrimarySecondaryEconomizer;


within Buildings.Applications.DataCenters.ChillerCooled;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Base classes for examples

within Buildings.Applications.DataCenters.ChillerCooled.Examples;
package BaseClasses "Base classes for examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses;
partial model PartialDataCenter
  "Partial model that impliments cooling system for data centers"
  replaceable package MediumA = Buildings.Media.Air "Medium model";
  replaceable package MediumW = Buildings.Media.Water "Medium model";

  // Chiller parameters
  parameter Integer numChi=2 "Number of chillers";
  parameter Modelica.Units.SI.MassFlowRate m1_flow_chi_nominal=34.7
    "Nominal mass flow rate at condenser water in the chillers";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_chi_nominal=18.3
    "Nominal mass flow rate at evaporator water in the chillers";
  parameter Modelica.Units.SI.PressureDifference dp1_chi_nominal=46.2*1000
    "Nominal pressure";
  parameter Modelica.Units.SI.PressureDifference dp2_chi_nominal=44.8*1000
    "Nominal pressure";
  parameter Modelica.Units.SI.Power QEva_nominal=m2_flow_chi_nominal*4200*(6.67
       - 18.56) "Nominal cooling capaciaty(Negative means cooling)";
 // WSE parameters
  parameter Modelica.Units.SI.MassFlowRate m1_flow_wse_nominal=34.7
    "Nominal mass flow rate at condenser water in the chillers";
  parameter Modelica.Units.SI.MassFlowRate m2_flow_wse_nominal=35.3
    "Nominal mass flow rate at condenser water in the chillers";
  parameter Modelica.Units.SI.PressureDifference dp1_wse_nominal=33.1*1000
    "Nominal pressure";
  parameter Modelica.Units.SI.PressureDifference dp2_wse_nominal=34.5*1000
    "Nominal pressure";

  parameter Buildings.Fluid.Movers.Data.Generic[numChi] perPumCW(
    each pressure=
          Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParameters(
          V_flow=m1_flow_chi_nominal/1000*{0.2,0.6,1.0,1.2},
          dp=(dp1_chi_nominal+60000+6000)*{1.2,1.1,1.0,0.6}))
    "Performance data for condenser water pumps";
  parameter Modelica.Units.SI.Time tWai=1200 "Waiting time";

  // AHU
  parameter Modelica.Units.SI.ThermalConductance UA_nominal=numChi*QEva_nominal
      /Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
      6.67,
      11.56,
      12,
      25)
    "Thermal conductance at nominal flow for sensible heat, used to compute time constant";
  parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=161.35
    "Nominal air mass flowrate";
  parameter Real yValMinAHU(min=0,max=1,unit="1")=0.1
    "Minimum valve openning position";
  // Set point
  parameter Modelica.Units.SI.Temperature TCHWSet=273.15 + 8
    "Chilled water temperature setpoint";
  parameter Modelica.Units.SI.Temperature TSupAirSet=TCHWSet + 10
    "Supply air temperature setpoint";
  parameter Modelica.Units.SI.Temperature TRetAirSet=273.15 + 25
    "Supply air temperature setpoint";
  parameter Modelica.Units.SI.Pressure dpSetPoi=80000
    "Differential pressure setpoint";

  replaceable
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialChillerWSE
    chiWSE(
    redeclare replaceable package Medium1 = MediumW,
    redeclare replaceable package Medium2 = MediumW,
    numChi=numChi,
    m1_flow_chi_nominal=m1_flow_chi_nominal,
    m2_flow_chi_nominal=m2_flow_chi_nominal,
    m1_flow_wse_nominal=m1_flow_wse_nominal,
    m2_flow_wse_nominal=m2_flow_wse_nominal,
    dp1_chi_nominal=dp1_chi_nominal,
    dp1_wse_nominal=dp1_wse_nominal,
    dp2_chi_nominal=dp2_chi_nominal,
    dp2_wse_nominal=dp2_wse_nominal,
    redeclare each
      Buildings.Fluid.Chillers.Data.ElectricEIR.ElectricEIRChiller_York_YT_1055kW_5_96COP_Vanes
      perChi,
    use_strokeTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_controller=false) "Chillers and waterside economizer"
  Buildings.Fluid.Sources.Boundary_pT expVesCW(
    redeclare replaceable package Medium = MediumW,
    nPorts=1)
    "Expansion tank"
  Buildings.Fluid.HeatExchangers.CoolingTowers.YorkCalc cooTow[numChi](
    redeclare each replaceable package Medium = MediumW,
    each TAirInWB_nominal(displayUnit="degC") = 283.15,
    each TApp_nominal=6,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyStateInitial,
    each dp_nominal=30000,
    each m_flow_nominal=0.785*m1_flow_chi_nominal,
    each PFan_nominal=18000)
    "Cooling tower"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCHWSup(
    redeclare replaceable package Medium = MediumW,
    m_flow_nominal=numChi*m2_flow_chi_nominal)
    "Chilled water supply temperature"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3  weaData(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCWSup(
    redeclare replaceable package Medium = MediumW,
    m_flow_nominal=numChi*m1_flow_chi_nominal)
    "Condenser water supply temperature"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCWRet(
    redeclare replaceable package Medium = MediumW,
    m_flow_nominal=numChi*m1_flow_chi_nominal)
    "Condenser water return temperature"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumCW[numChi](
    redeclare each replaceable package Medium = MediumW,
    each m_flow_nominal=m1_flow_chi_nominal,
    each addPowerToMedium=false,
    per=perPumCW,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    each use_riseTime=false) "Condenser water pump"

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.CoolingCoilHumidifyingHeating ahu(
    redeclare replaceable package Medium1 = MediumW,
    redeclare replaceable package Medium2 = MediumA,
    m1_flow_nominal=numChi*m2_flow_chi_nominal,
    m2_flow_nominal=mAir_flow_nominal,
    dpValve_nominal=6000,
    dp2_nominal=600,
    mWatMax_flow=0.01,
    UA_nominal=UA_nominal,
    addPowerToMedium=false,
    perFan(
      pressure(dp=800*{1.2,1.12,1},
         V_flow=mAir_flow_nominal/1.29*{0,0.5,1}),
         motorCooledByFluid=false),
    yValSwi=yValMinAHU + 0.1,
    yValDeaBan=0.05,
    QHeaMax_flow=30000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp1_nominal=30000)
    "Air handling unit"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCHWRet(
    redeclare replaceable package Medium = MediumW,
    m_flow_nominal=numChi*m2_flow_chi_nominal)
    "Chilled water return temperature"
  Buildings.Fluid.Sources.Boundary_pT expVesChi(
    redeclare replaceable package Medium = MediumW,
    nPorts=1)
    "Expansion tank"
  Buildings.Fluid.Sensors.RelativePressure senRelPre(
    redeclare replaceable package Medium =MediumW)
    "Differential pressure"
  Buildings.Fluid.Sensors.TemperatureTwoPort TAirSup(
    redeclare replaceable package Medium = MediumA,
    m_flow_nominal=mAir_flow_nominal)
    "Supply air temperature"
  Buildings.Examples.ChillerPlant.BaseClasses.SimplifiedRoom roo(
    redeclare replaceable package Medium = MediumA,
    rooLen=50,
    rooWid=30,
    rooHei=3,
    m_flow_nominal=mAir_flow_nominal,
    QRoo_flow=500000,
    nPorts=2)
    "Room model"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val[numChi](
    redeclare each package Medium = MediumW,
    each m_flow_nominal=m1_flow_chi_nominal,
    each dpValve_nominal=6000,
    each use_strokeTime=false)
    "Shutoff valves"

  Modelica.Blocks.Sources.Constant TCHWSupSet(k=TCHWSet)
    "Chilled water supply temperature setpoint"
  Buildings.Applications.DataCenters.ChillerCooled.Controls.ChillerStage chiStaCon(
    QEva_nominal=QEva_nominal, tWai=0,
    criPoiTem=TCHWSet + 1.5)
    "Chiller staging control"
  Modelica.Blocks.Math.RealToBoolean chiOn[numChi]
    "Real value to boolean value"
  Modelica.Blocks.Math.IntegerToBoolean intToBoo(
    threshold=Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical))
    "Inverse on/off signal for the WSE"
  Modelica.Blocks.Logical.Not wseOn
    "True: WSE is on; False: WSE is off "
  Buildings.Applications.DataCenters.ChillerCooled.Controls.ConstantSpeedPumpStage CWPumCon(
    tWai=0)
    "Condenser water pump controller"
  Modelica.Blocks.Sources.IntegerExpression chiNumOn(
    y=integer(sum(chiStaCon.y)))
    "The number of running chillers"
  Modelica.Blocks.Math.Gain gai[numChi](
    each k=m1_flow_chi_nominal) "Gain effect"
  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingTowerSpeed cooTowSpeCon(
    yMin=0,
    Ti=60,
    k=0.1)
    "Cooling tower speed control"
  Modelica.Blocks.Sources.RealExpression TCWSupSet(
    y=min(29.44 + 273.15, max(273.15 + 15.56, cooTow[1].TAir + 3)))
    "Condenser water supply temperature setpoint"

  Modelica.Blocks.Sources.Constant TAirSupSet(k=TSupAirSet)
    "Supply air temperature setpoint"
  Buildings.Applications.BaseClasses.Controls.VariableSpeedPumpStage varSpeCon(
    tWai=tWai,
    m_flow_nominal=m2_flow_chi_nominal,
    deaBanSpe=0.45)
    "Speed controller"
  Modelica.Blocks.Sources.RealExpression mPum_flow(
    y=chiWSE.port_b2.m_flow)
    "Mass flowrate of variable speed pumps"
  Buildings.Controls.Continuous.LimPID pumSpe(
    Ti=40,
    yMin=0.2,
    k=0.1)
    "Pump speed controller"
  Modelica.Blocks.Sources.Constant dpSetSca(k=1)
    "Scaled differential pressure setpoint"
  Modelica.Blocks.Math.Product pumSpeSig[numChi]
    "Pump speed signal"
  Buildings.Controls.Continuous.LimPID ahuValSig(
        Ti=40,
    reverseActing=false,
    yMin=yValMinAHU,
    k=0.01)          "Valve position signal for the AHU"
  Modelica.Blocks.Math.Product cooTowSpe[numChi]
    "Cooling tower speed"

  Buildings.Controls.Continuous.LimPID ahuFanSpeCon(
        k=0.1,
    reverseActing=false,
    yMin=0.2,
    Ti=240)   "Fan speed controller "
  Modelica.Blocks.Sources.Constant TAirRetSet(k=TRetAirSet)
    "Return air temperature setpoint"
  Utilities.Psychrometrics.X_pTphi XAirSupSet(use_p_in=false)
    "Mass fraction setpoint of supply air "
  Modelica.Blocks.Sources.Constant phiAirRetSet(k=0.5)
    "Return air relative humidity setpoint"
  Modelica.Blocks.Math.Gain gai1(k=1/dpSetPoi) "Gain effect"
  Buildings.Controls.OBC.CDL.Reals.Switch swi[numChi]
    "Switch to assign pump signal if plant is on"
  Buildings.Controls.OBC.CDL.Logical.Or plaOn "Output true if plant is on"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[numChi](each final
            k=0) "Outputs zero"
  Modelica.Blocks.MathBoolean.Or chiOnSta(nu=numChi)
    "Output true if at least one chiller is on"
equation
  connect(chiWSE.port_b2, TCHWSup.port_a)
  connect(chiWSE.port_b1, TCWRet.port_a)
  for i in 1:numChi loop
    connect(TCWSup.port_a, cooTow[i].port_b)
    connect(pumCW[i].port_a, TCWSup.port_b)
    connect(TCWRet.port_b, val[i].port_a)
  connect(weaBus.TWetBul, cooTow[i].TAir)
  end for;
  connect(senRelPre.port_b, ahu.port_b1)
  connect(cooTow.port_a, val.port_b)

  connect(TCWRet.port_b, expVesCW.ports[1])
  connect(ahu.port_b1, expVesChi.ports[1])

  connect(chiWSE.port_b2, TCHWSup.port_a)
  connect(chiWSE.port_b1, TCWRet.port_a)
   for i in 1:numChi loop
    connect(TCWSup.port_a, cooTow[i].port_b)
    connect(pumCW[i].port_b, chiWSE.port_a1)
    connect(chiOn[i].y, chiWSE.on[i])
   connect(cooTowSpeCon.y, cooTowSpe[i].u1)
   end for;
  connect(chiStaCon.y, chiOn.u)
  connect(intToBoo.y, wseOn.u)
  connect(wseOn.y, chiWSE.on[numChi + 1])
  connect(CWPumCon.y, gai.u)
  connect(TCWSupSet.y, cooTowSpeCon.TCWSupSet)
  connect(TCHWSupSet.y, cooTowSpeCon.TCHWSupSet)
  connect(TCWSup.T, cooTowSpeCon.TCWSup)
  connect(TCHWSup.T, cooTowSpeCon.TCHWSup)
  connect(chiWSE.TSet, TCHWSupSet.y)
  connect(mPum_flow.y, varSpeCon.masFloPum)
  connect(senRelPre.port_a, ahu.port_a1)
  connect(pumSpe.y, varSpeCon.speSig)
  connect(dpSetSca.y, pumSpe.u_s)
  connect(pumSpe.y, pumSpeSig[1].u2)
  connect(pumSpe.y, pumSpeSig[2].u2)
  connect(varSpeCon.y, pumSpeSig.u1)
  connect(TAirSupSet.y, ahuValSig.u_s)
  connect(TAirSup.port_a, ahu.port_b2)
  connect(TAirSup.T, ahuValSig.u_m)
  connect(ahuValSig.y, ahu.uVal)
  connect(TAirSupSet.y, ahu.TSet)
  connect(CWPumCon.y, val.y)
  connect(CWPumCon.y, cooTowSpe.u2)
  connect(cooTowSpe.y, cooTow.y)
  connect(TCHWRet.port_a, ahu.port_b1)
  connect(chiNumOn.y, CWPumCon.numOnChi)
  connect(ahu.port_a2, roo.airPorts[1])

  connect(roo.airPorts[2], TAirSup.port_b)
  connect(roo.TRooAir, ahuFanSpeCon.u_m)
  connect(TAirRetSet.y, ahuFanSpeCon.u_s)
  connect(phiAirRetSet.y, XAirSupSet.phi)
  connect(XAirSupSet.X[1], ahu.XSet_w)
  connect(TAirRetSet.y, XAirSupSet.T)
  connect(ahuFanSpeCon.y, ahu.uFan)
  connect(gai1.y, pumSpe.u_m)
  connect(gai1.u, senRelPre.p_rel)
  connect(weaData.weaBus, weaBus)

  connect(chiOnSta.u, chiOn.y)
  connect(chiOnSta.y, plaOn.u1)
  connect(wseOn.y, plaOn.u2)
  connect(zer.y, swi.u3)
  for i in 1:numChi loop
    connect(plaOn.y, swi[i].u2)
  end for;
  connect(swi.y, pumCW.m_flow_in)
  connect(gai.y, swi.u1)
  connect(plaOn.y, varSpeCon.on)
end PartialDataCenter;


Post-processing. This partial model calculate performance metrics for a data center system.
The performance metrics include cooling mode signal switch times, economizing hours, and total
energy consumption.

within Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses;
partial model PostProcess "Post-processing"

  Buildings.Utilities.Math.IntegratorWithReset FCTim "Free cooling time"
  Modelica.Blocks.Sources.RealExpression freCooSig "Free cooling signal"
  Modelica.Blocks.Sources.RealExpression parMecCooSig
    "Partial mechanic cooling signal"
  Buildings.Utilities.Math.IntegratorWithReset PMCTim
    "Partial mechanic cooling time"
  Buildings.Utilities.Math.IntegratorWithReset FMCHou
    "Full mechanic cooling time"
  Modelica.Blocks.Sources.RealExpression fulMecCooSig
    "Full mechanic cooling signal"
  Modelica.Blocks.Sources.RealExpression PHVAC
   "Power consumed by HVAC system"
  Modelica.Blocks.Sources.RealExpression PIT
    "Power consumed by IT"
  Modelica.Blocks.Continuous.Integrator EHVAC(
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=0)
    "Energy consumed by HVAC"
  Modelica.Blocks.Continuous.Integrator EIT(
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=0)
    "Energy consumed by IT"
  Modelica.Blocks.Math.IntegerChange sigCha(
    u(start=0, fixed=true))
    "Signal changes"
  Modelica.Blocks.MathInteger.TriggeredAdd swiTim "Triggered addition"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(k=1)
    "Unit signal"
equation
  connect(freCooSig.y,FCTim. u)
  connect(parMecCooSig.y,PMCTim. u)
  connect(fulMecCooSig.y, FMCHou.u)
  connect(PHVAC.y,EHVAC. u)
  connect(PIT.y,EIT. u)
  connect(sigCha.y, swiTim.trigger)
  connect(conInt.y, swiTim.u)
end PostProcess;


within Buildings.Applications.DataCenters;
package DXCooled "Package for data centers that use DX cooling and air-based equipment cooling"
  extends Modelica.Icons.VariantsPackage;
end DXCooled;


Controller for airside economizer. This model implements an airside economizer controller to modulate the outdoor air damper
in order to maintain desired mixed air temperature.
When the airside economizer is open, which means the system is in free cooling or partial mechanical
cooling, the position of the OA damper is controlled by a PI controller to maintain a desired mixed air temperature;
otherwise, the position of the OA damper is set as closed.

within Buildings.Applications.DataCenters.DXCooled.Controls;
model AirsideEconomizer "Controller for airside economizer"

  parameter Real gai(min=Modelica.Constants.small) = 1
    "Gain of controller"
  parameter Modelica.Units.SI.Time Ti=50 "Integrator time"
  parameter Real minOAFra(min=0,max=1, final unit="1")
    "Minimum outdoor air fraction";

  Modelica.Blocks.Interfaces.RealInput TMixAirSet(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC") "Mixed air setpoint temperature"
  Modelica.Blocks.Interfaces.RealInput TMixAirMea(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC") "Measured mixed air temperature"
  Modelica.Blocks.Interfaces.IntegerInput cooMod
    "Cooling mode of the cooling system"
  Modelica.Blocks.Interfaces.RealOutput y
    "Connector of Real output signal"

  Buildings.Controls.Continuous.LimPID con(
    reverseActing=false,
    k=gai,
    yMin=minOAFra,
    final controllerType=Modelica.Blocks.Types.SimpleController.PI,
    Ti=Ti) "PID controller"
protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant const(final k=0)
    "Constant output signal with value 1"

  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(
    final k=Integer(Types.CoolingModes.FullMechanical))
    "Outputs signal for full mechanical cooling"

  Buildings.Controls.OBC.CDL.Integers.Equal ecoOff
    "Determine if airside economizer is off"
  Buildings.Controls.OBC.CDL.Reals.Switch switch1
    "Switch to select control output"

equation
  connect(TMixAirSet, con.u_s)
  connect(TMixAirMea, con.u_m)
  connect(switch1.y, y)
  connect(ecoOff.y, switch1.u2)
  connect(const.y, switch1.u1)
  connect(con.y, switch1.u3)
  connect(ecoOff.u2, conInt.y)
  connect(ecoOff.u1, cooMod)
end AirsideEconomizer;


Controller for compressor speed. This model implements a PI controller to maintain the supply air temperature at its setpoint by adjusting the compressor's speed.
When the free cooling is activated, the DX unit is deactivated by setting the speed signal as 0. In Partial Mechanical cooling and
Full Mechanical cooling, the PI controller works to adjust the compressor's speed.

within Buildings.Applications.DataCenters.DXCooled.Controls;
model Compressor "Controller for compressor speed"

  parameter Real k=0.5 "Gain of controller";
  parameter Modelica.Units.SI.Time Ti=240 "Time constant of integrator block";
  parameter Real yMax=1 "Upper limit of output";
  parameter Real yMin=0 "Lower limit of output";
  parameter Boolean reverseActing=false
    "Set to true for throttling the water flow rate through a cooling coil controller";

  Buildings.Controls.Continuous.LimPID dxSpe(
    Td=1,
    final controllerType=Modelica.Blocks.Types.SimpleController.PI,
    final k=k,
    final Ti=Ti,
    final yMax=yMax,
    final yMin=yMin,
    reverseActing=reverseActing,
    reset=Buildings.Types.Reset.Parameter,
    y_reset=yMin) "Controller for variable speed DX coil"
  Modelica.Blocks.Interfaces.IntegerInput cooMod
    "Cooling mode of the cooling system"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput y(
    min=0,
    max=1,
    final unit="1") "Compressor speed"
  Modelica.Blocks.Interfaces.RealInput TMixAirSet(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC") "Mixed air setpoint temperature"
  Modelica.Blocks.Interfaces.RealInput TMixAirMea(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC") "Measured mixed air temperature"
  Buildings.Controls.OBC.CDL.Logical.Not not1
    "Negation of signal to trigger the integrator reset"

protected
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant conInt(final k=Integer(
        Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling))
    "Outputs signal for full mechanical cooling"
  Buildings.Controls.OBC.CDL.Integers.Equal freCoo
    "Determine if free cooling is on"
  Buildings.Controls.OBC.CDL.Reals.Switch switch1
    "Switch to select control output"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant const(final k=0)
    "Constant output signal with value 1"

equation
  connect(cooMod, freCoo.u1)
  connect(conInt.y, freCoo.u2)
  connect(freCoo.y, switch1.u2)
  connect(const.y, switch1.u1)
  connect(dxSpe.y, switch1.u3)
  connect(switch1.y, y)
  connect(TMixAirSet, dxSpe.u_s)
  connect(TMixAirMea, dxSpe.u_m)
  connect(not1.y, dxSpe.trigger)
  connect(freCoo.y, not1.u)
end Compressor;


Controller for the DX cooling system with an airside economizer. This model implements a cooling mode controller for an air-cooled direct expansion (DX) cooling system
with an airside economizer. This controller is based on a simplified differential dry-bulb temperature
control strategy, as described in ASHRAE G36.

within Buildings.Applications.DataCenters.DXCooled.Controls;
model CoolingMode
  "Controller for the DX cooling system with an airside economizer"

  parameter Modelica.Units.SI.Time tWai
    "Waiting time, set to avoid frequent switching";
  parameter Modelica.Units.SI.TemperatureDifference dT(min=0.1) = 1.1
    "Deadband";

  Modelica.Blocks.Interfaces.RealInput TOutDryBul(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Dry-bulb temperature of outdoor air"
  Modelica.Blocks.Interfaces.RealInput TRet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Return air temperature"
  Modelica.Blocks.Interfaces.RealInput TSupSet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Supply air temperature setpoint "

  Modelica.Blocks.Interfaces.IntegerOutput y
    "Cooling mode signal, integer value of Buildings.Applications.DataCenters.Examples.BaseClasses.Types.CoolingMode"

  Modelica.StateGraph.Transition con1(
    enableTimer=true,
    waitTime=tWai,
    condition=TOutDryBul > TSupSet + dT)
    "Fire condition 1: free cooling to partially mechanical cooling"
  Modelica.StateGraph.StepWithSignal parMecCoo(nIn=2, nOut=2)
    "Partial mechanical cooling mode"
  Modelica.StateGraph.InitialStepWithSignal freCoo(nIn=1, nOut=1)
                                                          "Free cooling mode"
  Modelica.StateGraph.StepWithSignal fulMecCoo(nIn=1, nOut=1)
                                               "Fully mechanical cooling mode"
  Modelica.StateGraph.Transition con2(
    enableTimer=true,
    waitTime=tWai,
    condition=TOutDryBul > TRet + dT)
    "Fire condition 2: partially mechanical cooling to fully mechanical cooling"
  Modelica.StateGraph.Transition con3(
    enableTimer=true,
    waitTime=tWai,
    condition=TOutDryBul < TRet - dT)
    "Fire condition 3: fully mechanical cooling to partially mechanical cooling"
  Modelica.StateGraph.Transition con4(
    enableTimer=true,
    waitTime=tWai,
    condition=TOutDryBul < TSupSet - dT)
    "Fire condition 4: partially mechanical cooling to free cooling"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
  Modelica.Blocks.MathInteger.MultiSwitch swi(
    nu=3,
    y_default=0,
    expr={Integer(Types.CoolingModes.FreeCooling),
          Integer(Types.CoolingModes.PartialMechanical),
          Integer(Types.CoolingModes.FullMechanical)})
    "Switch boolean signals to real signal"
equation
  connect(freCoo.outPort[1],con1. inPort)
  connect(con1.outPort,parMecCoo. inPort[1])
  connect(con2.inPort,parMecCoo. outPort[1])
  connect(con2.outPort,fulMecCoo. inPort[1])
  connect(fulMecCoo.outPort[1],con3. inPort)
  connect(con4.outPort,freCoo. inPort[1])
  connect(con3.outPort,parMecCoo. inPort[2])
  connect(con4.inPort,parMecCoo. outPort[2])
  connect(swi.u[1],freCoo. active)
  connect(parMecCoo.active,swi. u[2])
  connect(fulMecCoo.active,swi. u[3])
  connect(y, swi.y)
end CoolingMode;


within Buildings.Applications.DataCenters.DXCooled;
package Controls "Package with controllers for DX-cooled data centers"
  extends Modelica.Icons.Package;
end Controls;


within Buildings.Applications.DataCenters.DXCooled.Controls.Validation;
model AirsideEconomizer
  "Example that demonstrate the use of model
  Buildings.Applications.DataCenters.DXCooled.Controls.AirsideEconomizer"
  extends Modelica.Icons.Example;
  replaceable package Medium =
      Buildings.Media.Air;
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=0.43
    "Nominal air flowrate";
  Buildings.Applications.DataCenters.DXCooled.Controls.AirsideEconomizer con(
    minOAFra= 0,
    Ti=1) "Outdoor air damper controller"
  Modelica.Blocks.Sources.Constant mixAirSetPoi(k=291.15)
    "Mixed air temperature setpoint"
  Modelica.Blocks.Sources.CombiTimeTable cooMod(
    table=[0,  Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling);
           120,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling);
           120,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical);
           240,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical);
           240,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical);
           360,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)])
    "Cooling mode signal"

  Buildings.Fluid.Sources.Boundary_pT OA(
    redeclare package Medium = Medium,
    nPorts=2,
    use_T_in=true,
    p(displayUnit="Pa") = 100000)
    "Boundary conditions for outside air"
  Buildings.Fluid.Actuators.Dampers.MixingBox eco(
    redeclare package Medium = Medium,
    mOut_flow_nominal=mA_flow_nominal,
    mRec_flow_nominal=mA_flow_nominal,
    mExh_flow_nominal=mA_flow_nominal,
    use_strokeTime=false,
    dpDamExh_nominal=0.27,
    dpDamOut_nominal=0.27,
    dpDamRec_nominal=0.27,
    dpFixExh_nominal=20,
    dpFixOut_nominal=20,
    dpFixRec_nominal=20) "Airside economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemMixAir(
    redeclare package Medium = Medium,
    m_flow_nominal=mA_flow_nominal)
    "Temperature sensor for mixed air"
  Buildings.Fluid.Sources.Boundary_pT roo(
    redeclare package Medium = Medium,
    nPorts=1,
    p=100000 + 30,
    T(displayUnit="degC") = 298.15) "Boundary conditions for room air"
  Modelica.Blocks.Sources.CombiTimeTable outAir(table=[0,273.15 + 5; 120,273.15
         + 5; 120,273.15 + 20; 240,273.15 + 20; 240,273.15 + 30; 360,273.15 +
        30]) "Outdoor air temperature"
  Buildings.Fluid.Sources.Boundary_pT supAir(
    redeclare package Medium = Medium,
    nPorts=1,
    p(displayUnit="Pa") = 100000 - 30) "Boundary conditions for supply air"
  Modelica.Blocks.Math.RealToInteger reaToInt "Conversion from real to integer"
equation
  connect(mixAirSetPoi.y, con.TMixAirSet)
  connect(OA.ports[1], eco.port_Out)
  connect(eco.port_Exh, OA.ports[2])
  connect(eco.port_Sup,senTemMixAir. port_a)
  connect(senTemMixAir.T, con.TMixAirMea)
  connect(con.y, eco.y)
  connect(eco.port_Ret, roo.ports[1])
  connect(outAir.y[1], OA.T_in)
  connect(senTemMixAir.port_b, supAir.ports[1])
  connect(con.cooMod, reaToInt.y)
  connect(cooMod.y[1], reaToInt.u)
end AirsideEconomizer;


Example that demonstrates the use of a speed controller for DX coil. This example demonstrates how the speed signal of a variable-speed DX unit can be controlled.
The detailed control logic can be
refered in

Buildings.Applications.DataCenters.DXCooled.Controls.Compressor.

within Buildings.Applications.DataCenters.DXCooled.Controls.Validation;
model Compressor
  "Example that demonstrates the use of a speed controller for DX coil"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.DXCooled.Controls.Compressor dxSpeCon
    "Speed controller for a variable DX coil"
  Modelica.Blocks.Sources.Constant TSupSet(k=291.15)
    "Supply air temperature setpoint"
  Modelica.Blocks.Sources.Sine TSupMea(
    amplitude=2,
    f=1/120,
    offset=291.15) "Measured supply air temperature"

  Modelica.Blocks.Sources.CombiTimeTable cooMod(
    table=[0,  Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling);
           120,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling);
           120,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical);
           240,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical);
           240,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical);
           360,Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)])
    "Cooling mode signal"
  Modelica.Blocks.Math.RealToInteger reaToInt "Conversion from real to integer"
equation
  connect(TSupSet.y, dxSpeCon.TMixAirSet)
  connect(TSupMea.y, dxSpeCon.TMixAirMea)
  connect(cooMod.y[1], reaToInt.u)
  connect(reaToInt.y, dxSpeCon.cooMod)
end Compressor;


Example that demonstrates the use of cooling mode selection for the airside economizer. This example demonstrates how the cooling mode signal can be generated
according to varying outside air dry bulb temperature,
outside air dewpoint temperature, return air temperature and
supply air temperature setpoint.The detailed control logic can be
refered in

Buildings.Applications.DataCenters.DXCooled.Controls.CoolingMode.

within Buildings.Applications.DataCenters.DXCooled.Controls.Validation;
model CoolingMode
  "Example that demonstrates the use of cooling mode selection for the airside economizer"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.DXCooled.Controls.CoolingMode
    cooModCon(tWai=1200)
    "Cooling mode controller for the DX cooling system with an airside economizer"
  Modelica.Blocks.Sources.Constant TSupSet(k=291.15)
    "Supply air temperature setpoint"
  Modelica.Blocks.Sources.Constant TRet(k=295.15) "Return air temperature"
  BoundaryConditions.WeatherData.ReaderTMY3  weaDat(
    pAtmSou=Buildings.BoundaryConditions.Types.DataSource.Parameter,
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"

equation
  connect(TSupSet.y, cooModCon.TSupSet)
  connect(TRet.y, cooModCon.TRet)
  connect(weaDat.weaBus,weaBus)
  connect(weaBus.TDryBul, cooModCon.TOutDryBul)
end CoolingMode;


Collection of validation models

within Buildings.Applications.DataCenters.DXCooled.Controls;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


within Buildings.Applications.DataCenters.DXCooled.Examples;
model DXCooledAirsideEconomizer
  "Example that illustrates the use of Buildings.Fluid.HeatExchanger.DXCoil in a data center room"
  extends Modelica.Icons.Example;
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Examples.BaseClasses.PostProcess(
    fulMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FullMechanical)
      then 1 else 0),
    parMecCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.PartialMechanical)
      then 1 else 0),
    PHVAC(y=varSpeDX.P + fan.P),
    PIT(y=roo.QRoo_flow),
    freCooSig(
      y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
      then 1 else 0));

  replaceable package Medium = Buildings.Media.Air "Medium model";

  // Air temperatures at design conditions
  parameter Modelica.Units.SI.Temperature TASup_nominal=286.15
    "Nominal air temperature supplied to room";
  parameter Modelica.Units.SI.Temperature TRooSet=298.15
    "Nominal room air temperature";
  parameter Modelica.Units.SI.Temperature TAirSupSet=291.13
    "Nominal room air temperature";
 /////////////////////////////////////////////////////////
  // Cooling loads
  parameter Modelica.Units.SI.HeatFlowRate QRooInt_flow=500000
    "Internal heat gains of the room";
  parameter Modelica.Units.SI.HeatFlowRate QRooC_flow_nominal=-2*QRooInt_flow;
 ////////////////////////////////////////////////////////////
 // DX Coil
  parameter Modelica.Units.SI.MassFlowRate mA_flow_nominal=QRooC_flow_nominal/
      1006/(TASup_nominal - TRooSet) "Nominal air mass flow rate";
  parameter Modelica.Units.SI.HeatFlowRate QCoiC_flow_nominal=
      QRooC_flow_nominal "Cooling load of coil";
  parameter Real minSpeFan = 0.2
    "Minimum fan speed ratio required by variable speed fans";

  Buildings.Examples.ChillerPlant.BaseClasses.SimplifiedRoom roo(
    redeclare package Medium = Medium,
    rooLen=50,
    rooHei=3,
    rooWid=40,
    QRoo_flow=QRooInt_flow,
    m_flow_nominal=mA_flow_nominal,
    nPorts=2) "Simplified data center room"
  Buildings.Fluid.DXSystems.Cooling.AirSource.VariableSpeed varSpeDX(
    redeclare package Medium = Medium,
    dp_nominal=400,
    datCoi=datCoi,
    minSpeRat=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    show_T=true,
    T_start=303.15)
    "Variable speed DX coil"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    pAtmSou=Buildings.BoundaryConditions.Types.DataSource.Parameter,
    filNam=Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data reader"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"
  Buildings.Fluid.Movers.SpeedControlled_y fan(
    redeclare package Medium = Medium,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    addPowerToMedium=false,
    per(pressure(V_flow=mA_flow_nominal*{0,2}/1.2, dp=500*{2,0})),
    use_riseTime=true) "Supply air fan"
  Modelica.Blocks.Sources.Constant TRooAirSet(k=TRooSet)
    "Room air temperature setpoint"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemSupAir(
   redeclare package Medium = Medium,
   m_flow_nominal=mA_flow_nominal)
    "Temperature sensor for supply air"
  Modelica.Blocks.Sources.Constant SATSetPoi(k=TAirSupSet)
    "Supply air temperature set point"
  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=QCoiC_flow_nominal*(3/8),
          COP_nominal=3,
          SHR_nominal=0.8,
          TEvaIn_nominal=TRooSet,
          m_flow_nominal=mA_flow_nominal),
        perCur=
        Buildings.Fluid.DXSystems.Cooling.AirSource.Examples.PerformanceCurves.Curve_I()),
     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=QCoiC_flow_nominal*(1/2),
          COP_nominal=3,
          SHR_nominal=0.8,
          TEvaIn_nominal=TRooSet,
          m_flow_nominal=mA_flow_nominal),
        perCur=
        Buildings.Fluid.DXSystems.Cooling.AirSource.Examples.PerformanceCurves.Curve_I()),
     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=QCoiC_flow_nominal*(3/4),
          COP_nominal=3,
          SHR_nominal=0.8,
          TEvaIn_nominal=TRooSet,
          m_flow_nominal=mA_flow_nominal),
        perCur=
        Buildings.Fluid.DXSystems.Cooling.AirSource.Examples.PerformanceCurves.Curve_II()),
     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=QCoiC_flow_nominal,
          COP_nominal=3,
          SHR_nominal=0.8,
          TEvaIn_nominal=TRooSet,
          m_flow_nominal=mA_flow_nominal),
        perCur=
        Buildings.Fluid.DXSystems.Cooling.AirSource.Examples.PerformanceCurves.Curve_III())})
        "Coil data"
  Buildings.Fluid.Actuators.Dampers.MixingBox eco(
    redeclare package Medium = Medium,
    mOut_flow_nominal=mA_flow_nominal,
    mRec_flow_nominal=mA_flow_nominal,
    mExh_flow_nominal=mA_flow_nominal,
    use_strokeTime=false,
    dpDamExh_nominal=0.27,
    dpDamOut_nominal=0.27,
    dpDamRec_nominal=0.27,
    dpFixExh_nominal=20,
    dpFixOut_nominal=20,
    dpFixRec_nominal=20) "Airside economizer"
  Buildings.Fluid.Sources.Outside out(
    redeclare package Medium = Medium,
    nPorts=2)
    "Boundary conditions for outside air"
  Buildings.Applications.DataCenters.DXCooled.Controls.CoolingMode cooModCon(
    dT=1,
    tWai=120)
    "Cooling mode controller"
  Buildings.Fluid.Actuators.Dampers.Exponential dam1(
    redeclare package Medium = Medium,
    m_flow_nominal=mA_flow_nominal,
    dpDamper_nominal=0.27)
    "Open only when free cooling mode is activated"
  Buildings.Fluid.Actuators.Dampers.Exponential dam2(
    redeclare package Medium = Medium,
    m_flow_nominal=mA_flow_nominal,
    y_start=0,
    dpDamper_nominal=0.27) "Open when mechanical cooling is activated"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTemMixAir(
    redeclare package Medium = Medium,
    m_flow_nominal=mA_flow_nominal)
    "Temperature sensor for mixed air"
  Buildings.Applications.DataCenters.DXCooled.Controls.AirsideEconomizer ecoCon(
    minOAFra=0.05,
    Ti=240,
    gai=0.5)
    "Economzier controller"
  Modelica.Blocks.Sources.RealExpression freCoo(
    y=if cooModCon.y == Integer(Buildings.Applications.DataCenters.Types.CoolingModes.FreeCooling)
    then 1 else 0)
    "Set true if free cooling mode is on"
  Modelica.Blocks.Math.Feedback feedback1
    "Feedback signal"
  Modelica.Blocks.Sources.Constant const(k=1)
    "Constant output with value 1"
  Buildings.Controls.Continuous.LimPID fanSpe(
    Td=1,
    yMin=minSpeFan,
    Ti=240,
    k=0.5,
    reverseActing=false)
    "Fan speed controller"
  Buildings.Applications.DataCenters.DXCooled.Controls.Compressor speCon(
     k=1,
     Ti=120)
    "Speed controller for DX units"
equation
  connect(weaDat.weaBus, weaBus)
  connect(fan.port_a, senTemSupAir.port_b)
  connect(senTemSupAir.port_a, varSpeDX.port_b)
  connect(weaBus, out.weaBus)
  connect(dam2.port_b, varSpeDX.port_a)
  connect(dam1.port_b, senTemSupAir.port_a)
  connect(SATSetPoi.y, cooModCon.TSupSet)
  connect(eco.port_Sup, senTemMixAir.port_a)
  connect(senTemMixAir.port_b, dam1.port_a)
  connect(senTemMixAir.port_b, dam2.port_a)
  connect(SATSetPoi.y, ecoCon.TMixAirSet)
  connect(senTemMixAir.T, ecoCon.TMixAirMea)
  connect(ecoCon.y, eco.y)
  connect(feedback1.y, dam2.y)
  connect(out.ports[1], eco.port_Out)
  connect(eco.port_Exh, out.ports[2])
  connect(weaBus.TDryBul, cooModCon.TOutDryBul)
  connect(fan.port_b, roo.airPorts[1])
  connect(eco.port_Ret, roo.airPorts[2])
  connect(const.y, feedback1.u1)
  connect(cooModCon.y, ecoCon.cooMod)
  connect(TRooAirSet.y, fanSpe.u_s)
  connect(roo.TRooAir, fanSpe.u_m)
  connect(fanSpe.y, fan.y)
  connect(roo.TRooAir, cooModCon.TRet)
  connect(cooModCon.y, sigCha.u)
  connect(freCoo.y, dam1.y)
  connect(freCoo.y, feedback1.u2)
  connect(SATSetPoi.y, speCon.TMixAirSet)
  connect(senTemSupAir.T, speCon.TMixAirMea)
  connect(cooModCon.y, speCon.cooMod)
  connect(speCon.y, varSpeDX.speRat)
  connect(weaBus.TDryBul, varSpeDX.TOut)
end DXCooledAirsideEconomizer;


within Buildings.Applications.DataCenters.DXCooled;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Base icon. Basic class that provides a label with the component name above the icon.

within Buildings.BaseClasses;
block BaseIcon "Base icon"
end BaseIcon;


Base icon with model name below the icon. Basic class that provides a label with the component name below the icon.

within Buildings.BaseClasses;
block BaseIconLow "Base icon with model name below the icon"

end BaseIconLow;


within Buildings;
package BaseClasses "Package with base classes for the Buildings library"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


within Buildings;
package BoundaryConditions "Package with models for boundary conditions"
  extends Modelica.Icons.Package;
end BoundaryConditions;


Package with type definitions

within Buildings.BoundaryConditions;
package Types "Package with type definitions"
 extends Modelica.Icons.TypesPackage;
  type DataSource = enumeration(
      File "Use data from file",
      Parameter "Use parameter",
      Input "Use input connector") "Enumeration to define data source"

  type RadiationDataSource = enumeration(
      File "Use data from file",
      Input_HGloHor_HDifHor
        "Global horizontal and diffuse horizontal radiation from connector",
      Input_HDirNor_HDifHor
        "Direct normal and diffuse horizontal radiation from connector",
      Input_HDirNor_HGloHor
        "Direct normal and global horizontal radiation from connector")
    "Enumeration to define solar radiation data source"
  type SkyTemperatureCalculation = enumeration(
      HorizontalRadiation
        "Use horizontal irradiation",
      TemperaturesAndSkyCover
        "Use dry-bulb and dew-point temperatures and sky cover")
    "Enumeration for computation of sky temperature"
end Types;


User's Guide

within Buildings.BoundaryConditions;
package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;
end UsersGuide;


Surface temperature climatic constants

within Buildings.BoundaryConditions.GroundTemperature;
package ClimaticConstants "Surface temperature climatic constants"
  extends Modelica.Icons.MaterialPropertiesPackage;

  record Generic "Generic climatic constants"
    extends Modelica.Icons.Record;
    parameter Modelica.Units.SI.Temperature TSurMea
      "Mean annual surface temperature";
    parameter Modelica.Units.SI.TemperatureDifference TSurAmp
      "Surface temperature amplitude";
    parameter Modelica.Units.SI.Duration sinPha(displayUnit="d")
      "Phase lag of soil surface temperature";
  end Generic;

  record Boston =
    Buildings.BoundaryConditions.GroundTemperature.ClimaticConstants.Generic (
      TSurMea=284.23,
      TSurAmp=11.57,
      sinPha=9944640) "Boston";

  record NewYork =
    Buildings.BoundaryConditions.GroundTemperature.ClimaticConstants.Generic (
      TSurMea=286.03,
      TSurAmp=11.45,
      sinPha=9728640) "New York";

  record SanFrancisco =
    Buildings.BoundaryConditions.GroundTemperature.ClimaticConstants.Generic (
      TSurMea=287.64,
      TSurAmp=3.35,
      sinPha=10419840) "San Francisco";
end ClimaticConstants;


within Buildings.BoundaryConditions;
package GroundTemperature "Package with models to compute ground temperature"
  extends Modelica.Icons.VariantsPackage;
end GroundTemperature;


Undisturbed soil temperature. This model provides a prescribed temperature boundary condition for buried objects,
where the temperature is computed per the ASCE (1996) equation:

within Buildings.BoundaryConditions.GroundTemperature;
model UndisturbedSoilTemperature "Undisturbed soil temperature"
  parameter Modelica.Units.SI.Length dep "Depth";

  parameter Boolean useNFac = false
    "= true, use n-factors to correct climatic constants";
  parameter Real nFacTha = 1 "Thawing n-factor (TAir > 0degC)"
  parameter Real nFacFre = 1 "Freezing n-factor (TAir <= 0degC)"

  parameter Boolean useCon = false
    "= true, includes convection between air and surface coupling";
  parameter Real hSur(unit="W/(m2.K)", min=0) = 25
    "Surface convective heat transfer coefficient"

  replaceable parameter Buildings.HeatTransfer.Data.Soil.Generic
    soiDat "Soil thermal properties";
  replaceable parameter ClimaticConstants.Generic
    cliCon "Surface temperature climatic conditions";

  Modelica.Units.SI.Temperature T "Undisturbed soil temperature at depth dep";

protected
  constant Modelica.Units.SI.Angle pi=Modelica.Constants.pi;
  constant Modelica.Units.SI.Duration Year=365.2422*24*60*60
    "Annual period length";

  parameter Modelica.Units.SI.Length corDep=if useCon then dep + soiDat.k/hSur
       else dep "Convection-corrected depth";
  parameter ClimaticConstants.Generic corCliCon= if useNFac
    then BaseClasses.surfaceTemperature(cliCon=cliCon, nFacTha=nFacTha, nFacFre=nFacFre)
    else cliCon
    "<i>n</i>-factor corrected climatic constants";

  parameter Modelica.Units.SI.ThermalDiffusivity soiDif=soiDat.k/soiDat.c/
      soiDat.d "Soil diffusivity";
  parameter Modelica.Units.SI.Duration timLag=corCliCon.sinPha
    "Start time of surface temperature sinusoid";
  parameter Real pha = - corDep * (pi/soiDif/Year)^0.5
    "Phase angle of ground temperature sinusoid";

initial equation
  assert(not (useCon and useNFac),
    "N-Factors and surface convection corrections
    would typically not be used simultaneously",
    level = AssertionLevel.warning);

equation
  T = corCliCon.TSurMea + corCliCon.TSurAmp * exp(pha) *
    sin(2*pi*(time-timLag)/Year + pha);
end UndisturbedSoilTemperature;


within Buildings.BoundaryConditions.GroundTemperature;
package BaseClasses "Package with base classes for Buildings.BoundaryConditions.GroundTemperature"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Example model for undisturbed soil temperature with surface convection correction. This example model showcases the use of the convection coefficient
correction, which allows to specify the heat transfer rate between
the air and the surface temperature.

within Buildings.BoundaryConditions.GroundTemperature.Examples;
model CorrectedConvection
  "Example model for undisturbed soil temperature with surface convection correction"
  extends UndisturbedSoilTemperature(TSoi(each useCon=true, each hSur=5));
end CorrectedConvection;


Example model for undisturbed soil temperature with n-factors correction. This example model showcases the use of n-factors, which are used
to correct the surface temperature given the ratio of freezing/thawing
degree days (FDD/TDD) between the air and the ground.

within Buildings.BoundaryConditions.GroundTemperature.Examples;
model CorrectedNFactors
  "Example model for undisturbed soil temperature with n-factors correction"
  extends UndisturbedSoilTemperature(
    TSoi(each useNFac=true, each nFacTha=1.7, each nFacFre=0.66));
end CorrectedNFactors;


within Buildings.BoundaryConditions.GroundTemperature;
package Examples "Collection of models that illustrate model use and test models"
  extends Modelica.Icons.ExamplesPackage;
end Examples;


Example model for undisturbed soil temperature. This example model illustrates how the undisturbed soil temperature model
decreases seasonal temperature oscillations and increases delay as depth is
increasing.

within Buildings.BoundaryConditions.GroundTemperature.Examples;
model UndisturbedSoilTemperature "Example model for undisturbed soil temperature"
  extends Modelica.Icons.Example;

  parameter Integer nSoi = 4 "Number of probed depths";
  parameter Modelica.Units.SI.Length dep[nSoi]={0,2,5,9} "Probed depths";

  Buildings.BoundaryConditions.GroundTemperature.UndisturbedSoilTemperature
    TSoi[nSoi](dep=dep, each cliCon=cliCon, each soiDat=soiDat)
    "Undisturbed soil temperatures"

protected
  replaceable parameter ClimaticConstants.Boston cliCon
    "Surface temperature climatic conditions";
  replaceable parameter Buildings.HeatTransfer.Data.Soil.Generic soiDat(
    k=1.58,c=1150,d=1600) "Soil thermal properties";
end UndisturbedSoilTemperature;


Calculate black body sky temperature. This component computes the black-body sky temperature.

within Buildings.BoundaryConditions.SkyTemperature;
block BlackBody "Calculate black body sky temperature"
  extends Modelica.Blocks.Icons.Block;

  parameter Buildings.BoundaryConditions.Types.SkyTemperatureCalculation calTSky=
    Buildings.BoundaryConditions.Types.SkyTemperatureCalculation.TemperaturesAndSkyCover
    "Computation of black-body sky temperature"
  Modelica.Blocks.Interfaces.RealInput TDryBul(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Dry bulb temperature at ground level"
  Modelica.Blocks.Interfaces.RealInput TDewPoi(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC") "Dew point temperature"
  Modelica.Blocks.Interfaces.RealInput nOpa( min=0, max=1, unit="1")
    "Opaque sky cover [0, 1]"
  Modelica.Blocks.Interfaces.RealOutput TBlaSky(
    final quantity="ThermodynamicTemperature",
    displayUnit="degC",
    final unit="K") "Black-body sky temperature"
  Modelica.Blocks.Interfaces.RealInput HHorIR(
    unit="W/m2",
    min=0,
    nominal=100) "Horizontal infrared irradiation"
protected
  Modelica.Units.SI.Temperature TDewPoiK "Dewpoint temperature";
  Modelica.Units.SI.Emissivity epsSky "Black-body absorptivity of sky";
  Real nOpa10(min=0, max=10) "Opaque sky cover in [0, 10]";
equation
  if calTSky == Buildings.BoundaryConditions.Types.SkyTemperatureCalculation.TemperaturesAndSkyCover then
    TDewPoiK =  Buildings.Utilities.Math.Functions.smoothMin(TDryBul, TDewPoi, 0.1);
    nOpa10 =  10*nOpa "Input nOpa is scaled to [0,1] instead of [0,10]";
    epsSky =  (0.787 + 0.764*Modelica.Math.log(-TDewPoiK/Modelica.Constants.T_zero))*(1 + 0.0224*nOpa10 -
      0.0035*(nOpa10^2) + 0.00028*(nOpa10^3));
    TBlaSky =  TDryBul*(epsSky^0.25);
  else
    TDewPoiK =  273.15;
    nOpa10   =  0.0;
    epsSky   =  0.0;
    TBlaSky  =  (HHorIR/Modelica.Constants.sigma)^0.25;
  end if;
end BlackBody;


within Buildings.BoundaryConditions;
package SkyTemperature "Package with models to compute the sky temperature"
  extends Modelica.Icons.VariantsPackage;
end SkyTemperature;