Test the model ChillerWSE.Examples.BaseClasses.ChillerStageControl. This example test the chiller staging controller implemented in

Buildings.Applications.DataCenters.ChillerCooled.Controls.ChillerStage.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model ChillerStage
  "Test the model ChillerWSE.Examples.BaseClasses.ChillerStageControl"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.ChillerStage chiStaCon(
    tWai=30,
    QEva_nominal=-100*3.517*1000,
    dT=0.5)
    "Staging controller for chillers"
  Modelica.Blocks.Sources.Constant QTot(
    k=0.55*chiStaCon.QEva_nominal)
    "Total cooling load in chillers"
  Modelica.Blocks.Sources.IntegerTable cooMod(
    table=[0,0;
           360,1;
           720,2;
           1080,3])
    "Cooling mode"
  Modelica.Blocks.Sources.Pulse TCHWSup(
    amplitude=2,
    period=360,
    offset=273.15 + 5) "WSE chilled water supply temperature"
equation
  connect(QTot.y, chiStaCon.QTot)
  connect(cooMod.y, chiStaCon.cooMod)
  connect(TCHWSup.y, chiStaCon.TCHWSup)
end ChillerStage;


Test the model ChillerWSE.Examples.BaseClasses.ConstatnSpeedPumpStageControl. This example test how the number of required constant-speed pumps varies
based on cooling mode signals and the number of running chillers. Detailed
control logic can be found in

Buildings.Applications.DataCenters.ChillerCooled.Controls.ConstantSpeedPumpStage.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model ConstantSpeedPumpStage
  "Test the model ChillerWSE.Examples.BaseClasses.ConstatnSpeedPumpStageControl"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.ConstantSpeedPumpStage
  conSpePumSta(
    tWai=30)
    "Staging controller for constant speed pumps"
  Modelica.Blocks.Sources.IntegerTable cooMod(
    table=[0,0; 360,1;
           720,2; 1080,3])
    "Cooling mode"
  Modelica.Blocks.Sources.IntegerTable chiNumOn(
    table=[0,0; 360,1; 540,2; 720,1;
           900,2; 1080,1; 1260,2; 1440,1])
    "The number of running chillers"
equation
  connect(cooMod.y, conSpePumSta.cooMod)
  connect(chiNumOn.y,conSpePumSta.numOnChi)
end ConstantSpeedPumpStage;


Test the model ChillerWSE.Examples.BaseClasses.CoolingModeController. This model tests the cooling mode controller implemented in

Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingMode.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model CoolingMode
  "Test the model ChillerWSE.Examples.BaseClasses.CoolingModeController"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingMode
  cooModCon(
    deaBan1=1,
    deaBan2=1,
    tWai=30,
    deaBan3=1,
    deaBan4=1)
    "Cooling mode controller used in integrared waterside economizer chilled water system"
  Modelica.Blocks.Sources.Pulse TCHWLeaWSE(
    period=300,
    amplitude=15,
    offset=273.15 + 5) "WSE chilled water supply temperature"
  Modelica.Blocks.Sources.Constant TWetBub(k=273.15 + 5) "Wet bulb temperature"
  Modelica.Blocks.Sources.Constant TAppTow(k=5) "Cooling tower approach"
  Modelica.Blocks.Sources.Constant TCHWEntWSE(k=273.15 + 12)
    "Chilled water return temperature in waterside economizer"
  Modelica.Blocks.Sources.Constant TCHWLeaSet(k=273.15 + 10)
    "Chilled water supply temperature setpoint"
equation
  connect(TCHWLeaSet.y, cooModCon.TCHWSupSet)
  connect(TWetBub.y, cooModCon.TWetBul)
  connect(TAppTow.y, cooModCon.TApp)
  connect(TCHWLeaWSE.y, cooModCon.TCHWSupWSE)
  connect(TCHWEntWSE.y, cooModCon.TCHWRetWSE)
end CoolingMode;


Example that illustrates the use of Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingModeNonIntegrated. This model tests the cooling mode controller implemented in

Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingModeNonIntegrated.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model CoolingModeNonIntegrated
  "Example that illustrates the use of Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingModeNonIntegrated"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingModeNonIntegrated
  cooModCon(
    tWai=30,
    deaBan=1,
    TSwi=280.15)
    "Cooling mode controller used in integrared waterside economizer chilled water system"
  Modelica.Blocks.Sources.Pulse TCHWSup(
    period=300,
    amplitude=2,
    offset=273.15 + 7) "WSE chilled water supply temperature"
  Modelica.Blocks.Sources.Sine TWetBub(
    amplitude=4,
    f=1/300,
    offset=273.15 + 8) "Wet bulb temperature"
  Modelica.Blocks.Sources.Constant TCHWSupSet(k=273.15 + 10)
    "Chilled water supply temperature setpoint"
  Modelica.Blocks.Sources.IntegerTable chiNumOn(table=[0,0; 360,1; 540,2; 720,1;
        900,2])
    "The number of running chillers"
equation
  connect(TCHWSupSet.y, cooModCon.TCHWSupSet)
  connect(TWetBub.y, cooModCon.TWetBul)
  connect(TCHWSup.y, cooModCon.TCHWSup)
  connect(chiNumOn.y, cooModCon.numOnChi)
end CoolingModeNonIntegrated;


Test the model ChillerWSE.Examples.BaseClasses.CoolingTowerSpeedControl. This example tests the controller for the cooling tower fan speed. Detailed control logic can be found in

Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingTowerSpeed.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model CoolingTowerSpeed
  "Test the model ChillerWSE.Examples.BaseClasses.CoolingTowerSpeedControl"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.CoolingTowerSpeed
    cooTowSpeCon(controllerType=Modelica.Blocks.Types.SimpleController.PI)
    "Cooling tower speed controller"
  Modelica.Blocks.Sources.Sine CHWST(
    amplitude=2,
    f=1/360,
    offset=273.15 + 5) "Chilled water supply temperature"
  Modelica.Blocks.Sources.Constant CWSTSet(k=273.15 + 20)
    "Condenser water supply temperature setpoint"
  Modelica.Blocks.Sources.Sine CWST(
    amplitude=5,
    f=1/360,
    offset=273.15 + 20) "Condenser water supply temperature"
  Modelica.Blocks.Sources.Constant CHWSTSet(k=273.15 + 6)
    "Chilled water supply temperature setpoint"
  Modelica.Blocks.Sources.IntegerTable cooMod(table=[0,1; 360,2; 720,3])
    "Cooling mode"
equation
  connect(CWSTSet.y, cooTowSpeCon.TCWSupSet)
  connect(CHWSTSet.y, cooTowSpeCon.TCHWSupSet)
  connect(CWST.y, cooTowSpeCon.TCWSup)
  connect(CHWST.y, cooTowSpeCon.TCHWSup)
  connect(cooMod.y, cooTowSpeCon.cooMod)
end CoolingTowerSpeed;


Collection of validation models

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


Test model for reheater controller. This example tests the reheater controller with two varing input error signals.

within Buildings.Applications.DataCenters.ChillerCooled.Controls.Validation;
model Reheat "Test model for reheater controller"
  extends Modelica.Icons.Example;

  Buildings.Applications.DataCenters.ChillerCooled.Controls.Reheat heaCon(
    yValSwi=0.2,
    yValDeaBan=0.1,
    dTSwi=0,
    dTDeaBan=0.5,
    tWai=60) "Heater on/off controller"
  Modelica.Blocks.Sources.Sine sig1(
    amplitude=0.3,
    offset=0.3,
    f=1/1200) "Signal 1"
  Modelica.Blocks.Sources.Sine sig2(
    amplitude=3,
    offset=273.15 + 15,
    f=1/1200,
    phase=1.0471975511966) "Signal 2"
  Modelica.Blocks.Sources.Constant set1(k=0.2) "Set point for signal 1"
  Modelica.Blocks.Sources.Constant set2(k=273.15 + 16) "Set point for signal 2"
  Modelica.Blocks.Math.Add add1(k1=+1, k2=-1)
    "Error between signal 1 and setpoint 1"
  Modelica.Blocks.Math.Add add2(k1=+1, k2=-1)
    "Error between signal 2 and setpoint 2"
equation
  connect(sig1.y, add1.u1)
  connect(set1.y, add1.u2)
  connect(add1.y, heaCon.yVal)
  connect(sig2.y, add2.u1)
  connect(set2.y, add2.u2)
  connect(add2.y,heaCon.dT)
end Reheat;


Rangeability, R=50...100 typically

within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model CoolingCoilHumidifyingHeating
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialCoolingCoilHumidifyingHeating(
    redeclare Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage watVal(
      final R=R,
      final delta0=delta0),
    redeclare final Buildings.Fluid.Movers.SpeedControlled_y fan(y_start=yFan_start));

  // Parameters for water-side valve
  parameter Real R=50 "Rangeability, R=50...100 typically"
  parameter Real delta0=0.01
    "Range of significant deviation from equal percentage law"

  // Parameters for electric heater
  parameter Modelica.Units.SI.Time tauEleHea=10
    "Time constant at nominal flow for electric heater (if energyDynamics <> SteadyState)"
  parameter Modelica.Units.SI.Efficiency etaHea=1.0
    "Efficiency of electrical heater"
  parameter Modelica.Units.SI.HeatFlowRate QHeaMax_flow(min=0)
    "Nominal heating capacity of eletric heater,positive"
  // Parameters for humidifier
  parameter Modelica.Units.SI.MassFlowRate mWatMax_flow(min=0)
    "Nominal humidification capacity for humidifier, positive for humidification"
  parameter Modelica.Units.SI.Temperature THum=293.15
    "Temperature of water that is added to the fluid stream by the humidifier"
  parameter Modelica.Units.SI.Time tauHum=10
    "Time constant at nominal flow for humidifier(if energyDynamics <> SteadyState)"

  // parameters for heater controller
  parameter Real yValSwi(min=0, max=1, unit="1")
    "Switch point for valve signal";
  parameter Real yValDeaBan(min=0, max=1, unit="1")=0.1
    "Deadband for valve signal";
  parameter Modelica.Units.SI.TemperatureDifference dTSwi=0
    "Switch point for temperature difference";
  parameter Modelica.Units.SI.TemperatureDifference dTDeaBan=0.5
    "Deadband for temperature difference";
  parameter Modelica.Units.SI.Time tWai=60 "Waiting time";

  Modelica.Blocks.Interfaces.RealOutput PHea(
    final unit = "W",
    final quantity = "Power")
    "Power consumed by electric heater"
  Modelica.Blocks.Interfaces.RealInput TSet(
    final unit = "K",
    final quantity = "ThermodynamicTemperature")
    "Set point temperature of the fluid that leaves port_b"
  Modelica.Blocks.Interfaces.RealInput XSet_w(
    final unit = "1",
    final quantity = "MassFraction",
    min = 0,
    max = 0.03)
    "Set point for water vapor mass fraction in kg/kg total air of the fluid that leaves port_b"
  Modelica.Blocks.Sources.RealExpression dT(y(final unit="K")=T_inflow_hea - TSet)
    "Difference between inlet temperature and temperature setpoint of the reheater"

  Buildings.Fluid.Humidifiers.SprayAirWasher_X hum(
    redeclare final package Medium = Medium2,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_small=m2_flow_small,
    final show_T=show_T,
    final energyDynamics=energyDynamics,
    final tau=tauHum,
    final homotopyInitialization=homotopyInitialization,
    final dp_nominal=0,
    final m_flow_nominal=m2_flow_nominal,
    final mWatMax_flow=mWatMax_flow,
    final X_start=X_start,
    final from_dp=from_dp2,
    final linearizeFlowResistance=linearizeFlowResistance2,
    final deltaM=deltaM2)
    "Humidifier"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.ElectricHeater eleHea(
    redeclare final package Medium = Medium2,
    final allowFlowReversal=allowFlowReversal2,
    final show_T=show_T,
    final m_flow_small=m2_flow_small,
    final energyDynamics=energyDynamics,
    final tau=tauEleHea,
    final homotopyInitialization=homotopyInitialization,
    final dp_nominal=0,
    final QMax_flow=QHeaMax_flow,
    final eta=etaHea,
    final m_flow_nominal=m2_flow_nominal,
    final T_start=T_start,
    final from_dp=from_dp2,
    final linearizeFlowResistance=linearizeFlowResistance2,
    final deltaM=deltaM2)
    "Electric heater"

  Buildings.Applications.DataCenters.ChillerCooled.Controls.Reheat heaCon(
    final yValSwi=yValSwi,
    final yValDeaBan=yValDeaBan,
    final dTSwi=dTSwi,
    final dTDeaBan=dTDeaBan,
    final tWai=tWai)
    "Reheater on/off controller"

protected
  Medium2.Temperature T_inflow_hea= Medium2.temperature(state=Medium2.setState_phX(port_b2.p,
                           noEvent(actualStream(port_b2.h_outflow)),
                           noEvent(actualStream(port_b2.Xi_outflow))))
      "Temperature of inflowing fluid at port_a of reheater";

equation
  connect(TSet, eleHea.TSet)
  connect(XSet_w, hum.X_w)
  connect(fan.port_a, eleHea.port_b)
  connect(eleHea.port_a, hum.port_b)
  connect(hum.port_a, cooCoi.port_b2)
  connect(eleHea.P, PHea)
  connect(uFan,fan.y)
  connect(heaCon.y, eleHea.on)
  connect(dT.y, heaCon.dT)
  connect(heaCon.yVal, watVal.y_actual)
end CoolingCoilHumidifyingHeating;


Model for electric heater

within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model ElectricHeater "Model for electric heater"
  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface;
  extends Buildings.Fluid.Interfaces.TwoPortFlowResistanceParameters(
    final computeFlowResistance=(abs(dp_nominal) > Modelica.Constants.eps));

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

  parameter Modelica.Units.SI.Efficiency eta(max=1) = 1
    "Effciency of electrical heater";
  parameter Modelica.Units.SI.HeatFlowRate QMax_flow(min=0) = Modelica.Constants.inf
    "Maximum heat flow rate for heating (positive)"
  parameter Modelica.Units.SI.Temperature T_start=Medium.T_default
    "Start value of temperature"
   // Dynamics
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Modelica.Units.SI.Time tau(min=0) = 10 "Time constant at nominal flow rate (used
    if energyDynamics or massDynamics not equal Modelica.Fluid.Types.Dynamics.SteadyState)"

  Modelica.Blocks.Interfaces.RealOutput Q_flow(
    final quantity="HeatFlowRate",
    final unit="W")
    "Heat flow rate added to the fluid (if flow is from port_a to port_b)"
  Modelica.Blocks.Interfaces.RealOutput P(
    final quantity="Power",
    final unit="W")
   "Electrical power consumed"
  Modelica.Blocks.Interfaces.BooleanInput on
    "Set to true to enable heater, or false to disable heater"
  Modelica.Blocks.Interfaces.RealInput TSet(
    final unit="K",
    final quantity = "ThermodynamicTemperature",
    displayUnit="degC")
    "Set point temperature of the fluid that leaves port_b"

  Buildings.Fluid.HeatExchangers.Heater_T hea(
    final energyDynamics=energyDynamics,
    final T_start=T_start,
    final tau=tau,
    final from_dp=from_dp,
    final linearizeFlowResistance=linearizeFlowResistance,
    final deltaM=deltaM,
    final m_flow_small=m_flow_small,
    final show_T=show_T,
    final homotopyInitialization=homotopyInitialization,
    final allowFlowReversal=allowFlowReversal,
    redeclare package Medium = Medium,
    final m_flow_nominal=m_flow_nominal,
    final dp_nominal=dp_nominal,
    final QMax_flow=QMax_flow)
    "Heater with prescribed temperature"
  Modelica.Blocks.Math.Gain gaiEff(final k=1/eta) "Gain for efficiency"
protected
  Modelica.Blocks.Logical.Switch swi "Switch for temperature setpoint"

  Modelica.Blocks.Sources.Constant zer(
    final k(
      unit="K",
      displayUnit="degC") = 273.15)
    "Zero signal, set to 0 degC which essentially switches off any heating"

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

equation
  connect(port_a, hea.port_a)
  connect(hea.port_b, port_b)
  connect(hea.Q_flow, Q_flow)
  connect(on, swi.u2)
  connect(swi.y, hea.TSet)
  connect(TSet, swi.u1)
  connect(zer.y, swi.u3)
  connect(hea.Q_flow, gaiEff.u)
  connect(gaiEff.y, P)
end ElectricHeater;


Heat exchanger. This module impliments a heat exchanger model with a built-in PID controller to
control the outlet temperature at port_b2 if set parameter
use_controller=true . Otherwise, if set use_controller=false,
the PID controller and the three-way valve are removed and the outlet temperature at port_b2 will
not be controlled.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model HeatExchanger_TSet "Heat exchanger"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialHeatExchanger(
    final activate_ThrWayVal=use_controller);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialControllerInterface;

  Modelica.Blocks.Interfaces.RealInput TSet(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC") if use_controller
    "Temperature setpoint for port_b2"
  Buildings.Controls.Continuous.LimPID con(
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=yMax,
    final yMin=yMin,
    final wp=wp,
    final wd=wd,
    final Ni=Ni,
    final Nd=Nd,
    final initType=initType,
    final xi_start=xi_start,
    final xd_start=xd_start,
    final y_start=yCon_start,
    final reverseActing=reverseActing,
    final reset=reset,
    final y_reset=y_reset) if use_controller
    "Controller for temperature at port_b2"
  Modelica.Blocks.Sources.RealExpression T_b2(y=T_outflow) if use_controller
    "Temperature at port_b2"
protected
  Medium2.Temperature T_outflow = Medium2.temperature(state=Medium2.setState_phX(
      p=port_b2.p, h=actualStream(port_b2.h_outflow), X=actualStream(port_b2.Xi_outflow)))
      "Temperature of outflowing fluid at port_b on medium 2 side";

equation
  if use_controller then
    connect(T_b2.y, con.u_m)
    connect(TSet, con.u_s)
    connect(con.y, thrWayVal.y)
  end if;
  connect(y_reset_in, con.y_reset_in)
  connect(trigger, con.trigger)
end HeatExchanger_TSet;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model IntegratedPrimaryLoadSide
  "Integrated water-side economizer on the load side in a primary-only chilled water system"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialIntegratedPrimary(
    final m_flow_nominal={m1_flow_chi_nominal,m2_flow_chi_nominal,m1_flow_wse_nominal,
      m2_flow_chi_nominal,numChi*m2_flow_chi_nominal,m2_flow_wse_nominal},
    rhoStd = {Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default)});

 //Dynamics
  parameter Modelica.Units.SI.Time tauPump=1
    "Time constant of fluid volume for nominal flow in pumps, used if energy or mass balance is dynamic"
  //Pump
  parameter Integer numPum = numChi "Number of pumps"
  replaceable parameter Buildings.Fluid.Movers.Data.Generic perPum[numPum]
   "Performance data for the pumps"
  parameter Boolean addPowerToMedium = true
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"
  parameter Boolean use_riseTime=true
    "Set to true to continuously change motor speed"
  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to open or close valve"
  parameter Modelica.Blocks.Types.Init initPum = initValve
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real[numPum] yPum_start = fill(0,numPum)
    "Initial value of output:0-closed, 1-fully opened"
  parameter Real[numPum] yValPum_start = fill(0,numPum)
    "Initial value of output:0-closed, 1-fully opened"
  parameter Real lValPum = 0.0001
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  Modelica.Blocks.Interfaces.RealInput yPum[numPum](
    each final unit = "1",
    each min=0,
    each max=1)
    "Constant normalized rotational speed"
  Modelica.Blocks.Interfaces.RealOutput powPum[numPum](
    each final quantity="Power",
    each final unit="W")
    "Electrical power consumed by the pumps"

  Buildings.Applications.BaseClasses.Equipment.FlowMachine_y pum(
    redeclare final package Medium = Medium2,
    final p_start=p2_start,
    final T_start=T2_start,
    final X_start=X2_start,
    final C_start=C2_start,
    final C_nominal=C2_nominal,
    final m_flow_small=m2_flow_small,
    final show_T=show_T,
    final per=perPum,
    addPowerToMedium=addPowerToMedium,
    final energyDynamics=energyDynamics,
    final use_riseTime=use_riseTime,
    final use_strokeTime=use_strokeTime,
    final init=initPum,
    final tau=tauPump,
    final allowFlowReversal=allowFlowReversal2,
    final num=numPum,
    final m_flow_nominal=m2_flow_chi_nominal,
    dpValve_nominal=6000,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final deltaM=deltaM2,
    final riseTime=riseTime,
    final strokeTime=strokeTime,
    final yValve_start=yValPum_start,
    final l=lValPum,
    final yPump_start=yPum_start,
    final from_dp=from_dp2,
    final homotopyInitialization=homotopyInitialization,
    final linearizeFlowResistance=linearizeFlowResistance2) "Pumps"

equation
  connect(yPum, pum.u)
  connect(pum.P, powPum)
  connect(val5.port_b, pum.port_a)
  connect(pum.port_b, val6.port_a)
  connect(chiPar.port_a2, val6.port_a)
  connect(senTem.port_b, pum.port_a)
end IntegratedPrimaryLoadSide;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model IntegratedPrimaryPlantSide
  "Integrated waterside economizer on the plant side in a primary-only chilled water System"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialIntegratedPrimary(
    final m_flow_nominal={m1_flow_chi_nominal,m2_flow_chi_nominal,m1_flow_chi_nominal,
      m2_flow_chi_nominal,numChi*m2_flow_chi_nominal,m2_flow_chi_nominal},
    rhoStd = {Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default)});

  Fluid.FixedResistances.Junction jun3(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal={numChi*m2_flow_chi_nominal,-numChi*m2_flow_chi_nominal,
        m2_flow_wse_nominal},
    dp_nominal={0,0,0}) "Junction"
equation
  connect(val5.port_b, jun3.port_1)
  connect(senTem.port_b, jun3.port_3)
  connect(jun3.port_2, val6.port_a)
  connect(chiPar.port_a2, val6.port_a)
end IntegratedPrimaryPlantSide;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model IntegratedPrimarySecondary
  "Integrated waterside economizer on the load side in a primary-secondary chilled water system"
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialChillerWSE(
    final numVal=5,
    final m_flow_nominal={m1_flow_chi_nominal,m2_flow_chi_nominal,m1_flow_chi_nominal,
      m2_flow_wse_nominal,numChi*m2_flow_chi_nominal},
    rhoStd = {Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default)});

 // Dynamics
  parameter Modelica.Units.SI.Time tauPump=1
    "Time constant of fluid volume for nominal flow in pumps, used if energy or mass balance is dynamic"

  //Pump
  parameter Integer numPum=numChi "Number of pumps"
  parameter Modelica.Units.SI.MassFlowRate m_flow_pum_nominal(min=0)=
    m2_flow_chi_nominal "Nominal flow rate of the pump"
  replaceable parameter Buildings.Fluid.Movers.Data.Generic perPum[numPum]
    "Performance data for primary pumps"
  parameter Boolean addPowerToMedium=true
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"
  parameter Boolean use_riseTime=true
    "Set to true to continuously change motor speed"
  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to change motor speed between zero and full speed"
  parameter Modelica.Blocks.Types.Init initPum=initValve
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real[numPum] yPum_start(each min=0)=fill(0,numPum)
    "Initial value of output from pumps:0-off, 1-on"
  parameter Real[numPum] m_flow_start(each min=0)=fill(0,numPum)
    "Initial value of output from pumps"
  parameter Real[numPum] yValPum_start = fill(0,numPum)
    "Initial value of output:0-closed, 1-fully opened"
  parameter Real lValPum=0.0001
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Modelica.Units.SI.PressureDifference dpValPum_nominal=6000
    "Nominal differential pressure of the shutoff valves for primary pumps"
 //Valve
  parameter Real lVal5(min=1e-10,max=1) = 0.0001
    "Valve 5 leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Real yVal5_start = 0
    "Initial value of output from valve 5:0-closed, 1-fully opened"

  Modelica.Blocks.Interfaces.RealInput yPum[numPum](
      each final unit = "1",
      each min = 0,
      each max = 1)
    "Prescribed normalized flowrate for primary pumps: 1 - nominal flowrate, 0 - no flowrate"
  Modelica.Blocks.Interfaces.RealInput yVal5(
    final unit = "1",
    min = 0,
    max = 1)
    "Actuator position for valve 5 (0: closed, 1: open)"
  Modelica.Blocks.Interfaces.RealOutput powPum[numPum](
    each final quantity="Power",
    each final unit = "W")
    "Electrical power consumed by the pumps"

  Buildings.Fluid.Actuators.Valves.TwoWayLinear val5(
    redeclare final package Medium = Medium2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_nominal=numChi*m2_flow_chi_nominal,
    final show_T=show_T,
    final from_dp=from_dp2,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearizeFlowResistance2,
    final deltaM=deltaM2,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=initValve,
    final dpFixed_nominal=0,
    final dpValve_nominal=dpValve_nominal[5],
    final rhoStd=rhoStd[5],
    final y_start=yVal5_start,
    final l=lVal5)
    "Bypass valve: closed when fully mechanic cooling is activated; open when fully mechanic cooling is activated"
  Buildings.Applications.BaseClasses.Equipment.FlowMachine_m pum(
    redeclare final package Medium = Medium2,
    final p_start=p2_start,
    final T_start=T2_start,
    final X_start=X2_start,
    final C_start=C2_start,
    final C_nominal=C2_nominal,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_small=m2_flow_small,
    final show_T=show_T,
    final per=perPum,
    final addPowerToMedium=addPowerToMedium,
    final energyDynamics=energyDynamics,
    final use_riseTime=use_riseTime,
    final init=initPum,
    final tau=tauPump,
    final m_flow_nominal=m_flow_pum_nominal,
    final num=numPum,
    final deltaM=deltaM2,
    final dpValve_nominal=dpValPum_nominal,
    final l=lValPum,
    final strokeTime=strokeTime,
    final yValve_start=yValPum_start,
    final from_dp=from_dp2,
    final homotopyInitialization=homotopyInitialization,
    final linearizeFlowResistance=linearizeFlowResistance2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final riseTime=riseTime,
    final yPump_start=yPum_start) "Constant speed pumps"
  Buildings.Fluid.Sensors.MassFlowRate bypFlo(redeclare package Medium = Medium2)
    "Bypass water mass flowrate"
  Fluid.FixedResistances.Junction jun2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={m2_flow_wse_nominal,-numChi*m2_flow_chi_nominal,numChi*
        m2_flow_chi_nominal},
    dp_nominal={0,0,0}) "Junction"
  Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={numChi*m2_flow_chi_nominal,-numChi*m2_flow_chi_nominal,-
        m2_flow_wse_nominal},
    dp_nominal={0,0,0}) "Splitter"
  Fluid.FixedResistances.Junction jun3(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={numChi*m2_flow_chi_nominal,-numChi*m2_flow_chi_nominal,
        m2_flow_wse_nominal},
    dp_nominal={0,0,0}) "Junction"
equation
  connect(pum.port_b, chiPar.port_a2)
  connect(val5.y, yVal5)
  connect(yPum, pum.u)
  connect(pum.P, powPum)
  connect(bypFlo.port_a, jun2.port_1)
  connect(chiPar.port_b2, jun2.port_3)
  connect(jun2.port_2, port_b2)
  connect(port_a2, spl2.port_1)
  connect(spl2.port_3, wse.port_a2)
  connect(spl2.port_2, val5.port_a)
  connect(val5.port_b, jun3.port_1)
  connect(senTem.port_b, jun3.port_3)
  connect(jun3.port_2, pum.port_a)
  connect(bypFlo.port_b, pum.port_a)
end IntegratedPrimarySecondary;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model NonIntegrated
  "Non-integrated waterside economizer in chilled water system"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialChillerWSE(
    final numVal=4,
    final m_flow_nominal={m1_flow_chi_nominal,m2_flow_chi_nominal,m1_flow_wse_nominal,
      m2_flow_wse_nominal},
    rhoStd = {Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default),
            Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default)});

  Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal=
      {numChi*m2_flow_chi_nominal,-numChi*m2_flow_chi_nominal,-m2_flow_wse_nominal},
    dp_nominal={0,0,0}) "Splitter"
  Fluid.FixedResistances.Junction jun2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={m2_flow_wse_nominal,-numChi*m2_flow_chi_nominal,numChi*
        m2_flow_chi_nominal},
    dp_nominal={0,0,0}) "Junction"
equation
  connect(port_a2, spl2.port_1)
  connect(spl2.port_3, wse.port_a2)
  connect(spl2.port_2, chiPar.port_a2)
  connect(port_b2, jun2.port_2)
  connect(chiPar.port_b2, jun2.port_3)
  connect(jun2.port_1, senTem.port_b)
end NonIntegrated;


within Buildings.Applications.DataCenters.ChillerCooled;
package Equipment "Equipment models for chiller cooled data centers"
  extends Modelica.Icons.VariantsPackage;
end Equipment;


Waterside economizer

within Buildings.Applications.DataCenters.ChillerCooled.Equipment;
model WatersideEconomizer "Waterside economizer"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialPlantParallel(
    final num=1,
    val2(each final dpFixed_nominal=dp2_nominal),
    val1(each final dpFixed_nominal=dp1_nominal),
    final yValve_start={yValWSE_start});
  extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations(
    final massDynamics=energyDynamics,
    final mSenFac=1,
    redeclare final package Medium=Medium2);
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.ThreeWayValveParameters(
    final activate_ThrWayVal=use_controller);
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialControllerInterface;

  // Filter opening
  parameter Real yThrWayVal_start=1
   "Initial value of output from the filter in the bypass valve"
  parameter Real yValWSE_start=1
    "Initial value of output from the filter in the shutoff valve"

 // Heat exchanger
  parameter Modelica.Units.SI.Efficiency eta(start=0.8)
    "constant effectiveness";

 // Bypass valve parameters
  parameter Modelica.Units.SI.Time tauThrWayVal=10
    "Time constant at nominal flow for dynamic energy and momentum balance of the three-way valve"

  Modelica.Blocks.Interfaces.RealInput TSet(
    unit="K",
    displayUnit="degC") if use_controller
    "Set point for leaving water temperature"

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.HeatExchanger_TSet
    heaExc(
    redeclare final replaceable package Medium1 = Medium1,
    redeclare final replaceable package Medium2 = Medium2,
    final dpThrWayVal_nominal=dpThrWayVal_nominal,
    final use_controller=use_controller,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal=0,
    final dp2_nominal=0,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=yMax,
    final yMin=yMin,
    final wp=wp,
    final wd=wd,
    final Ni=Ni,
    final Nd=Nd,
    final initType=initType,
    final xi_start=xi_start,
    final xd_start=xd_start,
    final yCon_start=yCon_start,
    final reset=reset,
    final y_reset=y_reset,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small,
    final show_T=show_T,
    final from_dp1=from_dp1,
    final linearizeFlowResistance1=linearizeFlowResistance1,
    final deltaM1=deltaM1,
    final from_dp2=from_dp2,
    final linearizeFlowResistance2=linearizeFlowResistance2,
    final deltaM2=deltaM2,
    final homotopyInitialization=homotopyInitialization,
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=initValve,
    final yThrWayVal_start=yThrWayVal_start,
    final eta=eta,
    final fraK_ThrWayVal=fraK_ThrWayVal,
    final l_ThrWayVal=l_ThrWayVal,
    final R=R,
    final delta0=delta0,
    final tauThrWayVal=tauThrWayVal,
    final portFlowDirection_1=portFlowDirection_1,
    final portFlowDirection_2=portFlowDirection_2,
    final portFlowDirection_3=portFlowDirection_3,
    final rhoStd=rhoStd[2],
    final reverseActing=reverseActing) "Water-to-water heat exchanger"

equation
  connect(port_a1, heaExc.port_a1)
  connect(heaExc.port_a2, port_a2)
  connect(TSet, heaExc.TSet)
  connect(y_reset_in, heaExc.y_reset_in)
  connect(trigger, heaExc.trigger)
  connect(heaExc.port_b1, val1[1].port_a)
  connect(val2[1].port_a, heaExc.port_b2)
end WatersideEconomizer;


Essential parameters for air handling unit. This  block declares parameters that are required by most classes in the package

Buildings.Applications.DataCenters.ChillerCooled.Equipment.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model AHUParameters "Essential parameters for air handling unit"

  parameter Modelica.Units.SI.ThermalConductance UA_nominal
    "Thermal conductance at nominal flow for sensible heat, used to compute time constant"
  parameter Real r_nominal=2/3
    "Ratio between air-side and water-side convective heat transfer coefficient"

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


Flow resistance model for the chiller and WSE package.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
record FourPortResistanceChillerWSE
  "Flow resistance model for the chiller and WSE package"

  parameter Boolean computeFlowResistance1 = true
    "=true, compute flow resistance. Set to false to assume no friction"

  parameter Boolean from_dp1 = false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Modelica.Units.SI.PressureDifference dp1_chi_nominal(min=0,
      displayUnit="Pa") "Pressure difference on medium 1 side in the chillers"
  parameter Modelica.Units.SI.PressureDifference dp1_wse_nominal(min=0,
      displayUnit="Pa")
    "Pressure difference on medium 1 side in the waterside economizer"
  parameter Boolean linearizeFlowResistance1 = false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Real deltaM1 = 0.1
    "Fraction of nominal flow rate where flow transitions to laminar"
  parameter Boolean computeFlowResistance2 = true
    "=true, compute flow resistance. Set to false to assume no friction"
  parameter Boolean from_dp2 = false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Modelica.Units.SI.PressureDifference dp2_chi_nominal(min=0,
      displayUnit="Pa") "Pressure difference on medium 2 side in the chillers"
  parameter Modelica.Units.SI.PressureDifference dp2_wse_nominal(min=0,
      displayUnit="Pa")
    "Pressure difference on medium 2 side in the waterside economizer"
  parameter Boolean linearizeFlowResistance2 = false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Real deltaM2 = 0.1
    "Fraction of nominal flow rate where flow transitions to laminar"
end FourPortResistanceChillerWSE;


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


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialChillerWSE
  "Partial model for chiller and WSE package"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialChillerWSEInterface(
     final num=numChi+1);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.FourPortResistanceChillerWSE(
     final computeFlowResistance1=true,
     final computeFlowResistance2=true);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialControllerInterface(
     final reverseActing=false);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.ValvesParameters(
     numVal=4,
     final deltaM=deltaM1);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.SignalFilterParameters(
     final numAct=1,
     final yValve_start={yValWSE_start});
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.ThreeWayValveParameters(
     final activate_ThrWayVal=use_controller);

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

  //Chiller
  parameter Integer numChi(min=1) "Number of chillers"
  replaceable parameter Buildings.Fluid.Chillers.Data.ElectricEIR.Generic perChi[numChi]
    "Performance data for chillers"
  parameter Real[2] lValChi(each min=1e-10, each max=1) = {0.0001,0.0001}
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Real[numChi] yValChi_start=fill(0,numChi)
    "Initial value of output from on/off valves in chillers"

  //WSE
  parameter Modelica.Units.SI.Efficiency eta(
    min=0,
    max=1) = 0.8 "Heat exchange effectiveness"

  parameter Real[2] lValWSE(each min=1e-10, each max=1) = {0.0001,0.0001}
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Real yValWSE_start=0
    "Initial value of output from on/off valve in WSE"
  parameter Real yThrWayValWSE_start=0
    "Initial value of output from three-way bypass valve in WSE"

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

  parameter Modelica.Units.SI.Time tauChi1=30
    "Time constant at nominal flow in chillers"
  parameter Modelica.Units.SI.Time tauChi2=30
    "Time constant at nominal flow in chillers"
  parameter Modelica.Units.SI.Time tauWSE=10
    "Time constant at nominal flow for dynamic energy and momentum balance of the three-way valve"

  // Initialization
  parameter Medium1.AbsolutePressure p1_start = Medium1.p_default
    "Start value of pressure"
  parameter Medium1.Temperature T1_start = Medium1.T_default
    "Start value of temperature"
  parameter Medium1.MassFraction X1_start[Medium1.nX] = Medium1.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium1.ExtraProperty C1_start[Medium1.nC](
    final quantity=Medium1.extraPropertiesNames)=fill(0, Medium1.nC)
    "Start value of trace substances"
  parameter Medium1.ExtraProperty C1_nominal[Medium1.nC](
    final quantity=Medium1.extraPropertiesNames) = fill(1E-2, Medium1.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"
  parameter Medium2.AbsolutePressure p2_start = Medium2.p_default
    "Start value of pressure"
  parameter Medium2.Temperature T2_start = Medium2.T_default
    "Start value of temperature"
  parameter Medium2.MassFraction X2_start[Medium2.nX] = Medium2.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium2.ExtraProperty C2_start[Medium2.nC](
    final quantity=Medium2.extraPropertiesNames)=fill(0, Medium2.nC)
    "Start value of trace substances"
  parameter Medium2.ExtraProperty C2_nominal[Medium2.nC](
    final quantity=Medium2.extraPropertiesNames) = fill(1E-2, Medium2.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"

  // Temperature sensor
  parameter Modelica.Units.SI.Time tauSenT=1 "Time constant at nominal flow rate (use tau=0 for steady-state sensor,
    but see user guide for potential problems)"
  parameter Modelica.Blocks.Types.Init initTSenor = Modelica.Blocks.Types.Init.InitialState
    "Type of initialization of the temperature sensor (InitialState and InitialOutput are identical)"

  Modelica.Blocks.Interfaces.RealOutput TCHWSupWSE(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC",
    min=200,
    start=T2_start)
    "Chilled water supply temperature in the waterside economizer"
  Modelica.Blocks.Interfaces.RealOutput powChi[numChi](
    each final quantity="Power",
    each final unit="W")
    "Electric power consumed by chiller compressor"

  Buildings.Applications.BaseClasses.Equipment.ElectricChillerParallel chiPar(
    redeclare final replaceable package Medium1 = Medium1,
    redeclare final replaceable package Medium2 = Medium2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small,
    final show_T=show_T,
    final from_dp1=from_dp1,
    final linearizeFlowResistance1=linearizeFlowResistance1,
    final deltaM1=deltaM1,
    final from_dp2=from_dp2,
    final linearizeFlowResistance2=linearizeFlowResistance2,
    final deltaM2=deltaM2,
    final num=numChi,
    final per=perChi,
    final homotopyInitialization=homotopyInitialization,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final initValve=initValve,
    final m1_flow_nominal=m1_flow_chi_nominal,
    final m2_flow_nominal=m2_flow_chi_nominal,
    final dp1_nominal=dp1_chi_nominal,
    final tau1=tauChi1,
    final tau2=tauChi2,
    final energyDynamics=energyDynamics,
    final p1_start=p1_start,
    final T1_start=T1_start,
    final X1_start=X1_start,
    final C1_start=C1_start,
    final C1_nominal=C1_nominal,
    final p2_start=p2_start,
    final T2_start=T2_start,
    final X2_start=X2_start,
    final C2_start=C2_start,
    final C2_nominal=C2_nominal,
    final l=lValChi,
    final dp2_nominal=dp2_chi_nominal,
    final dpValve_nominal=dpValve_nominal[1:2],
    final rhoStd=rhoStd[1:2],
    final yValve_start=yValChi_start)
    "Chillers with identical nominal parameters but different performance curves"
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.WatersideEconomizer
    wse(
    redeclare final replaceable package Medium1 = Medium1,
    redeclare final replaceable package Medium2 = Medium2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final m1_flow_nominal=m1_flow_wse_nominal,
    final m2_flow_nominal=m2_flow_wse_nominal,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small,
    final from_dp1=from_dp1,
    final dp1_nominal=dp1_wse_nominal,
    final linearizeFlowResistance1=linearizeFlowResistance1,
    final deltaM1=deltaM1,
    final from_dp2=from_dp2,
    final dp2_nominal=dp2_wse_nominal,
    final linearizeFlowResistance2=linearizeFlowResistance2,
    final deltaM2=deltaM2,
    final homotopyInitialization=homotopyInitialization,
    final l=lValWSE,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final initValve=initValve,
    final energyDynamics=energyDynamics,
    final p_start=p2_start,
    final T_start=T2_start,
    final X_start=X2_start,
    final C_start=C2_start,
    final C_nominal=C2_nominal,
    final controllerType=controllerType,
    final k=k,
    final Ti=Ti,
    final Td=Td,
    final yMax=yMax,
    final yMin=yMin,
    final wp=wp,
    final wd=wd,
    final Ni=Ni,
    final Nd=Nd,
    final initType=initType,
    final xi_start=xi_start,
    final xd_start=xd_start,
    final yCon_start=yCon_start,
    final reset=reset,
    final y_reset=y_reset,
    final eta=eta,
    final fraK_ThrWayVal=fraK_ThrWayVal,
    final l_ThrWayVal=l_ThrWayVal,
    final R=R,
    final delta0=delta0,
    final dpValve_nominal=dpValve_nominal[3:4],
    final rhoStd=rhoStd[3:4],
    final yThrWayVal_start=yThrWayValWSE_start,
    final yValWSE_start=yValWSE_start,
    final tauThrWayVal=tauWSE,
    final use_controller=use_controller,
    final reverseActing=reverseActing,
    final show_T=show_T,
    final portFlowDirection_1=portFlowDirection_1,
    final portFlowDirection_2=portFlowDirection_2,
    final portFlowDirection_3=portFlowDirection_3) "Waterside economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort senTem(
    redeclare final replaceable package Medium = Medium2,
    final m_flow_nominal=m2_flow_wse_nominal,
    final tau=tauSenT,
    final initType=initTSenor,
    final T_start=T2_start,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_small=m2_flow_small)
    "Temperature sensor"

  Fluid.FixedResistances.Junction spl1(
    redeclare package Medium = Medium1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={numChi*m1_flow_chi_nominal,-m1_flow_wse_nominal,-numChi*
        m1_flow_chi_nominal},
    dp_nominal={0,0,0}) "Splitter"
  Fluid.FixedResistances.Junction jun1(
    redeclare package Medium = Medium1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={numChi*m1_flow_chi_nominal,-numChi*m1_flow_chi_nominal,
        m1_flow_wse_nominal},
    dp_nominal={0,0,0}) "Junction"
initial equation
  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);

equation
  for i in 1:numChi loop
  connect(chiPar.on[i], on[i])
  end for;
  connect(on[numChi+1], wse.on[1])
  connect(chiPar.TSet, TSet)
  connect(TSet, wse.TSet)
  connect(y_reset_in, wse.y_reset_in)
  connect(trigger, wse.trigger)
  connect(senTem.T,TCHWSupWSE)
  connect(wse.port_b2, senTem.port_a)
  connect(chiPar.P, powChi)
  connect(port_a1, spl1.port_1)
  connect(spl1.port_3, chiPar.port_a1)
  connect(spl1.port_2, wse.port_a1)
  connect(port_b1, jun1.port_2)
  connect(jun1.port_3, wse.port_b1)
  connect(chiPar.port_b1, jun1.port_1)
end PartialChillerWSE;


Partial model that defines the interface for chiller and WSE package. This model implements an interface for chillers and integrated/nonitegrated water-side economizers.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialChillerWSEInterface
  "Partial model that defines the interface for chiller and WSE package"
  extends Buildings.Fluid.Interfaces.PartialFourPort;

  // Nominal conditions
  parameter Modelica.Units.SI.MassFlowRate m1_flow_chi_nominal(min=0)
    "Nominal mass flow rate on the medium 1 side in the chiller"
  parameter Modelica.Units.SI.MassFlowRate m2_flow_chi_nominal(min=0)
    "Nominal mass flow rate on the medium 2 side in the chiller"
  parameter Modelica.Units.SI.MassFlowRate m1_flow_wse_nominal(min=0)
    "Nominal mass flow rate on the medium 1 side in the waterside economizer"
  parameter Modelica.Units.SI.MassFlowRate m2_flow_wse_nominal(min=0)
    "Nominal mass flow rate on the medium 2 side in the waterside economizer"

  // Advanced
  parameter Medium1.MassFlowRate m1_flow_small(min=0) = 1E-4*abs(m1_flow_chi_nominal)
    "Small mass flow rate for regularization of zero flow"
  parameter Medium2.MassFlowRate m2_flow_small(min=0) = 1E-4*abs(m2_flow_chi_nominal)
    "Small mass flow rate for regularization of zero flow"
  // Diagnostics
  parameter Boolean show_T = false
    "= true, if actual temperature at port is computed"
  parameter Integer num(min=1)=2 "Total number of chillers and waterside economizer";

  Modelica.Blocks.Interfaces.RealInput TSet(
    final unit="K",
    final quantity="ThermodynamicTemperature",
    displayUnit="degC")
    "Set point for leaving water temperature"
  Modelica.Blocks.Interfaces.BooleanInput on[num]
    "Set to true to enable equipment, or false to disable equipment"
  Medium1.MassFlowRate m1_flow = port_a1.m_flow
    "Mass flow rate from port_a1 to port_b1 (m1_flow > 0 is design flow direction)";
  Modelica.Units.SI.PressureDifference dp1(displayUnit="Pa") = port_a1.p -
    port_b1.p "Pressure difference between port_a1 and port_b1";

  Medium2.MassFlowRate m2_flow = port_a2.m_flow
    "Mass flow rate from port_a2 to port_b2 (m2_flow > 0 is design flow direction)";
  Modelica.Units.SI.PressureDifference dp2(displayUnit="Pa") = port_a2.p -
    port_b2.p "Pressure difference between port_a2 and port_b2";

  Medium1.ThermodynamicState sta_a1=
      Medium1.setState_phX(port_a1.p,
                           noEvent(actualStream(port_a1.h_outflow)),
                           noEvent(actualStream(port_a1.Xi_outflow)))
      if show_T "Medium properties in port_a1";
  Medium1.ThermodynamicState sta_b1=
      Medium1.setState_phX(port_b1.p,
                           noEvent(actualStream(port_b1.h_outflow)),
                           noEvent(actualStream(port_b1.Xi_outflow)))
      if show_T "Medium properties in port_b1";
  Medium2.ThermodynamicState sta_a2=
      Medium2.setState_phX(port_a2.p,
                           noEvent(actualStream(port_a2.h_outflow)),
                           noEvent(actualStream(port_a2.Xi_outflow)))
      if show_T "Medium properties in port_a2";
  Medium2.ThermodynamicState sta_b2=
      Medium2.setState_phX(port_b2.p,
                           noEvent(actualStream(port_b2.h_outflow)),
                           noEvent(actualStream(port_b2.Xi_outflow)))
      if show_T "Medium properties in port_b2";
protected
  Medium1.ThermodynamicState state_a1_inflow=
    Medium1.setState_phX(port_a1.p, inStream(port_a1.h_outflow), inStream(port_a1.Xi_outflow))
    "state for medium inflowing through port_a1";
  Medium1.ThermodynamicState state_b1_inflow=
    Medium1.setState_phX(port_b1.p, inStream(port_b1.h_outflow), inStream(port_b1.Xi_outflow))
    "state for medium inflowing through port_b1";
  Medium2.ThermodynamicState state_a2_inflow=
    Medium2.setState_phX(port_a2.p, inStream(port_a2.h_outflow), inStream(port_a2.Xi_outflow))
    "state for medium inflowing through port_a2";
  Medium2.ThermodynamicState state_b2_inflow=
    Medium2.setState_phX(port_b2.p, inStream(port_b2.h_outflow), inStream(port_b2.Xi_outflow))
    "state for medium inflowing through port_b2";

end PartialChillerWSEInterface;


Partial interface model for waterside economizer temperature controller. This module implements a PID controller interface.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialControllerInterface
  "Partial interface model for waterside economizer temperature controller"

  parameter Boolean use_controller=true
  "Set to ture if the built-in controller is enabled to maintain the outlet
  temperature on the load side of a heat exchanger";

 // Controller
  parameter Modelica.Blocks.Types.SimpleController controllerType=
    Modelica.Blocks.Types.SimpleController.PID
    "Type of controller"
  parameter Real k(min=0, unit="1") = 1
    "Gain of controller"
  parameter Modelica.Units.SI.Time Ti(min=Modelica.Constants.small) = 0.5
    "Time constant of integrator block"
  parameter Modelica.Units.SI.Time Td(min=0) = 0.1
    "Time constant of derivative block"
  parameter Real yMax(start=1)=1
   "Upper limit of output"
  parameter Real yMin=0
   "Lower limit of output"
  parameter Real wp(min=0) = 1
   "Set-point weight for Proportional block (0..1)"
  parameter Real wd(min=0) = 0
   "Set-point weight for Derivative block (0..1)"
  parameter Real Ni(min=100*Modelica.Constants.eps) = 0.9
    "Ni*Ti is time constant of anti-windup compensation"
  parameter Real Nd(min=100*Modelica.Constants.eps) = 10
    "The higher Nd, the more ideal the derivative block"
  parameter Modelica.Blocks.Types.Init initType=Modelica.Blocks.Types.Init.InitialState
    "Type of initialization (1: no init, 2: steady state, 3: initial state, 4: initial output)"
  parameter Real xi_start=0
    "Initial or guess value value for integrator output (= integrator state)"
  parameter Real xd_start=0
    "Initial or guess value for state of derivative block"
  parameter Real yCon_start=0
    "Initial value of output from the controller"
  parameter Boolean reverseActing=false
    "Set to true for throttling the water flow rate through a cooling coil controller"
  parameter Buildings.Types.Reset reset = Buildings.Types.Reset.Disabled
    "Type of controller output reset"
  parameter Real y_reset=xi_start
    "Value to which the controller output is reset if the boolean trigger
    has a rising edge, used if reset == Buildings.Types.Reset.Parameter"

 Modelica.Blocks.Interfaces.BooleanInput trigger
    if reset <> Buildings.Types.Reset.Disabled
    "Resets the controller output when trigger becomes true"
  Modelica.Blocks.Interfaces.RealInput y_reset_in
    if reset == Buildings.Types.Reset.Input
    "Input signal for state to which integrator is reset,
    enabled if reset = Buildings.Types.Reset.Input"
end PartialControllerInterface;


Partial AHU model

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialCoolingCoilHumidifyingHeating "Partial AHU model "
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface(
    final show_T=true);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.AHUParameters;
  extends Buildings.Fluid.Actuators.BaseClasses.ValveParameters(
    final m_flow_nominal=m1_flow_nominal,
    final rhoStd=Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
    final deltaM = deltaM2);
  extends Buildings.Fluid.Interfaces.FourPortFlowResistanceParameters(
    final computeFlowResistance1=true,
    final computeFlowResistance2=true);

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

  // Initialization of the fan
  parameter Medium2.AbsolutePressure p_start = Medium2.p_default
    "Start value of pressure"
  parameter Medium2.Temperature T_start=Medium2.T_default
    "Start value of temperature"
  parameter Medium2.MassFraction X_start[Medium2.nX](
       quantity=Medium2.substanceNames) = Medium2.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium2.ExtraProperty C_start[Medium2.nC](
       quantity=Medium2.extraPropertiesNames)=fill(0, Medium2.nC)
    "Start value of trace substances"
  parameter Medium2.ExtraProperty C_nominal[Medium2.nC](
       quantity=Medium2.extraPropertiesNames) = fill(1E-2, Medium2.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"
  // valve parameters
  parameter Real l(min=1e-10, max=1) = 0.0001
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"

  parameter Boolean use_strokeTime=false
    "Set to true to continuously open and close valve on the water-side"
  parameter Modelica.Units.SI.Time strokeTime=120
    "Time needed to open or close valve"
  parameter Modelica.Blocks.Types.Init initValve=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real yValve_start=1 "Initial value of output"
  // fan parameters
   parameter Buildings.Fluid.Types.InputType inputType = Buildings.Fluid.Types.InputType.Continuous
    "Control input type"
  parameter Boolean addPowerToMedium=true
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"
  parameter Modelica.Units.SI.Time tauFan=1
    "Time constant at nominal flow (if energyDynamics <> SteadyState)"
  parameter Boolean use_riseTime=true
    "Set to true to continuously change motor speed"
  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to change motor speed between zero and full speed"
  parameter Modelica.Blocks.Types.Init initFan=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real yFan_start(min=0, max=1, unit="1")=0 "Initial value of speed"
  replaceable parameter Buildings.Fluid.Movers.Data.Generic perFan "Performance data for the fan"

  Modelica.Blocks.Interfaces.RealInput uVal(min=0,max=1,unit="1")
    "Actuator position (0: closed, 1: open) on water side"
  Modelica.Blocks.Interfaces.RealInput uFan
if not inputType == Buildings.Fluid.Types.InputType.Stages
   "Continuous input signal for the fan"
  Modelica.Blocks.Interfaces.RealOutput PFan(
    final quantity="Power",
    final unit="W")
    "Electrical power consumed by the fan"
  Modelica.Blocks.Interfaces.RealOutput yVal(
    min=0,
    max=1,
    final unit="1") "Actual valve position"
  Modelica.Blocks.Interfaces.IntegerInput stage
 if inputType == Buildings.Fluid.Types.InputType.Stages
    "Stage input signal for the pressure head"

  Fluid.HeatExchangers.WetCoilEffectivenessNTU cooCoi(
    redeclare final package Medium1 = Medium1,
    redeclare final package Medium2 = Medium2,
    final UA_nominal=UA_nominal,
    final r_nominal=r_nominal,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final show_T=show_T,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small,
    final energyDynamics=energyDynamics,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final dp1_nominal=0,
    final dp2_nominal=dp2_nominal)
    "Cooling coil"
  replaceable Buildings.Fluid.Movers.BaseClasses.PartialFlowMachine fan
    constrainedby Buildings.Fluid.Movers.BaseClasses.PartialFlowMachine(
    redeclare final package Medium = Medium2,
    final per=perFan,
    final allowFlowReversal=allowFlowReversal2,
    final show_T=show_T,
    final energyDynamics=energyDynamics,
    final inputType=inputType,
    final tau=tauFan,
    final addPowerToMedium=addPowerToMedium,
    final use_riseTime=use_riseTime,
    final riseTime=riseTime,
    final init=initFan,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final m_flow_small=m2_flow_small) "Fan"
  replaceable Buildings.Fluid.Actuators.BaseClasses.PartialTwoWayValveKv watVal
    constrainedby Buildings.Fluid.Actuators.BaseClasses.PartialTwoWayValveKv(
      redeclare final package Medium = Medium1,
      final allowFlowReversal=allowFlowReversal1,
      final show_T=show_T,
      final l=l,
      final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
      final from_dp=from_dp1,
      final homotopyInitialization=homotopyInitialization,
      final linearized=linearizeFlowResistance1,
      final rhoStd=rhoStd,
      final use_strokeTime=use_strokeTime,
      final strokeTime=strokeTime,
      final init=initValve,
      final y_start=yValve_start,
      final dpValve_nominal=dpValve_nominal,
      final m_flow_nominal=m_flow_nominal,
      final deltaM=deltaM1,
      final dpFixed_nominal=dp1_nominal)
    "Two-way valve"

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

equation
  connect(port_a1, cooCoi.port_a1)
  connect(cooCoi.port_a2, port_a2)
  connect(cooCoi.port_b1, watVal.port_a)
  connect(watVal.port_b, port_b1)
  connect(fan.P, PFan)
  connect(watVal.y, uVal)
  connect(port_b2, fan.port_b)
  connect(fan.stage, stage)
  connect(yVal, watVal.y_actual)
end PartialCoolingCoilHumidifyingHeating;


Partial model for heat exchangers

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialHeatExchanger "Partial model for heat exchangers "

  extends Buildings.Fluid.Interfaces.PartialFourPortInterface;
  extends Buildings.Fluid.Interfaces.FourPortFlowResistanceParameters(
    final computeFlowResistance1=(dp1_nominal > Modelica.Constants.eps),
    final computeFlowResistance2=(dp2_nominal > Modelica.Constants.eps));
  extends Buildings.Fluid.Interfaces.LumpedVolumeDeclarations(
    final massDynamics=energyDynamics,
    final mSenFac=1,
    redeclare final package Medium=Medium2);
  extends
    Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.ThreeWayValveParameters;

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

  parameter Modelica.Units.SI.Efficiency eta(
    min=0,
    max=1,
    start=0.8) "constant effectiveness";

   // Filter opening
  parameter Boolean use_strokeTime=true
    "Set to true to continuously open and close valve"
  parameter Modelica.Units.SI.Time strokeTime=30
    "Time needed to open or close valve"
  parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real yThrWayVal_start=1
    "Initial value of output from the filter in the bypass valve"
  parameter Modelica.Units.SI.PressureDifference dpValve_nominal(
    displayUnit="Pa",
    min=0,
    fixed=true) = 6000 "Nominal pressure drop of fully open valve"

 // Time constant
  parameter Modelica.Units.SI.Time tauThrWayVal=10
    "Time constant at nominal flow for dynamic energy and momentum balance of the three-way valve"
  // Advanced
  parameter Modelica.Units.SI.Density rhoStd=Medium2.density_pTX(
      101325,
      273.15 + 4,
      Medium2.X_default)
    "Inlet density for which valve coefficients are defined"

  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear thrWayVal(
    redeclare package Medium = Medium2,
    final from_dp=from_dp2,
    final linearized={linearizeFlowResistance2,linearizeFlowResistance2},
    final rhoStd=rhoStd,
    final homotopyInitialization=homotopyInitialization,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=init,
    final R=R,
    final delta0=delta0,
    final fraK=fraK_ThrWayVal,
    final dpFixed_nominal={dp2_nominal,0},
    final energyDynamics=energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final X_start=X_start,
    final y_start=yThrWayVal_start,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final l=l_ThrWayVal,
    final dpValve_nominal=dpValve_nominal,
    final deltaM=deltaM2,
    final m_flow_nominal=m2_flow_nominal,
    final portFlowDirection_1=portFlowDirection_1,
    final portFlowDirection_2=portFlowDirection_2,
    final portFlowDirection_3=portFlowDirection_3,
    final tau=tauThrWayVal) if activate_ThrWayVal
    "Three-way valve used to control the outlet temperature "

  Buildings.Fluid.HeatExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    final allowFlowReversal1=allowFlowReversal1,
    final allowFlowReversal2=allowFlowReversal2,
    final m1_flow_nominal=m1_flow_nominal,
    final m2_flow_nominal=m2_flow_nominal,
    final m1_flow_small=m1_flow_small,
    final m2_flow_small=m2_flow_small,
    final show_T=show_T,
    final from_dp1=from_dp1,
    final dp1_nominal=dp1_nominal,
    final linearizeFlowResistance1=linearizeFlowResistance1,
    final deltaM1=deltaM1,
    final from_dp2=from_dp2,
    final linearizeFlowResistance2=linearizeFlowResistance2,
    final deltaM2=deltaM2,
    final eps=eta,
    final homotopyInitialization=homotopyInitialization,
    final dp2_nominal=if activate_ThrWayVal then 0 else dp2_nominal)
    "Heat exchanger"

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

equation
  connect(port_a1, hex.port_a1)
  connect(hex.port_b1, port_b1)
  connect(hex.port_a2, port_a2)
  if activate_ThrWayVal then
    connect(hex.port_b2, thrWayVal.port_1)
    connect(port_a2, thrWayVal.port_3)
    connect(thrWayVal.port_2, port_b2)
  else
    connect(port_b2, hex.port_b2)
  end if;
end PartialHeatExchanger;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
model PartialIntegratedPrimary
  "Integrated water-side economizer for primary-only chilled water system"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialChillerWSE(
    final numVal=6);

  //Parameters for the valve used in free cooling mode
  parameter Real lVal5(min=1e-10,max=1) = 0.0001
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Real lVal6(min=1e-10,max=1) = 0.0001
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"

  parameter Real yVal5_start(min=0,max=1) = 0
    "Initial value of output:0-closed, 1-fully opened"
  parameter Real yVal6_start(min=0,max=1) = 1-yVal5_start
    "Initial value of output:0-closed, 1-fully opened"

 Modelica.Blocks.Interfaces.RealInput yVal6(
   final unit = "1",
   min=0,
   max=1)
    "Actuator position for valve 6 (0: closed, 1: open)"

  Modelica.Blocks.Interfaces.RealInput yVal5(
    final unit= "1",
    min=0,
    max=1)
    "Actuator position for valve 5(0: closed, 1: open)"

  Buildings.Fluid.Actuators.Valves.TwoWayLinear val5(
    redeclare final package Medium = Medium2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final allowFlowReversal=allowFlowReversal2,
    final m_flow_nominal=numChi*m2_flow_chi_nominal,
    final show_T=show_T,
    final from_dp=from_dp2,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearizeFlowResistance2,
    final deltaM=deltaM2,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=initValve,
    final dpFixed_nominal=0,
    final dpValve_nominal=dpValve_nominal[5],
    final l=lVal5,
    final rhoStd=rhoStd[5],
    final y_start=yVal5_start) "Bypass valve: closed when fully mechanic cooling is activated;
    open when fully mechanic cooling is activated"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val6(
    redeclare final package Medium = Medium2,
    final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    final m_flow_nominal=m2_flow_wse_nominal,
    final allowFlowReversal=allowFlowReversal2,
    final show_T=show_T,
    final from_dp=from_dp2,
    final homotopyInitialization=homotopyInitialization,
    final linearized=linearizeFlowResistance2,
    final deltaM=deltaM2,
    final use_strokeTime=use_strokeTime,
    final strokeTime=strokeTime,
    final init=initValve,
    final dpFixed_nominal=0,
    final dpValve_nominal=dpValve_nominal[6],
    final l=lVal6,
    final rhoStd=rhoStd[6],
    final y_start=yVal6_start) "Bypass valve: closed when free cooling mode is deactivated;
    open when free cooling is activated"

  Fluid.FixedResistances.Junction spl2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={numChi*m2_flow_chi_nominal,-numChi*m2_flow_chi_nominal,
        -m2_flow_wse_nominal},
    dp_nominal={0,0,0}) "Splitter"
  Fluid.FixedResistances.Junction jun2(
    redeclare package Medium = Medium2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    m_flow_nominal={m2_flow_wse_nominal,-numChi*m2_flow_chi_nominal,numChi*
        m2_flow_chi_nominal},
    dp_nominal={0,0,0}) "Junction"
equation
  connect(val5.y, yVal5)
  connect(yVal6, val6.y)
  connect(port_a2, spl2.port_1)
  connect(spl2.port_3, wse.port_a2)
  connect(spl2.port_2, val5.port_a)
  connect(val6.port_b, jun2.port_1)
  connect(jun2.port_2, port_b2)
  connect(chiPar.port_b2, jun2.port_3)
end PartialIntegratedPrimary;


Partial interface for operation sequence . Partial model that transforms the valve signal.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialOperationSequenceInterface
  "Partial interface for operation sequence "

  Modelica.Blocks.Math.BooleanToReal booToRea(
    final realTrue=1,
    final realFalse=0)
    "Boolean to real (if true then 1 else 0)"
  Modelica.Blocks.Math.Feedback inv
    "Inversion of the control signal"
protected
  Modelica.Blocks.Sources.Constant uni(final k=1)
    "Unitary signal"
equation
  connect(uni.y, inv.u1)
  connect(booToRea.y, inv.u2)
end PartialOperationSequenceInterface;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialParallelElectricEIR
  "Partial model for electric chiller parallel"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialPlantParallel(
    val2(each final dpFixed_nominal=dp2_nominal),
    val1(each final dpFixed_nominal=dp1_nominal));

  parameter Modelica.Units.SI.Time tau1=30
    "Time constant at nominal flow in chillers"
  parameter Modelica.Units.SI.Time tau2=30
    "Time constant at nominal flow in chillers"

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

  // Initialization
  parameter Medium1.AbsolutePressure p1_start = Medium1.p_default
    "Start value of pressure"
  parameter Medium1.Temperature T1_start = Medium1.T_default
    "Start value of temperature"
  parameter Medium1.MassFraction X1_start[Medium1.nX] = Medium1.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium1.ExtraProperty C1_start[Medium1.nC](
    final quantity=Medium1.extraPropertiesNames)=fill(0, Medium1.nC)
    "Start value of trace substances"
  parameter Medium1.ExtraProperty C1_nominal[Medium1.nC](
    final quantity=Medium1.extraPropertiesNames) = fill(1E-2, Medium1.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"
  parameter Medium2.AbsolutePressure p2_start = Medium2.p_default
    "Start value of pressure"
  parameter Medium2.Temperature T2_start = Medium2.T_default
    "Start value of temperature"
  parameter Medium2.MassFraction X2_start[Medium2.nX] = Medium2.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium2.ExtraProperty C2_start[Medium2.nC](
    final quantity=Medium2.extraPropertiesNames)=fill(0, Medium2.nC)
    "Start value of trace substances"
  parameter Medium2.ExtraProperty C2_nominal[Medium2.nC](
    final quantity=Medium2.extraPropertiesNames) = fill(1E-2, Medium2.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"
  Modelica.Blocks.Interfaces.BooleanInput on[num]
    "Set to true to enable compressor, or false to disable compressor"
  Modelica.Blocks.Interfaces.RealInput TSet(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    displayUnit="degC")
    "Set point for leaving water temperature"
  Modelica.Blocks.Interfaces.RealOutput P[num](
    each final quantity="Power",
    each final unit="W")
    "Electric power consumed by chiller compressor"

  replaceable Buildings.Fluid.Chillers.BaseClasses.PartialElectric chi[num]
    constrainedby Buildings.Fluid.Chillers.BaseClasses.PartialElectric(
      redeclare each final package Medium1 = Medium1,
      redeclare each final package Medium2 = Medium2,
      each final allowFlowReversal1=allowFlowReversal1,
      each final allowFlowReversal2=allowFlowReversal2,
      each final show_T=show_T,
      each final from_dp1=from_dp1,
      each final dp1_nominal=0,
      each final linearizeFlowResistance1=linearizeFlowResistance1,
      each final deltaM1=deltaM1,
      each final from_dp2=from_dp2,
      each final dp2_nominal=0,
      each final linearizeFlowResistance2=linearizeFlowResistance2,
      each final deltaM2=deltaM2,
      each final homotopyInitialization=homotopyInitialization,
      each final m1_flow_nominal=m1_flow_nominal,
      each final m2_flow_nominal=m2_flow_nominal,
      each final m1_flow_small=m1_flow_small,
      each final m2_flow_small=m2_flow_small,
      each final tau1=tau1,
      each final tau2=tau2,
      each final energyDynamics=energyDynamics,
      each final p1_start=p1_start,
      each final T1_start=T1_start,
      each final X1_start=X1_start,
      each final C1_start=C1_start,
      each final C1_nominal=C1_nominal,
      each final p2_start=p2_start,
      each final T2_start=T2_start,
      each final X2_start=X2_start,
      each final C2_start=C2_start,
      each final C2_nominal=C2_nominal)
    "Chillers with identical nominal parameters but different performance curves"

equation
  for i in 1:num loop
  connect(TSet, chi[i].TSet)
  connect(chi[i].port_a1, port_a1)
  connect(chi[i].port_a2, port_a2)
  end for;
  connect(chi.port_b2, val2.port_a)
  connect(chi.port_b1, val1.port_a)
  connect(on, chi.on)
  connect(chi.P, P)
end PartialParallelElectricEIR;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialPlantParallel
  "Partial source plant model with associated valves"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.PartialPlantParallelInterface;
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.ValvesParameters(
    final numVal = 2,
    final m_flow_nominal = {m1_flow_nominal,m2_flow_nominal},
    rhoStd = {Medium1.density_pTX(101325, 273.15+4, Medium1.X_default),
            Medium2.density_pTX(101325, 273.15+4, Medium2.X_default)},
    final deltaM=deltaM1);
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.SignalFilter(
    final numAct=num);

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

  // Isolation valve parameters
  parameter Real l[2](each min=1e-10, each max=1) = {0.0001,0.0001}
    "Valve leakage, l=Kv(y=0)/Kv(y=1)"

  Buildings.Fluid.Actuators.Valves.TwoWayLinear val2[num](
    redeclare each replaceable package Medium = Medium2,
    each final allowFlowReversal=allowFlowReversal2,
    each final m_flow_nominal=m2_flow_nominal,
    each dpFixed_nominal=dp2_nominal,
    each final show_T=show_T,
    each final homotopyInitialization=homotopyInitialization,
    each final strokeTime=strokeTime,
    each final init=initValve,
    each final use_strokeTime=false,
    each final deltaM=deltaM2,
    each final l=l[2],
    final y_start=yValve_start,
    each final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    each final from_dp=from_dp2,
    each final linearized=linearizeFlowResistance2,
    each final rhoStd=rhoStd[2],
    each final dpValve_nominal=dpValve_nominal[2])
    "Isolation valves on medium 2 side for on/off use"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val1[num](
    redeclare each replaceable package Medium = Medium1,
    each final allowFlowReversal=allowFlowReversal1,
    each final m_flow_nominal=m1_flow_nominal,
    each dpFixed_nominal=dp1_nominal,
    each final show_T=show_T,
    each final homotopyInitialization=homotopyInitialization,
    each final use_strokeTime=false,
    each final strokeTime=strokeTime,
    each final init=initValve,
    final y_start=yValve_start,
    each final deltaM=deltaM1,
    each final l=l[1],
    each final dpValve_nominal=dpValve_nominal[1],
    each final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    each final from_dp=from_dp1,
    each final linearized=linearizeFlowResistance1,
    each final rhoStd=rhoStd[1])
    "Isolation valves on medium 1 side for on/off use"

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

equation
  for i in 1:num loop
    connect(val1[i].port_b, port_b1)
    connect(val2[i].port_b, port_b2)
  end for;
  if use_strokeTime then
    connect(booToRea.y, actPos.u)
  else
    connect(booToRea.y, y_actual)
  end if;
  connect(on, booToRea.u)
  connect(y_actual, val1.y)
  connect(y_actual, val2.y)
end PartialPlantParallel;


Partial model that implements the interface for parallel plants.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialPlantParallelInterface "Partial model that implements the interface for parallel plants"
  extends Buildings.Fluid.Interfaces.PartialFourPortInterface;
  extends Buildings.Fluid.Interfaces.FourPortFlowResistanceParameters(
     final computeFlowResistance1=true,
     final computeFlowResistance2=true);

  parameter Integer num(min=1)=2 "Number of equipment";

  Modelica.Blocks.Math.BooleanToReal booToRea[num](
    each final realTrue=1,
    each final realFalse=0)
    "Boolean to real (if true then 1 else 0)"
  Modelica.Blocks.Interfaces.BooleanInput on[num]
    "Set to true to enable equipment, or false to disable equipment"
equation
  connect(on, booToRea.u)
end PartialPlantParallelInterface;


Partial model for pump parallel

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model PartialPumpParallel "Partial model for pump parallel"

  extends Buildings.Fluid.Interfaces.PartialTwoPortInterface;
  extends Buildings.Fluid.Actuators.BaseClasses.ValveParameters;

  replaceable parameter Buildings.Fluid.Movers.Data.Generic per[num](
    each motorCooledByFluid=false)
    constrainedby Buildings.Fluid.Movers.Data.Generic
    "Record with performance data"

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

 // Pump parameters
  parameter Integer num=2 "The number of pumps";
  parameter Boolean addPowerToMedium=false
    "Set to false to avoid any power (=heat and flow work) being added to medium (may give simpler equations)"
  parameter Modelica.Units.SI.Time tau=1
    "Time constant at nominal flow (if energyDynamics <> SteadyState)"
  parameter Boolean use_riseTime=true
    "Set to true to continuously change motor speed"
  parameter Boolean use_strokeTime=true
    "Set to true to continuously change valve position"
  parameter Modelica.Units.SI.Time riseTime=30
    "Time needed to change motor speed"
  parameter Modelica.Blocks.Types.Init init=Modelica.Blocks.Types.Init.InitialOutput
    "Type of initialization (no init/steady state/initial state/initial output)"
  parameter Real[num] yPump_start=fill(0,num) "Initial value of pump signals"

   // Valve parameters
  parameter Real l=0.0001 "Valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Modelica.Units.SI.Time strokeTime=riseTime
    "Time needed to open or close valve"
  parameter Real[num] yValve_start = fill(1,num)
    "Initial value of valve signals"

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

  // Initialization
  parameter Medium.AbsolutePressure p_start = Medium.p_default
    "Start value of pressure"
  parameter Medium.Temperature T_start = Medium.T_default
    "Start value of temperature"
  parameter Medium.MassFraction X_start[Medium.nX] = Medium.X_default
    "Start value of mass fractions m_i/m"
  parameter Medium.ExtraProperty C_start[Medium.nC](
    final quantity=Medium.extraPropertiesNames)=fill(0, Medium.nC)
    "Start value of trace substances"
  parameter Medium.ExtraProperty C_nominal[Medium.nC](
    final quantity=Medium.extraPropertiesNames) = fill(1E-2, Medium.nC)
    "Nominal value of trace substances. (Set to typical order of magnitude.)"
  parameter Boolean from_dp = false
    "= true, use m_flow = f(dp) else dp = f(m_flow)"
  parameter Boolean linearizeFlowResistance = false
    "= true, use linear relation between m_flow and dp for any flow rate"
  parameter Real threshold(min = 0.01) = 0.05
    "Hysteresis threshold";
  Modelica.Blocks.Interfaces.RealInput u[num](
    each final unit="1",
    each max=1,
    each min=0)
    "Continuous input signal for the flow machine"
  Modelica.Blocks.Interfaces.RealOutput P[num](
    each final quantity="Power",
    each final unit="W")
    "Electrical power consumed by the pumps"

  replaceable Buildings.Fluid.Movers.BaseClasses.PartialFlowMachine pum[num]
    constrainedby Buildings.Fluid.Movers.BaseClasses.PartialFlowMachine(
    redeclare each final replaceable package Medium = Medium,
    each final inputType=Buildings.Fluid.Types.InputType.Continuous,
    final per=per,
    each final addPowerToMedium=addPowerToMedium,
    each final allowFlowReversal=allowFlowReversal,
    each final m_flow_small=m_flow_small,
    each final show_T=show_T,
    each final tau=tau,
    each final use_riseTime=use_riseTime,
    each final riseTime=riseTime,
    each final init=init,
    each final energyDynamics=energyDynamics,
    each final p_start=p_start,
    each final T_start=T_start,
    each final X_start=X_start,
    each final C_start=C_start,
    each final C_nominal=C_nominal) "Pumps"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear val[num](
    redeclare each final replaceable package Medium = Medium,
    each final dpFixed_nominal=0,
    each final l=l,
    each final CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    each final allowFlowReversal=allowFlowReversal,
    each final show_T=show_T,
    each final rhoStd=rhoStd,
    each final use_strokeTime=use_strokeTime,
    each final strokeTime=strokeTime,
    each final init=init,
    final y_start=yValve_start,
    each final dpValve_nominal=dpValve_nominal,
    each final m_flow_nominal=m_flow_nominal,
    each final deltaM=deltaM,
    each final from_dp=from_dp,
    each final linearized=linearizeFlowResistance,
    each final homotopyInitialization=homotopyInitialization)
    "Isolation valves"

  Buildings.Controls.OBC.CDL.Reals.Hysteresis hys[num](
    each final uLow=threshold,
    each final uHigh=2*threshold) "Hysteresis for isolation valves"

  Buildings.Controls.OBC.CDL.Reals.Switch swi[num]
    "Switch to enable pump only once the valve is commanded open"
protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer[num](
    each final k=0.0) "Outputs 0 as the control signal"
protected
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant one[num](each final k=
        1.0) "Outputs 1 as the control signal"
initial equation
  assert(homotopyInitialization, "In " + getInstanceName() +
    ": The constant homotopyInitialization has been modified from its default value. This constant will be removed in future releases.",
    level = AssertionLevel.warning);

equation
  connect(pum.port_b, val.port_a)
  for i in 1:num loop
  connect(val[i].port_b, port_b)
  connect(port_a, pum[i].port_a)
  end for;
  connect(pum.P, P)
  connect(hys.u, u)
  connect(hys.y, swi.u2)
  connect(zer.y, swi.u3)
  connect(one.y, swi.u1)
  connect(swi.y, val.y)
end PartialPumpParallel;


Partial model that implements the filtered opening for valves and dampers. Partial model that implements the filters that are used to approximate the travel time of the actuators.
The signal y_actual is used to obtain the current position of the actuators.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model SignalFilter  "Partial model that implements the filtered opening for valves and dampers"
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses.SignalFilterParameters;
protected
  Modelica.Blocks.Interfaces.RealOutput[numAct] y_actual "Actual valve position"

  Modelica.Blocks.Nonlinear.SlewRateLimiter[numAct] actPos(
    each Rising=1/strokeTime,
    each Falling=-1/strokeTime,
    each Td=0.001*strokeTime,
    each initType=initValve,
    y_start=yValve_start,
    each strict=true)
    if use_strokeTime
      "Actuator position"

  Modelica.Blocks.Interfaces.RealOutput[numAct] y_filtered if use_strokeTime
    "Filtered valve positions in the range 0..1"
equation
 connect(actPos.y,y_filtered)
  if use_strokeTime then
   connect(actPos.y, y_actual)
 end if;
end SignalFilter;


Model with parameters for a three-way valve. Partial model that decribes the parameters of a three-way valve.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model ThreeWayValveParameters
  "Model with parameters for a three-way valve"
  parameter Boolean activate_ThrWayVal
    "Activate the use of three-way valve: True-use three-way valve; False-not use the three-way valve";
  parameter Modelica.Units.SI.PressureDifference dpThrWayVal_nominal(
    displayUnit="Pa",
    min=0,
    fixed=true) = 6000 "Nominal pressure drop of fully open valve"
  parameter Real fraK_ThrWayVal(
    min=0,
    max=1) = 0.7
    "Fraction Kv(port_3→port_2)/Kv(port_1→port_2)for the three-way valve"
  parameter Real l_ThrWayVal[2](
    each min=1e-10,
    each max=1) = {0.0001,0.0001}
    "Bypass valve leakage, l=Kv(y=0)/Kv(y=1)"
  parameter Real R=50
    "Rangeability, R=50...100 typically for the three-way valve"
  parameter Real delta0=0.01
    "Range of significant deviation from equal percentage law for the three-way valve"
  //Advanced
  parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_1=
    Modelica.Fluid.Types.PortFlowDirection.Bidirectional
    "Flow direction for port_1 in the three-way valve"
  parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_2=
    Modelica.Fluid.Types.PortFlowDirection.Bidirectional
    "Flow direction for port_2 in the three-way valve"
  parameter Modelica.Fluid.Types.PortFlowDirection portFlowDirection_3=
    Modelica.Fluid.Types.PortFlowDirection.Bidirectional
    "Flow direction for port_3 in the three-way valve"
end ThreeWayValveParameters;


Model with parameters for multiple valves. Model that computes the flow coefficients of vectored valves. The number of vectored valves is
defined by the parameter numVal.

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.BaseClasses;
partial model ValvesParameters "Model with parameters for multiple valves"

  parameter Integer numVal "Number of valves";
  parameter Buildings.Fluid.Types.CvTypes CvData=Buildings.Fluid.Types.CvTypes.OpPoint
   "Selection of flow coefficient"
  parameter Real[numVal] Kv(
    each fixed= if CvData==Buildings.Fluid.Types.CvTypes.Kv then true else false)
    "Kv (metric) flow coefficient [m3/h/(bar)^(1/2)]"
  parameter Real[numVal] Cv(
    each fixed= if CvData==Buildings.Fluid.Types.CvTypes.Cv then true else false)
    "Cv (US) flow coefficient [USG/min/(psi)^(1/2)]"
  parameter Modelica.Units.SI.Area[numVal] Av(each fixed=if CvData == Buildings.Fluid.Types.CvTypes.Av
         then true else false) "Av (metric) flow coefficient"
  parameter Real deltaM = 0.02
    "Fraction of nominal flow rate where linearization starts, if y=1"
  parameter Modelica.Units.SI.MassFlowRate[numVal] m_flow_nominal
    "Nominal mass flow rate"
  parameter Modelica.Units.SI.PressureDifference[numVal] dpValve_nominal(
    each displayUnit="Pa",
    each min=0,
    each fixed=if CvData == Buildings.Fluid.Types.CvTypes.OpPoint then true
         else false) = fill(6000, numVal) "Nominal pressure drop of fully open valve, used if
    CvData=Buildings.Fluid.Types.CvTypes.OpPoint"
  parameter Modelica.Units.SI.Density[numVal] rhoStd
    "Inlet density for which valve coefficients are defined"
protected
  parameter Real[numVal] Kv_SI(
    each min=0,
    each fixed= false)
    "Flow coefficient for fully open valve in SI units, Kv=m_flow/sqrt(dp) [kg/s/(Pa)^(1/2)]"
initial equation
  if  CvData == Buildings.Fluid.Types.CvTypes.OpPoint then
    Kv_SI =           m_flow_nominal./sqrt(dpValve_nominal);
    Kv    =           Kv_SI./(rhoStd/3600/sqrt(1E5));
    Cv    =           Kv_SI./(rhoStd*0.0631/1000/sqrt(6895));
    Av    =           Kv_SI./sqrt(rhoStd);
  elseif CvData == Buildings.Fluid.Types.CvTypes.Kv then
    Kv_SI =           Kv.*rhoStd/3600/sqrt(1E5)
      "Unit conversion m3/(h*sqrt(bar)) to kg/(s*sqrt(Pa))";
    Cv    =           Kv_SI./(rhoStd*0.0631/1000/sqrt(6895));
    Av    =           Kv_SI./sqrt(rhoStd);
    dpValve_nominal =  (m_flow_nominal./Kv_SI).^2;
  elseif CvData == Buildings.Fluid.Types.CvTypes.Cv then
    Kv_SI =           Cv.*rhoStd*0.0631/1000/sqrt(6895)
      "Unit conversion USG/(min*sqrt(psi)) to kg/(s*sqrt(Pa))";
    Kv    =           Kv_SI./(rhoStd/3600/sqrt(1E5));
    Av    =           Kv_SI./sqrt(rhoStd);
    dpValve_nominal =  (m_flow_nominal./Kv_SI).^2;
  else
    assert(CvData == Buildings.Fluid.Types.CvTypes.Av, "Invalid value for CvData.
Obtained CvData = " + String(CvData) + ".");
    Kv_SI =           Av.*sqrt(rhoStd);
    Kv    =           Kv_SI./(rhoStd/3600/sqrt(1E5));
    Cv    =           Kv_SI./(rhoStd*0.0631/1000/sqrt(6895));
    dpValve_nominal =  (m_flow_nominal./Kv_SI).^2;
  end if;
end ValvesParameters;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model CoolingCoilHumidifyingHeating_ClosedLoop
  "Model of a air handling unit that tests temperature and humidity control"
  extends Modelica.Icons.Example;
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialAirHandlerControl(
    relHum(k=0.5),
    sou_1(p=500000),
    sou_2(nPorts = 1),
    masFra(redeclare package Medium = Medium2),
    TWat(
      startTime=1200,
      offset=273.15 + 13,
      height=-6));

  parameter Modelica.Units.SI.ThermalConductance UA_nominal=m2_flow_nominal*
      1006*(T_b2_nominal - T_a2_nominal)/
      Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
      T_a1_nominal,
      T_b1_nominal,
      T_a2_nominal,
      T_b2_nominal)
    "Thermal conductance at nominal flow for sensible heat, used to compute time constant";
  parameter Real yValMin = 0.4 "Minimum position of water-side valves";

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.CoolingCoilHumidifyingHeating ahu(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    allowFlowReversal1=true,
    allowFlowReversal2=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    tauEleHea=1,
    tauHum=1,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    UA_nominal=UA_nominal,
    dpValve_nominal=6000,
    mWatMax_flow=0.01,
    perFan(pressure(V_flow=m2_flow_nominal*{0,0.5,1}, dp=300*{1.2,1.12,1})),
    yValve_start=1,
    dp1_nominal=3000,
    dp2_nominal=200,
    use_strokeTime=false,
    QHeaMax_flow=10000,
    yValSwi=yValMin + 0.1,
    yValDeaBan=0.05)
    "Air handling unit"
  Modelica.Blocks.Sources.Constant uFan(k=1) "Control input for fan"
  Modelica.Blocks.Sources.Constant  masFraSet(k=0.011)
    "Setpoint mass fraction"
  Buildings.Controls.Continuous.LimPID PID(
    yMax=1,
    reverseActing=false,
    Td=120,
    yMin=yValMin,
    k=0.5,
    Ti=60)
    "PID controller for the water-side valve in air handling units"
equation
  connect(ahu.port_a2, sou_2.ports[1])
  connect(uFan.y, ahu.uFan)
  connect(ahu.port_b2, temSenAir2.port_a)
  connect(temSenWat1.port_b, ahu.port_a1)
  connect(TSet.y, PID.u_s)
  connect(temSenAir2.T, PID.u_m)
  connect(PID.y, ahu.uVal)
  connect(masFraSet.y, ahu.XSet_w)
  connect(TSet.y, ahu.TSet)
  connect(ahu.port_b1, temSenWat2.port_a)
end CoolingCoilHumidifyingHeating_ClosedLoop;


within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model CoolingCoilHumidifyingHeating_OpenLoop
  "Model of a air handling unit that tests variable mass flow rates"
  extends Modelica.Icons.Example;
  extends Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation.BaseClasses.PartialAirHandlerMassFlow(
      sou_2(nPorts=1), relHum(k=0.5));
  parameter Modelica.Units.SI.ThermalConductance UA_nominal=m2_flow_nominal*
      1006*(12 - 26)/Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
      T_a1_nominal,
      T_b1_nominal,
      T_a2_nominal,
      T_b2_nominal)
    "Thermal conductance at nominal flow for sensible heat, used to compute time constant";
  parameter Real yValMin = 0.4 "Minimum position of water-side valves";

  Buildings.Applications.DataCenters.ChillerCooled.Equipment.CoolingCoilHumidifyingHeating ahu(
    redeclare package Medium1 = Medium1,
    redeclare package Medium2 = Medium2,
    allowFlowReversal1=true,
    allowFlowReversal2=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    yValve_start=0.2,
    tauEleHea=1,
    tauHum=1,
    m1_flow_nominal=m1_flow_nominal,
    m2_flow_nominal=m2_flow_nominal,
    UA_nominal=UA_nominal,
    dpValve_nominal=6000,
    QHeaMax_flow=10000,
    mWatMax_flow=0.01,
    perFan(pressure(V_flow=m2_flow_nominal*{0,0.5,1}, dp=300*{1.2,1.12,1})),
    dp1_nominal=3000,
    dp2_nominal=200,
    yValSwi=yValMin+0.05)
    "Air handling unit"

  Buildings.Fluid.Sensors.RelativeHumidityTwoPort senRelHum(
    redeclare package Medium = Medium2, m_flow_nominal=m2_flow_nominal)
    "Sensor for relative humidity"
  Modelica.Blocks.Sources.Constant uVal(k=0.2)
    "Control signal for water valve"
  Modelica.Blocks.Sources.Constant temSet(k=15 + 273.15)
    "Temperature setpoint "
  Modelica.Blocks.Sources.Constant XSet(k=0.01) "Mass fraction set point"
  Modelica.Blocks.Sources.Constant uFan(k=1) "Control input for fan"
equation
  connect(ahu.port_a2, sou_2.ports[1])
  connect(ahu.port_b2, senRelHum.port_a)
  connect(uVal.y, ahu.uVal)
  connect(uFan.y, ahu.uFan)
  connect(temSet.y, ahu.TSet)
  connect(XSet.y, ahu.XSet_w)
  connect(temSenAir2.port_a, senRelHum.port_b)
  connect(temSenWat1.port_b, ahu.port_a1)
  connect(temSenWat2.port_a, ahu.port_b1)
end CoolingCoilHumidifyingHeating_OpenLoop;


Test model for ElectricHeater

within Buildings.Applications.DataCenters.ChillerCooled.Equipment.Validation;
model ElectricHeater "Test model for ElectricHeater"
  extends Modelica.Icons.Example;
  extends Buildings.Fluid.HeatExchangers.Examples.BaseClasses.Heater(
    redeclare package Medium = Buildings.Media.Air,
    m_flow_nominal=V*1.2*6/3600,
    Q_flow_nominal=30*6*6,
    mov(nominalValuesDefineDefaultPressureCurve=true,
    dp_nominal=1200));
  Buildings.Applications.DataCenters.ChillerCooled.Equipment.ElectricHeater eleHea(
    redeclare package Medium = Medium,
    m_flow_nominal=m_flow_nominal,
    QMax_flow=Q_flow_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=1000,
    eta=0.95)
    "Electric heater"
   Buildings.Controls.SetPoints.Table tab(table=[0,273.15 + 15; 1,273.15 + 30])
    "Temperature set point"
  Modelica.Blocks.Sources.BooleanStep uHea(startTime(displayUnit="min") = 60000)
    "On/off signal"
equation
  connect(mov.port_b, eleHea.port_a)
  connect(eleHea.port_b, THeaOut.port_a)
  connect(conPI.y, tab.u)
  connect(tab.y, eleHea.TSet)
  connect(uHea.y, eleHea.on)
end ElectricHeater;