within Buildings.Examples.DualFanDualDuct;
model ClosedLoop "Closed loop model of a dual-fan dual-duct system"
  extends Modelica.Icons.Example;

  replaceable package MediumA = Buildings.Media.Air(T_default=293.15);
  package MediumW = Buildings.Media.Water "Medium model for water";

  parameter Real yFan_start=0.0 "Initial or guess value of output (= state)";

  parameter Boolean from_dp=true
    "= 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 Modelica.Units.SI.Volume VRooCor=2698 "Room volume corridor";
  parameter Modelica.Units.SI.Volume VRooSou=568.77 "Room volume south";
  parameter Modelica.Units.SI.Volume VRooNor=568.77 "Room volume north";
  parameter Modelica.Units.SI.Volume VRooEas=360.08 "Room volume east";
  parameter Modelica.Units.SI.Volume VRooWes=360.08 "Room volume west";

  constant Real conv=1.2/3600 "Conversion factor for nominal mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate m0_flow_cor=3*VRooCor*conv
    "Design mass flow rate core";
  parameter Modelica.Units.SI.MassFlowRate m0_flow_sou=8*VRooSou*conv
    "Design mass flow rate perimeter 1";
  parameter Modelica.Units.SI.MassFlowRate m0_flow_eas=9*VRooEas*conv
    "Design mass flow rate perimeter 2";
  parameter Modelica.Units.SI.MassFlowRate m0_flow_nor=11*VRooNor*conv
    "Design mass flow rate perimeter 3";
  parameter Modelica.Units.SI.MassFlowRate m0_flow_wes=10*VRooWes*conv
    "Design mass flow rate perimeter 4";

  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=m0_flow_cor +
      m0_flow_sou + m0_flow_eas + m0_flow_nor + m0_flow_wes
    "Nominal air mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mAirOut_flow_nominal=0.3*
      m_flow_nominal "Nominal outside air mass flow rate";
  parameter Modelica.Units.SI.MassFlowRate mAirHot_flow_nominal=0.3*
      m_flow_nominal "Nominal air mass flow rate for hot deck";
  parameter Modelica.Units.SI.MassFlowRate mAirCol_flow_nominal=m_flow_nominal
    "Nominal air mass flow rate for cold deck";
  ///////////////////////////////////////////////////////////////////////////////////////
  // Water mass flow rates
  parameter Modelica.Units.SI.MassFlowRate mWatPre_flow_nominal=(
      TMixHea_nominal - 273.15 - (-20))*1000/15/4200*mAirOut_flow_nominal
    "Nominal water mass flow rate for preheat coil";
  parameter Modelica.Units.SI.MassFlowRate mWatCol_flow_nominal=(28 - 13)*1000*
      1.3/4200/15*mAirCol_flow_nominal
    "Nominal water mass flow rate for cooling coil of cold deck";
  parameter Modelica.Units.SI.MassFlowRate mWatHot_flow_nominal=(40 - (
      TMixHea_nominal - 273.15))*1000/15/4200*mAirHot_flow_nominal
    "Nominal water mass flow rate for heating coil of cold deck";
  // Water temperatures
  parameter Modelica.Units.SI.Temperature TMixHea_nominal=0.3*(273.15 + (-20))
       + 0.7*(273.15 + 20) "Mixed air temperature at winter design conditions";
  parameter Modelica.Units.SI.Temperature TMixCoo_nominal=0.3*(273.15 + (33))
       + 0.7*(273.15 + 26) "Mixed air temperature at summer design conditions";
  parameter Modelica.Units.SI.Temperature TSupCol_nominal=12 + 273.15
    "Cold deck temperature at nominal condition";

  Buildings.Fluid.Sources.Outside amb(redeclare package Medium = MediumA, nPorts=2)
    "Ambient conditions"
  Buildings.Fluid.FixedResistances.PressureDrop fil(
    m_flow_nominal=m_flow_nominal,
    redeclare package Medium = MediumA,
    dp_nominal=200 + 200 + 200 + 100,
    from_dp=from_dp,
    linearized=linearizeFlowResistance) "Filter"
  Buildings.Fluid.HeatExchangers.DryCoilEffectivenessNTU preHeaCoi(
    redeclare package Medium1 = MediumA,
    redeclare package Medium2 = MediumW,
    allowFlowReversal2=false,
    dp2_nominal=6000,
    m1_flow_nominal=m_flow_nominal,
    m2_flow_nominal=mWatPre_flow_nominal,
    dp1_nominal=0,
    Q_flow_nominal=mAirOut_flow_nominal*1006*(TMixHea_nominal - TSupCol_nominal),
    T_a1_nominal=281.65,
    T_a2_nominal=323.15,
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.ParallelFlow)
    "Preheat coil"

  Fluid.HeatExchangers.WetCoilEffectivenessNTU cooCoi(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumA,
    m1_flow_nominal=mWatCol_flow_nominal,
    m2_flow_nominal=mAirCol_flow_nominal,
    UA_nominal=-mAirCol_flow_nominal*1000*15/
        Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
        T_a1=6,
        T_b1=12,
        T_a2=28,
        T_b2=13),
    dp2_nominal=0,
    from_dp2=from_dp,
    linearizeFlowResistance2=linearizeFlowResistance,
    dp1_nominal=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Cooling coil"
  Buildings.Fluid.Movers.SpeedControlled_y fanSupHot(
    redeclare package Medium = MediumA,
    per(pressure(V_flow=mAirHot_flow_nominal/1.2*{0,2}, dp=600*{2,0})),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
                           "Supply air fan for hot deck"
  Buildings.Fluid.Movers.Preconfigured.SpeedControlled_y fanSupCol(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAirCol_flow_nominal,
    dp_nominal=600,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
                           "Supply air fan for cold deck"
  Buildings.Fluid.Movers.Preconfigured.SpeedControlled_y fanRet(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    dp_nominal=100,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
                           "Return air fan"
  Buildings.Fluid.Sources.Boundary_pT sinHea(
    redeclare package Medium = MediumW,
    nPorts=2,
    p=300000,
    T=308.15) "Sink for heating coil"
  Buildings.Fluid.Sources.Boundary_pT sinCoo(
    redeclare package Medium = MediumW,
    p=300000,
    T=285.15,
    nPorts=1) "Sink for cooling coil"
  Modelica.Blocks.Routing.RealPassThrough TOut(y(
      final quantity="ThermodynamicTemperature",
      final unit="K",
      displayUnit="degC",
      min=0))
  Buildings.Examples.DualFanDualDuct.Controls.HeatingCoilTemperatureSetpoint
    TSupSetHea(TOn=284.15, TOff=279.15)
    "Set point for preheat coil outlet temperature "
  Buildings.Examples.VAVReheat.BaseClasses.Controls.FanVFD conFanSupHot(
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=yFan_start,
    xSet_nominal(
      final unit="Pa",
      displayUnit="Pa") = 30,
    r_N_min=0.2,
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    k=1) "Controller for fan of hot deck"
  Buildings.Controls.SetPoints.OccupancySchedule occSch(occupancy=3600*{6,19})
    "Occupancy schedule"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.ModeSelector modeSelector
  Buildings.Examples.VAVReheat.BaseClasses.Controls.ControlBus controlBus
  Buildings.Fluid.Sensors.TemperatureTwoPort TPreHeaCoi(redeclare package Medium =
               MediumA, m_flow_nominal=m_flow_nominal)
    "Preheating coil outlet temperature"
  Buildings.Utilities.Math.Min min(nin=5) "Computes lowest room temperature"
  Buildings.Utilities.Math.Average ave(nin=5)
    "Compute average of room temperatures"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear valCoo(
    redeclare package Medium = MediumW,
    CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    m_flow_nominal=m_flow_nominal*1000*15/4200/10,
    dpValve_nominal=6000,
    from_dp=true,
    dpFixed_nominal=6000,
    use_strokeTime=false) "Cooling coil valve"
  Buildings.Fluid.Sources.Boundary_pT souCoo(
    redeclare package Medium = MediumW,
    p=3E5 + 12000,
    nPorts=1,
    T=279.15) "Source for cooling coil"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.Economizer conEco(
    have_frePro=true,
    VOut_flow_min=0.3*m_flow_nominal/1.2,
    k=0.05,
    Ti=1200)
           "Controller for economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort TRet(redeclare package Medium =
        MediumA, m_flow_nominal=m_flow_nominal) "Return air temperature sensor"
  Buildings.Fluid.Sensors.TemperatureTwoPort TMix(redeclare package Medium =
        MediumA, m_flow_nominal=m_flow_nominal) "Mixed air temperature sensor"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.RoomTemperatureSetpoint TSetRoo(THeaOff=
        289.15)
  Buildings.Fluid.Sources.Boundary_pT souHea(
    redeclare package Medium = MediumW,
    p(displayUnit="Pa") = 300000 + 12000,
    T=318.15,
    nPorts=2) "Source for heating coil"
  Buildings.Fluid.Actuators.Dampers.MixingBox eco(
    redeclare package Medium = MediumA,
    mOut_flow_nominal=m_flow_nominal,
    mRec_flow_nominal=m_flow_nominal,
    mExh_flow_nominal=m_flow_nominal,
    from_dp=from_dp,
    linearized=true,
    strokeTime=15,
    y_start=0,
    dpDamExh_nominal=0.27,
    dpDamOut_nominal=0.27,
    dpDamRec_nominal=0.27,
    dpFixExh_nominal=10,
    dpFixOut_nominal=10,
    dpFixRec_nominal=10) "Economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCoiCoo(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAirCol_flow_nominal) "Cooling coil outlet temperature"
  Buildings.Fluid.Sensors.VolumeFlowRate VOut1(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    tau=1) "Outside air volume flow rate"
  Buildings.Examples.DualFanDualDuct.ThermalZones.SupplyBranch cor(
    redeclare package MediumA = MediumA,
    m_flow_nominal=m0_flow_cor,
    VRoo=2698,
    from_dp=true) "Zone for core of buildings (azimuth will be neglected)"
  Buildings.Examples.DualFanDualDuct.ThermalZones.SupplyBranch sou(
    redeclare package MediumA = MediumA,
    m_flow_nominal=m0_flow_sou,
    VRoo=568.77,
    from_dp=true) "South-facing thermal zone"
  Buildings.Examples.DualFanDualDuct.ThermalZones.SupplyBranch eas(
    redeclare package MediumA = MediumA,
    m_flow_nominal=m0_flow_eas,
    VRoo=360.08,
    from_dp=true) "East-facing thermal zone"
  Buildings.Examples.DualFanDualDuct.ThermalZones.SupplyBranch nor(
    redeclare package MediumA = MediumA,
    m_flow_nominal=m0_flow_nor,
    VRoo=568.77,
    from_dp=true) "North-facing thermal zone"
  Buildings.Examples.DualFanDualDuct.ThermalZones.SupplyBranch wes(
    redeclare package MediumA = MediumA,
    m_flow_nominal=m0_flow_wes,
    VRoo=360.08,
    from_dp=true) "West-facing thermal zone"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.FanVFD conFanRet(
    xSet_nominal(
      final unit="Pa",
      displayUnit="Pa") = 30,
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=yFan_start,
    r_N_min=0.2,
    k=1,
    Ti=15,
    controllerType=Modelica.Blocks.Types.SimpleController.P)
    "Controller for return air fan"
  Buildings.Fluid.FixedResistances.Junction splRetRoo1(
    redeclare package Medium = MediumA,
    m_flow_nominal={m_flow_nominal,m_flow_nominal - m0_flow_cor,m0_flow_cor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {30,0,70},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room return"
  Buildings.Fluid.FixedResistances.Junction splRetSou(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_sou + m0_flow_eas + m0_flow_nor + m0_flow_wes,
        m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_sou},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {20,0,50},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room return"
  Buildings.Fluid.FixedResistances.Junction splRetEas(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_nor +
        m0_flow_wes,m0_flow_eas},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {20,0,30},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room return"
  Buildings.Fluid.FixedResistances.Junction splRetNor(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_nor + m0_flow_wes,m0_flow_wes,m0_flow_nor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {20,10,10},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room return"
  Buildings.Fluid.FixedResistances.Junction splSupRoo1Hot(
    redeclare package Medium = MediumA,
    m_flow_nominal={m_flow_nominal,m_flow_nominal - m0_flow_cor,m0_flow_cor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {240,0,-80},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupSouHot(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_sou + m0_flow_eas + m0_flow_nor + m0_flow_wes,
        m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_sou},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-60},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupEasHot(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_nor +
        m0_flow_wes,m0_flow_eas},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-40},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupNorHot(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_nor + m0_flow_wes,m0_flow_wes,m0_flow_nor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-20},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Examples.DualFanDualDuct.Controls.CoolingCoilTemperatureSetpoint
    TSetCoo(
      TOn=285.15,
      TOff=313.15)
    "Set point for cooling coil"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  BoundaryConditions.WeatherData.Bus weaBus "Weather Data Bus"
  Buildings.Examples.VAVReheat.BaseClasses.Floor flo(
    redeclare package Medium = MediumA)
    "Model of a floor of the building that is served by this VAV system"
  Modelica.Blocks.Routing.DeMultiplex5 TRooAir
    "Demultiplex for room air temperature"

  Buildings.Fluid.HeatExchangers.DryCoilEffectivenessNTU          heaCoi(
    redeclare package Medium1 = MediumW,
    redeclare package Medium2 = MediumA,
    m1_flow_nominal=mWatHot_flow_nominal,
    m2_flow_nominal=mAirHot_flow_nominal,
    Q_flow_nominal=mAirHot_flow_nominal*1000*(12 - 45),
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    dp2_nominal=0,
    from_dp2=from_dp,
    linearizeFlowResistance2=linearizeFlowResistance,
    dp1_nominal=0,
    T_a1_nominal=285.15,
    T_a2_nominal=318.15) "Heating coil for hot deck"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCoiHea(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAirHot_flow_nominal) "Heating coil outlet temperature"
  Buildings.Fluid.FixedResistances.Junction splHotColDec(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal*{1,1,1},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal(each displayUnit="Pa") = {5,5,0})
    "Splitter for cold deck"
  Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage valPreHea(
    redeclare package Medium = MediumW,
    CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    dpValve_nominal=6000,
    from_dp=true,
    m_flow_nominal=mWatPre_flow_nominal,
    use_strokeTime=false) "Preheating coil valve"
  Buildings.Fluid.Movers.FlowControlled_m_flow pumPreHea(
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    m_flow_nominal=mWatPre_flow_nominal,
    inputType=Buildings.Fluid.Types.InputType.Continuous,
    nominalValuesDefineDefaultPressureCurve=true,
    dp_nominal=6000)
    "Pump for preheat coil (to ensure constant flow through the coil)"
  Buildings.Fluid.FixedResistances.Junction splCol1(
    from_dp=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    linearized=true,
    dp_nominal(each displayUnit="Pa") = {0,0,0},
    redeclare package Medium = MediumW,
    m_flow_nominal=mWatPre_flow_nominal*{1,1,1}) "Splitter for cold deck"
  Buildings.Fluid.FixedResistances.Junction splCol2(
    from_dp=true,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    linearized=true,
    dp_nominal(each displayUnit="Pa") = {0,0,0},
    redeclare package Medium = MediumW,
    m_flow_nominal=mWatPre_flow_nominal*{1,1,1}) "Splitter for cold deck"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear valHea(
    redeclare package Medium = MediumW,
    CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    dpValve_nominal=6000,
    from_dp=true,
    m_flow_nominal=mWatPre_flow_nominal,
    dpFixed_nominal=6000,
    use_strokeTime=false) "Heating coil valve"
  Buildings.Controls.Continuous.LimPID heaCoiCon(
    Td=60,
    initType=Modelica.Blocks.Types.Init.InitialState,
    yMax=1,
    yMin=0,
    Ti=120,
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    k=1) "Controller for heating coil"
  Buildings.Controls.SetPoints.Table TSetHot(table=[273.15 + 5,273.15 + 40; 273.15
         + 22,273.15 + 22]) "Setpoint for hot deck temperature"
  Buildings.Fluid.FixedResistances.Junction splSupRoo1Col(
    redeclare package Medium = MediumA,
    m_flow_nominal={m_flow_nominal,m_flow_nominal - m0_flow_cor,m0_flow_cor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal(each displayUnit="Pa") = {240,0,-80},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupSouCol(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_sou + m0_flow_eas + m0_flow_nor + m0_flow_wes,
        m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_sou},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-60},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupEasCol(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_eas + m0_flow_nor + m0_flow_wes,m0_flow_nor +
        m0_flow_wes,m0_flow_eas},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-40},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Buildings.Fluid.FixedResistances.Junction splSupNorCol(
    redeclare package Medium = MediumA,
    m_flow_nominal={m0_flow_nor + m0_flow_wes,m0_flow_wes,m0_flow_nor},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal={20,0,-20},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
    "Splitter for room supply"
  Modelica.Blocks.Sources.Constant pStaPre_Set(      y(final unit="Pa", min=0), k=30)
    "Setpoint for static pressure"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.FanVFD conFanSupCol(
    initType=Modelica.Blocks.Types.Init.InitialState,
    y_start=yFan_start,
    xSet_nominal(
      final unit="Pa",
      displayUnit="Pa") = 30,
    r_N_min=0.2) "Controller for fan of cold deck"
  Modelica.Blocks.Sources.Constant pStaBui_Set(y(final unit="Pa", min=0), k=30)
    "Setpoint for static pressure of building"

  Controls.PreHeatCoil conPreHeatCoi "Controller for preheat coil"
  Modelica.Blocks.Math.Gain gaiPumPreCoi(k=mWatPre_flow_nominal)
    "Gain for preheat coil pump"
  Buildings.Controls.Continuous.LimPID conCooCoi(
    Td=60,
    initType=Modelica.Blocks.Types.Init.InitialState,
    yMax=1,
    yMin=0,
    Ti=120,
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    k=1,
    reverseActing=false) "Controller for cooling coil"
  Controls.MixedAirTemperatureSetpoint TMixSet
    "Mixed air temperature set point"
  Buildings.Controls.OBC.CDL.Reals.PID conTMix(
    k=0.05,
    Ti=1200,
    reverseActing=false) "Controller for mixed air temperature"
equation
  connect(fil.port_b, preHeaCoi.port_a1)
  connect(controlBus, modeSelector.cb)
  connect(occSch.tNexOcc, controlBus.dTNexOcc)
  connect(TOut.y, controlBus.TOut)
  connect(occSch.occupied, controlBus.occupied)
  connect(min.y, controlBus.TRooMin)
  connect(ave.y, controlBus.TRooAve)
  connect(TRet.T, conEco.TRet)
  connect(TMix.T, conEco.TMix)
  connect(controlBus, conEco.controlBus)
  connect(TSetRoo.controlBus, controlBus)
  connect(fil.port_a, TMix.port_b)
  connect(cor.controlBus, controlBus)
  connect(sou.controlBus, controlBus)
  connect(eas.controlBus, controlBus)
  connect(nor.controlBus, controlBus)
  connect(wes.controlBus, controlBus)
  connect(conEco.yOA, eco.y)
  connect(eco.port_Exh, amb.ports[1])
  connect(amb.ports[2], VOut1.port_a)
  connect(VOut1.port_b, eco.port_Out)
  connect(eco.port_Sup, TMix.port_a)
  connect(preHeaCoi.port_b1, TPreHeaCoi.port_a)
  connect(TRet.port_b, eco.port_Ret)
  connect(splRetNor.port_1, splRetEas.port_2)
  connect(splRetEas.port_1, splRetSou.port_2)
  connect(splRetSou.port_1, splRetRoo1.port_2)
  connect(splSupRoo1Hot.port_2, splSupSouHot.port_1)
  connect(splSupSouHot.port_2, splSupEasHot.port_1)
  connect(splSupEasHot.port_2, splSupNorHot.port_1)
  connect(cooCoi.port_b2, TCoiCoo.port_a)
  connect(valCoo.port_b, cooCoi.port_a1)
  connect(cooCoi.port_b1, sinCoo.ports[1])
  connect(conEco.VOut_flow, VOut1.V_flow)
  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.u)
  connect(amb.weaBus, weaBus)
  connect(cor.port_b, flo.portsCor[1])
  connect(splRetRoo1.port_3, flo.portsCor[2])
  connect(sou.port_b, flo.portsSou[1])
  connect(splRetSou.port_3, flo.portsSou[2])
  connect(eas.port_b, flo.portsEas[1])
  connect(splRetEas.port_3, flo.portsEas[2])
  connect(nor.port_b, flo.portsNor[1])
  connect(splRetNor.port_3, flo.portsNor[2])
  connect(wes.port_b, flo.portsWes[1])
  connect(splRetNor.port_2, flo.portsWes[2])
  connect(weaBus, flo.weaBus)
  connect(flo.TRooAir, min.u)
  connect(flo.TRooAir, ave.u)
  connect(TRooAir.y1[1], sou.TRoo)
  connect(TRooAir.y2[1], eas.TRoo)
  connect(TRooAir.y3[1], nor.TRoo)
  connect(TRooAir.y4[1], wes.TRoo)
  connect(TRooAir.y5[1], cor.TRoo)
  connect(TRooAir.u, flo.TRooAir)
  connect(fanSupCol.port_b, cooCoi.port_a2)
  connect(fanSupHot.port_b, heaCoi.port_a2)
  connect(heaCoi.port_b2, TCoiHea.port_a)
  connect(TPreHeaCoi.port_b, splHotColDec.port_3)
  connect(splHotColDec.port_1, fanSupCol.port_a)

  connect(pumPreHea.port_b, preHeaCoi.port_a2)
  connect(souHea.ports[1], valPreHea.port_a)
  connect(valPreHea.port_b, splCol1.port_1)
  connect(splCol1.port_2, pumPreHea.port_a)
  connect(splCol2.port_3, splCol1.port_3)
  connect(splCol2.port_1, preHeaCoi.port_b2)
  connect(splCol2.port_2, sinHea.ports[1])
  connect(heaCoi.port_a1, valHea.port_b)
  connect(valHea.port_a, souHea.ports[2])
  connect(heaCoi.port_b1, sinHea.ports[2])
  connect(TSetHot.y, heaCoiCon.u_s)
  connect(heaCoiCon.u_m, TCoiHea.T)
  connect(heaCoiCon.y, valHea.y)
  connect(valCoo.port_a, souCoo.ports[1])
  connect(splSupRoo1Col.port_2, splSupSouCol.port_1)
  connect(splSupSouCol.port_2, splSupEasCol.port_1)
  connect(splSupEasCol.port_2, splSupNorCol.port_1)
  connect(cor.port_aHot, splSupRoo1Hot.port_3)
  connect(cor.port_aCol, splSupRoo1Col.port_3)
  connect(sou.port_aHot, splSupSouHot.port_3)
  connect(sou.port_aCol, splSupSouCol.port_3)
  connect(eas.port_aHot, splSupEasHot.port_3)
  connect(eas.port_aCol, splSupEasCol.port_3)
  connect(nor.port_aHot, splSupNorHot.port_3)
  connect(nor.port_aCol, splSupNorCol.port_3)
  connect(splSupNorHot.port_2, wes.port_aHot)
  connect(splSupNorCol.port_2, wes.port_aCol)
  connect(nor.p_relHot, conFanSupHot.u_m)
  connect(pStaPre_Set.y, conFanSupHot.u)
  connect(pStaPre_Set.y, conFanSupCol.u)
  connect(nor.p_relCol, conFanSupCol.u_m)
  connect(flo.p_rel, conFanRet.u_m)
  connect(controlBus.TOut, TSetHot.u)
  connect(conFanRet.y, fanRet.y)
  connect(conFanSupHot.y, fanSupHot.y)
  connect(conFanSupCol.y, fanSupCol.y)
  connect(pStaBui_Set.y, conFanRet.u)
  connect(TCoiCoo.port_b, splSupRoo1Col.port_1)
  connect(TCoiHea.port_b, splSupRoo1Hot.port_1)
  connect(splRetRoo1.port_1, fanRet.port_a)
  connect(TRet.port_a, fanRet.port_b)
  connect(splHotColDec.port_2, fanSupHot.port_a)
  connect(gaiPumPreCoi.y, pumPreHea.m_flow_in)
  connect(conPreHeatCoi.yPum, gaiPumPreCoi.u)
  connect(conPreHeatCoi.TSupSetHea, TSupSetHea.TSet)
  connect(conPreHeatCoi.TMix, TMix.T)
  connect(TPreHeaCoi.T, conPreHeatCoi.TAirSup)
  connect(conPreHeatCoi.yVal, valPreHea.y)
  connect(modeSelector.yFan, conFanSupCol.uFan)
  connect(modeSelector.yFan, conFanSupHot.uFan)
  connect(modeSelector.yFan, conFanRet.uFan)
  connect(cor.yFan, modeSelector.yFan)
  connect(modeSelector.yFan, sou.yFan)
  connect(modeSelector.yFan, eas.yFan)
  connect(modeSelector.yFan, nor.yFan)
  connect(modeSelector.yFan, wes.yFan)
  connect(modeSelector.yEco, conEco.uEna)
  connect(conCooCoi.y, valCoo.y)
  connect(TCoiCoo.T, conCooCoi.u_m)
  connect(TSetCoo.TSet, conCooCoi.u_s)
  connect(controlBus, TSetCoo.controlBus)
  connect(controlBus, TSupSetHea.controlBus)
  connect(controlBus, TMixSet.controlBus)
  connect(TSupSetHea.TSet, TMixSet.TSupHeaSet)
  connect(TSetCoo.TSet, TMixSet.TSupCooSet)
  connect(conTMix.y, conEco.uOATSup)
  connect(TMixSet.TSet, conTMix.u_s)
  connect(TMix.T, conTMix.u_m)
end ClosedLoop;


within Buildings.Examples;
package DualFanDualDuct "Dual fan dual duct HVAC system with five thermal zones"
  extends Modelica.Icons.ExamplesPackage;
end DualFanDualDuct;


Set point scheduler for cooling coil.

within Buildings.Examples.DualFanDualDuct.Controls;
block CoolingCoilTemperatureSetpoint "Set point scheduler for cooling coil"
  extends Modelica.Blocks.Icons.Block;
  import Buildings.Examples.VAVReheat.BaseClasses.Controls.OperationModes;
  parameter Modelica.Units.SI.Temperature TOn(displayUnit="degC")
    "Setpoint during on";
  parameter Modelica.Units.SI.Temperature TOff(displayUnit="degC")
    "Setpoint during off";
  Modelica.Blocks.Sources.RealExpression TSetPoi(
     y(final unit="K", displayUnit="degC")=if (mode.y == Integer(OperationModes.occupied) or
           mode.y == Integer(OperationModes.unoccupiedPreCool) or
           mode.y == Integer(OperationModes.safety)) then TOn else TOff)
    "Air temperature setpoint"
  VAVReheat.BaseClasses.Controls.ControlBus controlBus
  Modelica.Blocks.Routing.IntegerPassThrough mode
  Modelica.Blocks.Interfaces.RealOutput TSet(
    final unit="K",
    displayUnit="degC")
    "Temperature set point"
equation
  connect(controlBus.controlMode, mode.u)
  connect(TSetPoi.y, TSet)
end CoolingCoilTemperatureSetpoint;


Set point scheduler for heating coil.

within Buildings.Examples.DualFanDualDuct.Controls;
block HeatingCoilTemperatureSetpoint "Set point scheduler for heating coil"
  import Buildings.Examples.VAVReheat.BaseClasses.Controls.OperationModes;
  extends CoolingCoilTemperatureSetpoint(TSetPoi(
    y=if (mode.y == Integer(OperationModes.unoccupiedOff)) then TOff else TOn));
end HeatingCoilTemperatureSetpoint;


Mixed air temperature setpoint for economizer.

within Buildings.Examples.DualFanDualDuct.Controls;
model MixedAirTemperatureSetpoint
  "Mixed air temperature setpoint for economizer"
  extends Modelica.Blocks.Icons.Block;
  Modelica.Blocks.Routing.Extractor TSetMix(
    nin=6,
    index(start=2, fixed=true)) "Mixed air setpoint temperature extractor"
  Modelica.Blocks.Sources.Constant off(k=273.15 + 13)
    "Setpoint temperature to close damper"
  Buildings.Utilities.Math.Average ave(nin=2)
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupHeaSet(
    final unit="K",
    displayUnit="degC")
    "Supply temperature setpoint for heating"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TSupCooSet(
    final unit="K",
    displayUnit="degC")
    "Supply temperature setpoint for cooling"
  Buildings.Controls.OBC.CDL.Interfaces.RealOutput TSet(
    final unit="K",
    displayUnit="degC")
   "Mixed air temperature setpoint"
  Modelica.Blocks.Sources.Constant TPreCoo(k=273.15 + 13)
    "Setpoint during pre-cooling"
  VAVReheat.BaseClasses.Controls.ControlBus controlBus
  Modelica.Blocks.Routing.Multiplex2 multiplex2_1
equation
  connect(TSetMix.u[1], ave.y)
  connect(ave.y, TSetMix.u[1])
  connect(off.y, TSetMix.u[2])
  connect(off.y, TSetMix.u[3])
  connect(off.y, TSetMix.u[4])
  connect(TPreCoo.y, TSetMix.u[5])
  connect(off.y, TSetMix.u[6])
  connect(controlBus.controlMode, TSetMix.index)
  connect(TSetMix.y, TSet)
  connect(multiplex2_1.y, ave.u)
  connect(TSupCooSet, multiplex2_1.u2[1])
  connect(TSupHeaSet, multiplex2_1.u1[1])
end MixedAirTemperatureSetpoint;


Package with controller models

within Buildings.Examples.DualFanDualDuct;
package Controls "Package with controller models"
    extends Modelica.Icons.VariantsPackage;
end Controls;


Controller for preheat coil. Controller for the preheat coil. If the air inlet temperature is below
a minimum temperature, such as <i>10</i>°C, the preheat coil is activated.
It then switches the pump on, and regulates the valve
to meet the set point temperature for the supply air.

within Buildings.Examples.DualFanDualDuct.Controls;
model PreHeatCoil "Controller for preheat coil"
  extends Modelica.Blocks.Icons.Block;

  Buildings.Controls.Continuous.LimPID preHeaCoiCon(
    yMax=1,
    yMin=0,
    Td=60,
    initType=Modelica.Blocks.Types.Init.InitialState,
    Ti=120,
    strict=true,
    k=0.1) "Controller for pre-heating coil"
  Modelica.Blocks.Sources.Constant zero(k=0) "Zero output signal"
  Modelica.Blocks.Logical.Switch swiPumPreCoi "Switch for preheat coil pump"
  Modelica.Blocks.Logical.OnOffController preHeaOn(bandwidth=1)
    "Switch to enable preheat coil"
  Modelica.Blocks.Sources.Constant TPreHeaOn(k=273.15 + 10)
    "Temperature when preheat coil is switched on."
  Modelica.Blocks.Sources.Constant one(k=1) "Outputs 1"
  Modelica.Blocks.Interfaces.RealInput TAirSup(unit="K")
    "Supply air temperature after the coil"
  Modelica.Blocks.Interfaces.RealInput TSupSetHea(unit="K")
    "Heating set point temperature for supply air"
  Modelica.Blocks.Interfaces.RealOutput yVal(unit="1")
    "Control signal for valve"
  Modelica.Blocks.Interfaces.RealInput TMix(unit="K")
    "Mixed air temperature upstream of coil"
  Modelica.Blocks.Interfaces.RealOutput yPum(unit="1")
    "Control signal for pump"
  Modelica.Blocks.Logical.Switch swiValOp
    "Switch to close valve if pump is not running"
  Modelica.StateGraph.InitialStep pumOff(nIn=1, nOut=1)
                                         "Pump is off"
  Modelica.StateGraph.TransitionWithSignal toOn "Switch pump on"
    inner Modelica.StateGraph.StateGraphRoot
                         stateGraphRoot
  Modelica.StateGraph.StepWithSignal pumOn(nIn=1, nOut=1)
                                           "Pump on"
  Modelica.StateGraph.TransitionWithSignal toOff(enableTimer=true, waitTime=30*
        60) "Switch pump off"
  Modelica.Blocks.Logical.Not not1
equation
  connect(preHeaOn.reference,TPreHeaOn. y)
  connect(zero.y, swiPumPreCoi.u3)
  connect(one.y, swiPumPreCoi.u1)
  connect(TAirSup, preHeaCoiCon.u_m)
  connect(TSupSetHea, preHeaCoiCon.u_s)
  connect(TMix, preHeaOn.u)
  connect(yPum, swiPumPreCoi.y)
  connect(zero.y, swiValOp.u3)
  connect(swiValOp.y, yVal)
  connect(pumOff.outPort[1], toOn.inPort)
  connect(toOn.condition, preHeaOn.y)
  connect(pumOn.inPort[1], toOn.outPort)
  connect(toOff.inPort, pumOn.outPort[1])
  connect(preHeaOn.y, not1.u)
  connect(not1.y, toOff.condition)
  connect(toOff.outPort, pumOff.inPort[1])
  connect(pumOn.active, swiPumPreCoi.u2)
  connect(pumOn.active, swiValOp.u2)
  connect(preHeaCoiCon.y, swiValOp.u1)
end PreHeatCoil;


Controller for room mixing box.

within Buildings.Examples.DualFanDualDuct.Controls;
block RoomMixingBox "Controller for room mixing box"
  extends Modelica.Blocks.Icons.Block;

  parameter Modelica.Units.SI.MassFlowRate m_flow_min "Minimum mass flow rate";
  Buildings.Controls.OBC.CDL.Reals.PID conHea(
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    Td=60,
    k=0.1,
    Ti=120) "Controller for heating"
  Buildings.Controls.OBC.CDL.Reals.PID conCoo(
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    reverseActing=false,
    Td=60,
    k=0.1,
    Ti=120) "Controller for cooling (acts on damper)"
  Modelica.Blocks.Interfaces.RealInput TRoo(
    final quantity="ThermodynamicTemperature",
    final unit = "K",
    displayUnit = "degC", min=0)
    "Measured room temperature"
  Modelica.Blocks.Interfaces.RealOutput yHot "Signal for hot air damper"
  Modelica.Blocks.Interfaces.RealOutput yCol "Signal for cold deck air damper"
  Modelica.Blocks.Interfaces.RealInput mAir_flow
    "Measured air mass flow rate into the room"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput yFan
    "Fan operation, true if fan is running"
  Buildings.Controls.OBC.CDL.Reals.PID conFloRat(
    controllerType=Buildings.Controls.OBC.CDL.Types.SimpleController.PI,
    Td=60,
    k=0.1,
    Ti=120,
    r=m_flow_min)   "Controller for mass flow rate"
  Modelica.Blocks.Sources.Constant mAirSet(k=m_flow_min)
    "Set point for minimum air flow rate"
  Buildings.Controls.OBC.CDL.Reals.Max max
    "Adds control signal for minimum flow rate of zone"
  Modelica.Blocks.Interfaces.RealInput TRooSetHea(unit="K")
    "Room temperature setpoint for heating"
  Modelica.Blocks.Interfaces.RealInput TRooSetCoo(unit="K")
    "Room temperature setpoint for cooling"
  Modelica.Blocks.Sources.RealExpression gaiHea(y=1 - gaiCoo.y)
    "Gain for adding minimum flow rate to cooling signal"
  Modelica.Blocks.Math.Product product
  Modelica.Blocks.Math.Product product1
  Buildings.Controls.OBC.CDL.Reals.Max maxCoo
    "Adds control signal for minimum flow rate of zone"
  Buildings.Controls.OBC.CDL.Reals.Subtract dTSet
    "Difference in set point"
  Buildings.Controls.OBC.CDL.Reals.Subtract dTRooHea
    "Difference in room air temperature compared to heating setpoint"
  Buildings.Controls.OBC.CDL.Reals.Limiter gaiCoo(uMax=1, uMin=0)
    "Gain of cooling"
  Buildings.Controls.OBC.CDL.Reals.Divide gaiCooUnl
    "Gain of cooling, unlimited"
  Buildings.Controls.OBC.CDL.Reals.Switch swiHot "Switch for heating"
  Buildings.Controls.OBC.CDL.Reals.Switch swiCoo "Switch for cooling"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(k=0) "Zero signal"
equation
  connect(mAir_flow, conFloRat.u_m)
  connect(conHea.y, max.u1)
  connect(conHea.u_s, TRooSetHea)
  connect(conCoo.u_s, TRooSetCoo)
  connect(TRoo, conCoo.u_m)
  connect(TRoo, conHea.u_m)
  connect(conFloRat.y, product.u1)
  connect(product.y, max.u2)
  connect(product.u2, gaiHea.y)
  connect(mAirSet.y, conFloRat.u_s)
  connect(dTSet.u1, TRooSetCoo)
  connect(dTSet.u2, TRooSetHea)
  connect(dTRooHea.u1, TRoo)
  connect(dTRooHea.u2, TRooSetHea)
  connect(gaiCooUnl.u1, dTRooHea.y)
  connect(dTSet.y, gaiCooUnl.u2)
  connect(gaiCooUnl.y, gaiCoo.u)
  connect(gaiCoo.y, product1.u2)
  connect(conFloRat.y, product1.u1)
  connect(conCoo.y, maxCoo.u1)
  connect(maxCoo.u2, product1.y)
  connect(swiHot.y, yHot)
  connect(swiHot.u1, max.y)
  connect(yCol, swiCoo.y)
  connect(swiCoo.u1, maxCoo.y)
  connect(swiCoo.u2, yFan)
  connect(zer.y, swiCoo.u3)
  connect(zer.y, swiHot.u3)
  connect(yFan, swiHot.u2)
end RoomMixingBox;


Example models to test the components

within Buildings.Examples.DualFanDualDuct.Controls;
package Examples "Example models to test the components"
    extends Modelica.Icons.ExamplesPackage;
end Examples;


Test model for preheat coil controller. Test model for the preheat coil controller.

within Buildings.Examples.DualFanDualDuct.Controls.Examples;
model PreHeatCoil "Test model for preheat coil controller"
extends Modelica.Icons.Example;
  Modelica.Blocks.Sources.Constant TSupSet(k=273.15 + 16)
    "Set point for supply air temperature"
  Modelica.Blocks.Sources.Constant TAirSup(k=273.15 + 15)
    "Supply air temperature"
  Modelica.Blocks.Sources.Trapezoid TMix(
    amplitude=15,
    rising=900,
    width=900,
    falling=900,
    period=3600,
    offset=273.15 + 5) "Mixed air temperature"
  Buildings.Examples.DualFanDualDuct.Controls.PreHeatCoil preHeatCoil
equation

  connect(TMix.y, preHeatCoil.TMix)
  connect(preHeatCoil.TSupSetHea, TSupSet.y)
  connect(preHeatCoil.TAirSup, TAirSup.y)
end PreHeatCoil;


Test model for room mixing box.

within Buildings.Examples.DualFanDualDuct.Controls.Examples;
model RoomMixingBox "Test model for room mixing box"
extends Modelica.Icons.Example;
  Buildings.Examples.DualFanDualDuct.Controls.RoomMixingBox conMix(m_flow_min=1)
    "Controller for mixing box"
  Modelica.Blocks.Sources.Constant TH(k=273.15 + 20)
  Modelica.Blocks.Sources.Constant TC(k=273.15 + 26)
  Modelica.Blocks.Sources.Trapezoid TRoo(
    amplitude=15,
    rising=900,
    width=900,
    falling=900,
    period=3600,
    offset=273.15 + 15) "Room temperature"
  Modelica.Blocks.Sources.Trapezoid m_flow(
    rising=900,
    width=900,
    falling=900,
    period=3600,
    amplitude=2,
    offset=0,
    startTime=3600) "Mass flow rate"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant yFan(k=true)
    "Fan control signal"
equation

  connect(TH.y, conMix.TRooSetHea)
  connect(TC.y, conMix.TRooSetCoo)
  connect(TRoo.y, conMix.TRoo)
  connect(m_flow.y, conMix.mAir_flow)
  connect(yFan.y, conMix.yFan)
end RoomMixingBox;


within Buildings.Examples.DualFanDualDuct;
package ThermalZones "Package with models for the thermal zones"
extends Modelica.Icons.VariantsPackage;
end ThermalZones;


Supply branch of a dual duct system

within Buildings.Examples.DualFanDualDuct.ThermalZones;
model SupplyBranch "Supply branch of a dual duct system"
  replaceable package MediumA = Modelica.Media.Interfaces.PartialMedium
    "Medium model for air"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHot(redeclare package Medium =
        MediumA) "Connector for hot deck"
  Modelica.Fluid.Interfaces.FluidPort_a port_aCol(redeclare package Medium =
        MediumA) "Connector for cold deck"
  Modelica.Fluid.Interfaces.FluidPort_a port_b(redeclare package Medium =
        MediumA)
    "Fluid connector b (positive design flow direction is from port_a1 to port_b1)"
  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 Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Mass flow rate cold air deck";
  parameter Modelica.Units.SI.MassFlowRate mAirHot_flow_nominal=0.3*
      m_flow_nominal "Mass flow rate hot air deck";
  parameter Modelica.Units.SI.MassFlowRate mAirCol_flow_nominal=m_flow_nominal
    "Mass flow rate cold air deck";

  parameter Modelica.Units.SI.Volume VRoo "Room volume";
  Controls.RoomMixingBox con(m_flow_min=VRoo*3*1.2/3600)
    "Room temperature controller"
  VAVReheat.BaseClasses.Controls.ControlBus controlBus
  Buildings.Fluid.Actuators.Dampers.Exponential vavHot(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAirHot_flow_nominal,
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    y_start=0,
    dpDamper_nominal=0.27,
    dpFixed_nominal=40 - 0.27) "VAV damper for hot deck"
  Buildings.Fluid.Actuators.Dampers.Exponential vavCol(
    redeclare package Medium = MediumA,
    m_flow_nominal=mAirCol_flow_nominal,
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    y_start=0,
    dpDamper_nominal=0.27,
    dpFixed_nominal=40 - 0.27) "VAV damper for cold deck"

  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(redeclare package Medium =
        MediumA) "Sensor for mass flow rate"
  Modelica.Blocks.Math.Gain fraMasFlo(k=1/m_flow_nominal)
    "Fraction of mass flow rate, relative to nominal flow"
  Modelica.Blocks.Math.Gain ACH(k=1/VRoo/1.2*3600) "Air change per hour"
  Modelica.Blocks.Interfaces.RealInput TRoo "Measured room temperature"
  Buildings.Fluid.FixedResistances.Junction mix(
    redeclare package Medium = MediumA,
    m_flow_nominal={mAirCol_flow_nominal,mAirHot_flow_nominal,
        mAirCol_flow_nominal + mAirHot_flow_nominal},
    from_dp=from_dp,
    linearized=linearizeFlowResistance,
    dp_nominal=20*{0,0,0},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Mixer for hot and cold air deck"

  Buildings.Fluid.Sensors.RelativePressure senRelPreHot(redeclare package Medium =
        MediumA) "Relative pressure hot deck (compared to room pressure)"
  Buildings.Fluid.Sensors.RelativePressure senRelPreCol(redeclare package Medium =
        MediumA) "Relative pressure cold deck (compared to room pressure)"
  Modelica.Blocks.Interfaces.RealOutput p_relCol "Pressure signal of cold deck"
  Modelica.Blocks.Interfaces.RealOutput p_relHot "Pressure signal of hot deck"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup(redeclare package Medium = MediumA,
      m_flow_nominal=m_flow_nominal) "Supply air temperature"
  Buildings.Controls.OBC.CDL.Interfaces.BooleanInput yFan
    "Fan operation, true if fan is running"
equation
  connect(fraMasFlo.u, senMasFlo.m_flow)
  connect(ACH.u, senMasFlo.m_flow)
  connect(con.TRoo, TRoo)
  connect(vavHot.port_a, port_aHot)
  connect(vavHot.port_b, mix.port_2)
  connect(mix.port_1, vavCol.port_b)
  connect(mix.port_3, senMasFlo.port_a)
  connect(senMasFlo.m_flow, con.mAir_flow)
  connect(con.yHot, vavHot.y)
  connect(con.yCol, vavCol.y)
  connect(senRelPreHot.port_a, port_aHot)
  connect(senRelPreCol.port_a, port_aCol)
  connect(vavCol.port_a, port_aCol)
  connect(senRelPreHot.port_b, mix.port_3)
  connect(senRelPreCol.port_b, mix.port_3)
  connect(senRelPreCol.p_rel, p_relCol)
  connect(senRelPreHot.p_rel, p_relHot)
  connect(con.TRooSetHea, controlBus.TRooSetHea)
  connect(con.TRooSetCoo, controlBus.TRooSetCoo)
  connect(senMasFlo.port_b, TSup.port_a)
  connect(TSup.port_b, port_b)
  connect(con.yFan, yFan)
end SupplyBranch;


within Buildings.Examples;
package HydronicHeating "Hydronic heating system with storage, two rooms and thermostatic radiator valves"
  extends Modelica.Icons.ExamplesPackage;
end HydronicHeating;


within Buildings.Examples.HydronicHeating;
model TwoRoomsWithStorage
  "Model of a hydronic heating system with energy storage"
  extends Modelica.Icons.Example;
 replaceable package MediumA = Buildings.Media.Air(T_default=293.15)
    "Medium model for air";
 replaceable package MediumW = Buildings.Media.Water "Medium model";
 parameter Integer nRoo = 2 "Number of rooms";
  parameter Modelica.Units.SI.Volume VRoo=4*6*3 "Volume of one room";
  parameter Modelica.Units.SI.Power Q_flow_nominal=2200
    "Nominal power of heating plant";
 // Due to the night setback, in which the radiator do not provide heat input into the room,
 // we scale the design power of the radiator loop
 parameter Real scaFacRad = 1.5
    "Scaling factor to scale the power (and mass flow rate) of the radiator loop";
  parameter Modelica.Units.SI.Temperature TSup_nominal=273.15 + 50 + 5
    "Nominal supply temperature for radiators";
  parameter Modelica.Units.SI.Temperature TRet_nominal=273.15 + 40 + 5
    "Nominal return temperature for radiators";
  parameter Modelica.Units.SI.Temperature dTRad_nominal=TSup_nominal -
      TRet_nominal "Nominal temperature difference for radiator loop";
  parameter Modelica.Units.SI.Temperature dTBoi_nominal=20
    "Nominal temperature difference for boiler loop";
  parameter Modelica.Units.SI.MassFlowRate mRad_flow_nominal=scaFacRad*
      Q_flow_nominal/dTRad_nominal/4200
    "Nominal mass flow rate of radiator loop";
  parameter Modelica.Units.SI.MassFlowRate mBoi_flow_nominal=scaFacRad*
      Q_flow_nominal/dTBoi_nominal/4200 "Nominal mass flow rate of boiler loop";
  parameter Modelica.Units.SI.PressureDifference dpPip_nominal=10000
    "Pressure difference of pipe (without valve)";
  parameter Modelica.Units.SI.PressureDifference dpVal_nominal=6000
    "Pressure difference of valve";
  parameter Modelica.Units.SI.PressureDifference dpRoo_nominal=6000
    "Pressure difference of flow leg that serves a room";
  parameter Modelica.Units.SI.PressureDifference dpThrWayVal_nominal=6000
    "Pressure difference of three-way valve";
  parameter Modelica.Units.SI.PressureDifference dp_nominal=dpPip_nominal +
      dpVal_nominal + dpRoo_nominal + dpThrWayVal_nominal
    "Pressure difference of loop";
  // Room model

  Buildings.Fluid.Movers.SpeedControlled_y pumBoi(
    redeclare package Medium = MediumW,
    per(pressure(V_flow=mBoi_flow_nominal/1000*{0.5,1}, dp=(3000 + 2000)*{2,1})),
    use_riseTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump for boiler circuit"

  Buildings.Fluid.Movers.Preconfigured.SpeedControlled_y pumRad(
    redeclare package Medium = MediumW,
    m_flow_nominal=mRad_flow_nominal,
    dp_nominal=dp_nominal,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Pump that serves the radiators"

  parameter HeatTransfer.Data.OpaqueConstructions.Insulation100Concrete200 matLayExt
    "Construction material for exterior walls"
  parameter HeatTransfer.Data.OpaqueConstructions.Brick120 matLayPar
    "Construction material for partition walls"
  parameter HeatTransfer.Data.OpaqueConstructions.Generic matLayFlo(
        material={
          HeatTransfer.Data.Solids.Concrete(x=0.2),
          HeatTransfer.Data.Solids.InsulationBoard(x=0.15),
          HeatTransfer.Data.Solids.Concrete(x=0.05)},
        final nLay=3) "Construction material for floor"
  parameter HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false) "Data record for the glazing system"
  ThermalZones.Detailed.MixedAir roo1(
    redeclare package Medium = MediumA,
    AFlo=6*4,
    hRoo=2.7,
    nConExt=0,
    nConExtWin=2,
    datConExtWin(
      layers={matLayExt, matLayExt},
      A={4*3, 6*3},
      glaSys={glaSys, glaSys},
      wWin={3, 2},
      each hWin=2,
      each fFra=0.1,
      til={Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall},
      azi={Buildings.Types.Azimuth.W, Buildings.Types.Azimuth.S}),
    nConPar=2,
    datConPar(
      layers={matLayFlo, matLayPar},
      A={6*4, 6*3/2},
      til={Buildings.Types.Tilt.Floor, Buildings.Types.Tilt.Wall},
      azi={Buildings.Types.Azimuth.N, Buildings.Types.Azimuth.N}),
    nConBou=0,
    nSurBou=1,
    surBou(
      each A=4*3,
      each absIR=0.9,
      each absSol=0.9,
      each til=Buildings.Types.Tilt.Wall),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    nPorts=3,
    linearizeRadiation=true,
    extConMod=Buildings.HeatTransfer.Types.ExteriorConvection.Fixed)
    "Room model"

  ThermalZones.Detailed.MixedAir roo2(
    redeclare package Medium = MediumA,
    AFlo=6*4,
    hRoo=2.7,
    nConExt=0,
    nConExtWin=2,
    datConExtWin(
      layers={matLayExt, matLayExt},
      A={4*3, 6*3},
      glaSys={glaSys, glaSys},
      wWin={2, 2},
      each hWin=2,
      each fFra=0.1,
      til={Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall},
      azi={Buildings.Types.Azimuth.E, Buildings.Types.Azimuth.S}),
    nConPar=2,
    datConPar(
      layers={matLayFlo, matLayPar},
      A={6*4, 6*3/2},
      til={Buildings.Types.Tilt.Floor, Buildings.Types.Tilt.Wall},
      azi={Buildings.Types.Azimuth.N, Buildings.Types.Azimuth.N}),
    nConBou=0,
    nSurBou=1,
    surBou(
      each A=4*3,
      each absIR=0.9,
      each absSol=0.9,
      each til=Buildings.Types.Tilt.Wall),
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    linearizeRadiation=true,
    nPorts=3,
    extConMod=Buildings.HeatTransfer.Types.ExteriorConvection.Fixed)
    "Room model"
  Buildings.Fluid.Boilers.BoilerPolynomial boi(
    a={0.9},
    effCur=Buildings.Fluid.Types.EfficiencyCurves.Constant,
    redeclare package Medium = MediumW,
    Q_flow_nominal=Q_flow_nominal,
    m_flow_nominal=mBoi_flow_nominal,
    fue=Buildings.Fluid.Data.Fuels.HeatingOilLowerHeatingValue(),
    dp_nominal=3000 + 2000,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_start=293.15) "Boiler"
  Buildings.HeatTransfer.Sources.FixedTemperature TAmb(T=288.15)
    "Ambient temperature in boiler room"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TRoo2
  Controls.OBC.CDL.Reals.PIDWithReset conPum(
    yMax=1,
    Td=60,
    yMin=0.05,
    k=0.5,
    Ti=15) "Controller for pump"
  Buildings.Fluid.Sensors.RelativePressure dpSen(redeclare package Medium =
        MediumW)
  Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage val2(
    redeclare package Medium = MediumW,
    dpValve_nominal(displayUnit="Pa") = dpVal_nominal,
    m_flow_nominal=mRad_flow_nominal/nRoo,
    dpFixed_nominal=dpRoo_nominal,
    from_dp=true,
    use_strokeTime=false) "Radiator valve"
  Controls.OBC.CDL.Reals.PID conRoo2(
    yMax=1,
    yMin=0,
    Ti=60,
    Td=60,
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    k=0.5) "Controller for room temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TRoo1
  Buildings.Fluid.Actuators.Valves.TwoWayEqualPercentage val1(
    redeclare package Medium = MediumW,
    dpValve_nominal(displayUnit="Pa") = dpVal_nominal,
    m_flow_nominal=mRad_flow_nominal/nRoo,
    dpFixed_nominal=dpRoo_nominal,
    from_dp=true,
    use_strokeTime=false) "Radiator valve"
  Controls.OBC.CDL.Reals.PID conRoo1(
    yMax=1,
    yMin=0,
    Ti=60,
    Td=60,
    controllerType=Modelica.Blocks.Types.SimpleController.P,
    k=0.5) "Controller for room temperature"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad1(
    redeclare package Medium = MediumW,
    Q_flow_nominal=scaFacRad*Q_flow_nominal/nRoo,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_a_nominal=323.15,
    T_b_nominal=313.15) "Radiator"
  Buildings.Fluid.HeatExchangers.Radiators.RadiatorEN442_2 rad2(
    redeclare package Medium = MediumW,
    Q_flow_nominal=scaFacRad*Q_flow_nominal/nRoo,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    T_a_nominal=323.15,
    T_b_nominal=313.15) "Radiator"
  Buildings.Fluid.Actuators.Valves.ThreeWayEqualPercentageLinear thrWayVal(
    redeclare package Medium = MediumW,
    dpValve_nominal=dpThrWayVal_nominal,
    l={0.01,0.01},
    tau=10,
    m_flow_nominal=mRad_flow_nominal,
    dpFixed_nominal={100,0},
    use_strokeTime=false,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState) "Three-way valve"
  Controls.OBC.CDL.Reals.PIDWithReset conVal(
    yMax=1,
    yMin=0,
    xi_start=1,
    Td=60,
    k=0.1,
    Ti=120) "Controller for pump"
  Buildings.Fluid.Storage.StratifiedEnhanced tan(
    m_flow_nominal=mRad_flow_nominal,
    dIns=0.3,
    redeclare package Medium = MediumW,
    hTan=2,
    nSeg=5,
    show_T=true,
    VTan=0.2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Storage tank"

  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor tanTemBot
    "Tank temperature"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor tanTemTop
    "Tank temperature"
  Buildings.Controls.OBC.CDL.Reals.GreaterThreshold greThr(t=TSup_nominal + 5)
    "Check for temperature at the bottom of the tank"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaPum "Signal converter for pump"
  Buildings.Controls.OBC.CDL.Reals.Greater lesThr
    "Check for temperature at the top of the tank"
  Buildings.Fluid.Sensors.TemperatureTwoPort temSup(
    redeclare package Medium = MediumW,
    m_flow_nominal=mRad_flow_nominal)
  Buildings.Fluid.Sensors.TemperatureTwoPort temRet(
    redeclare package Medium = MediumW,
    m_flow_nominal=mRad_flow_nominal)
  Buildings.Controls.SetPoints.SupplyReturnTemperatureReset heaCha(
    dTOutHeaBal=0,
    use_TRoo_in=true,
    TSup_nominal=TSup_nominal,
    TRet_nominal=TRet_nominal,
    TOut_nominal=258.15)
  Controls.SetPoints.OccupancySchedule occSch1(occupancy=3600*{7,8,10,11,11.5,
        15,19,21}) "Occupancy schedule"
  Buildings.Controls.OBC.CDL.Reals.Switch switch1
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant zer(k=0) "Outputs zero"
  Controls.SetPoints.OccupancySchedule occSch2(
      firstEntryOccupied=false, occupancy=3600*{7,10,12,22})
    "Occupancy schedule"
  Buildings.Controls.OBC.CDL.Reals.Switch switch2
  Controls.SetPoints.OccupancySchedule occSch "Occupancy schedule"
  Buildings.Controls.OBC.CDL.Reals.Switch swi "Switch to select set point"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooNig(k=273.15 + 16)
    "Room temperature set point at night"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooSet(k=273.15 + 21)
  Controls.OBC.CDL.Reals.MultiMax mulMax(nin=2)
    "Maximum radiator valve position"
  Controls.OBC.CDL.Reals.Hysteresis hysPum(
    uLow=0.01,
    uHigh=0.5) "Hysteresis for pump"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "File reader that reads weather data"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Bus with weather data"
  Buildings.Fluid.Sources.Outside out(
    redeclare package Medium = MediumA,
    use_C_in=false,
    nPorts=4) "Outside air conditions"
  Buildings.Fluid.FixedResistances.PressureDrop dpFac4(
    from_dp=false,
    redeclare package Medium = MediumA,
    m_flow_nominal=6*4*3*1.2*0.3/3600,
    dp_nominal=10) "Pressure drop at facade"
  HeatTransfer.Conduction.MultiLayer parWal(A=4*3, layers=matLayPar,
    stateAtSurface_a=true,
    stateAtSurface_b=true) "Partition wall between the two rooms"
  Buildings.Fluid.FixedResistances.PressureDrop dpFac1(
    from_dp=false,
    redeclare package Medium = MediumA,
    m_flow_nominal=6*4*3*1.2*0.3/3600,
    dp_nominal=10) "Pressure drop at facade"
  Buildings.Fluid.HeatExchangers.ConstantEffectiveness hex(
    redeclare package Medium1 = MediumA,
    redeclare package Medium2 = MediumA,
    m1_flow_nominal=2*VRoo*1.2*0.3/3600,
    m2_flow_nominal=2*VRoo*1.2*0.3/3600,
    dp1_nominal=100,
    dp2_nominal=100,
    eps=0.9) "Heat recovery"
  Buildings.Fluid.Movers.FlowControlled_m_flow fanSup(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false) "Supply air fan"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant m_flow_out(k=2*VRoo*1.2*0.37/3600)
    "Outside air mass flow rate"
  Buildings.Fluid.Movers.FlowControlled_m_flow fanRet(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState,
    nominalValuesDefineDefaultPressureCurve=true,
    use_riseTime=false) "Return air fan"
  Airflow.Multizone.Orifice lea1(redeclare package Medium = MediumA, A=0.01^2)
    "Leakage of facade of room"
  Airflow.Multizone.Orifice lea2(redeclare package Medium = MediumA, A=0.01^2)
    "Leakage of facade of room"
  Modelica.Blocks.MathBoolean.Or pumOnSig(nu=3) "Signal for pump being on"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToReaBoi
    "Signal converter for boiler"
  Modelica.Blocks.Math.MatrixGain gai1(K=[35; 70; 30])
    "Gain to convert from occupancy (per person) to radiant, convective and latent heat in [W/m2] "
  Modelica.Blocks.Math.MatrixGain gai2(K=[35; 70; 30])
    "Gain to convert from occupancy (per person) to radiant, convective and latent heat in [W/m2] "
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant dTThr(k=1) "Threshold to switch boiler off"
  Buildings.Controls.OBC.CDL.Reals.Subtract sub1
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TRooOff(k=273.15 - 5)
    "Low room temperature set point to switch heating off"
  Buildings.Controls.OBC.CDL.Reals.Switch swi1 "Switch to select set point"
  Modelica.Blocks.Logical.OnOffController onOff(bandwidth=2) "On/off switch"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TOutSwi(k(
      final unit="K",
      displayUnit="degC") = 289.15,
    y(final unit="K",
      displayUnit="degC"))
    "Outside air temperature to switch heating on or off"
  Buildings.Fluid.Sources.Boundary_pT bou(nPorts=1, redeclare package Medium = MediumW)
    "Fixed boundary condition, needed to provide a pressure in the system"
  Controls.OBC.CDL.Reals.MultiplyByParameter gain(k=1/dp_nominal)
    "Gain used to normalize pressure measurement signal"
  Buildings.Fluid.FixedResistances.Junction splVal(
    dp_nominal={dpPip_nominal,0,0},
    m_flow_nominal=mRad_flow_nominal*{1,-1,-1},
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flow splitter"
  Buildings.Fluid.FixedResistances.Junction splVal1(
    m_flow_nominal=mRad_flow_nominal*{1,-1,-1},
    redeclare package Medium = MediumW,
    dp_nominal={0,0,0},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flow splitter"
  Buildings.Fluid.FixedResistances.Junction splVal2(
    m_flow_nominal=mRad_flow_nominal*{1,-1,-1},
    redeclare package Medium = MediumW,
    dp_nominal={0,0,0},
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flow splitter"

  CoolingControl cooCon "Controller for cooling"
  Buildings.Fluid.Actuators.Dampers.Exponential damSupByp(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    use_strokeTime=false,
    dpDamper_nominal=0.27) "Supply air damper that bypasses the heat recovery"
  Buildings.Fluid.HeatExchangers.SensibleCooler_T coo(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    dp_nominal=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Coil for mechanical cooling"
  Modelica.Blocks.Logical.LessThreshold lesThrTOut(threshold=15 + 273.15)
    "Output true if outdoor air is below heating cut-off limit"
  Buildings.Controls.OBC.CDL.Logical.And and1
    "Logical test to enable pump and subsequently the boiler"

  block CoolingControl
    "Controller for the free cooling and the mechanical cooling"
     extends Modelica.Blocks.Icons.Block;

    parameter Modelica.Units.SI.Temperature TRooCoo=25 + 273.15
      "Set point for mechanical cooling";
    parameter Modelica.Units.SI.Temperature TRooFre=22 + 273.15
      "Maximum temperature above which free cooling is enabled";
    parameter Modelica.Units.SI.Temperature TOutFre=16 + 273.15
      "Outside temperature above which free cooling is allowed";
    parameter Modelica.Units.SI.TemperatureDifference dT=1
      "Dead-band for free cooling";
     parameter Real Kp(min=0) = 1 "Proportional band for mechanical cooling";

     Modelica.Blocks.Interfaces.RealInput TRoo(unit="K") "Room air temperature"
     Modelica.Blocks.Interfaces.RealInput TOut(unit="K")
      "Outside air temperature"
     Modelica.Blocks.Interfaces.RealOutput TSupCoo
      "Control signal for set point for leaving air temperature of cooling coil"
     Modelica.Blocks.Interfaces.RealOutput yF
      "Control signal for free cooling, 1 if free cooling should be provided"

     Modelica.Blocks.Interfaces.RealOutput yHex
      "Control signal for heat recovery damper"
  initial equation
     yF   = 0;
     yHex = 1;
  algorithm
     when TRoo > TRooFre and TOut > TOutFre and TOut < TRoo - dT then
       yF   := 1;
       yHex := 0;
     elsewhen  TOut < TOutFre-dT or TOut > TRoo then
       yF   := 0;
       yHex := 1;
     end when;
     TSupCoo :=273.15 + Buildings.Utilities.Math.Functions.smoothLimit(
                 x=30 - 20*Kp*(TRoo - TRooCoo),
                 l=10,
                 u=30,
                 deltaX=0.1);
  end CoolingControl;
  Buildings.Fluid.Actuators.Dampers.Exponential damHex(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    use_strokeTime=false,
    dpDamper_nominal=0.27) "Supply air damper that closes the heat recovery"
  Buildings.Fluid.Actuators.Dampers.Exponential damRetByp(
    redeclare package Medium = MediumA,
    m_flow_nominal=2*VRoo*1.2*0.37/3600,
    use_strokeTime=false,
    dpDamper_nominal=0.27) "Return air damper that bypasses the heat recovery"
  Modelica.StateGraph.InitialStep off(nIn=1, nOut=1)
                                      "Pump and furnace off"
  Modelica.StateGraph.TransitionWithSignal T1 "Transition to pump on"
  Modelica.StateGraph.StepWithSignal pumOn(nIn=1, nOut=1)
                                           "Pump on"
  Modelica.StateGraph.Transition T3(enableTimer=true, waitTime=10)
    "Transition to boiler on"
  Modelica.StateGraph.StepWithSignal boiOn(nIn=1, nOut=1)
                                           "Boiler on"
  Modelica.StateGraph.TransitionWithSignal T2
    "Transition that switches boiler off"
  Modelica.StateGraph.StepWithSignal pumOn2(nIn=1, nOut=1)
                                            "Pump on"
  Modelica.StateGraph.Transition T4(enableTimer=true, waitTime=10)
    "Transition to boiler on"
  inner Modelica.StateGraph.StateGraphRoot stateGraphRoot
    "Root of the state graph"
  Buildings.Controls.OBC.CDL.Conversions.BooleanToReal booToRea
    "Conversion from boolean to real signal"
  Controls.OBC.CDL.Reals.Sources.Constant           occ1(k=1/6/4)
    "Heat gain if occupied in room 1"
  Controls.OBC.CDL.Reals.Sources.Constant           occ2(k=1/6/4)
    "Heat gain if occupied in room 2"
  Controls.OBC.CDL.Reals.MovingAverage aveTOut(delta=24*3600)
    "Time averaged outdoor air temperature"
  Fluid.FixedResistances.Junction           splVal3(
    dp_nominal={0,0,0},
    m_flow_nominal=mBoi_flow_nominal*{-1,1,1},
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flow splitter"
  Fluid.FixedResistances.Junction           splVal4(
    dp_nominal={0,0,0},
    m_flow_nominal=mBoi_flow_nominal*{1,-1,-1},
    redeclare package Medium = MediumW,
    energyDynamics=Modelica.Fluid.Types.Dynamics.SteadyState)
    "Flow splitter"
equation
  connect(TAmb.port,boi. heatPort)
  connect(pumRad.port_b, dpSen.port_a)
  connect(dpSen.port_b, pumRad.port_a)
  connect(val1.port_b, rad1.port_a)
  connect(val2.port_b, rad2.port_a)
  connect(conRoo1.y, val1.y)
  connect(conRoo2.y, val2.y)
  connect(pumRad.port_a, thrWayVal.port_2)
  connect(boi.port_b,pumBoi. port_a)
  connect(tan.heaPorVol[1], tanTemTop.port)
  connect(tanTemBot.port, tan.heaPorVol[tan.nSeg])
  connect(temSup.T, conVal.u_m)
  connect(heaCha.TSup, conVal.u_s)
  connect(occSch1.occupied, switch1.u2)
  connect(zer.y, switch1.u3)
  connect(occSch2.occupied, switch2.u2)
  connect(zer.y, switch2.u3)
  connect(swi.y, conRoo1.u_s)
  connect(swi.y, conRoo2.u_s)
  connect(mulMax.y, hysPum.u)
  connect(conRoo1.y, mulMax.u[1])
  connect(conRoo2.y, mulMax.u[2])
  connect(conVal.y, thrWayVal.y)
  connect(booToReaPum.y, pumBoi.y)
  connect(rad1.heatPortCon, roo1.heaPorAir)
  connect(roo1.heaPorRad, rad1.heatPortRad)
  connect(roo1.heaPorAir, TRoo1.port)
  connect(weaBus, roo1.weaBus)
  connect(rad2.heatPortCon, roo2.heaPorAir)
  connect(rad2.heatPortRad, roo2.heaPorRad)
  connect(roo2.heaPorAir, TRoo2.port)
  connect(weaBus, roo2.weaBus)
  connect(roo1.surf_surBou[1], parWal.port_b)
  connect(parWal.port_a, roo2.surf_surBou[1])
  connect(roo1.ports[1], dpFac1.port_b)
  connect(dpFac1.port_a, hex.port_a2)
  connect(dpFac4.port_b, roo2.ports[1])
  connect(dpFac4.port_a, hex.port_a2)
  connect(fanSup.m_flow_in, m_flow_out.y)
  connect(fanRet.port_a, hex.port_b2)
  connect(out.ports[1], fanSup.port_a)
  connect(fanRet.port_b, out.ports[2])
  connect(m_flow_out.y, fanRet.m_flow_in)
  connect(lea1.port_b, roo1.ports[2])
  connect(lea1.port_a, out.ports[3])
  connect(lea2.port_b, roo2.ports[2])
  connect(lea2.port_a, out.ports[4])
  connect(swi.y, heaCha.TRoo_in)
  connect(pumRad.port_b, temSup.port_a)
  connect(booToReaPum.u, pumOnSig.y)
  connect(weaBus.TDryBul, heaCha.TOut)
  connect(weaBus, out.weaBus)
  connect(switch1.y, gai1.u[1])
  connect(gai1.y, roo1.qGai_flow)
  connect(switch2.y, gai2.u[1])
  connect(gai2.y, roo2.qGai_flow)
  connect(heaCha.TSup, lesThr.u1)
  connect(booToReaBoi.y, boi.y)
  connect(tan.heaPorTop, TAmb.port)
  connect(TAmb.port, tan.heaPorSid)
  connect(TAmb.port, tan.heaPorBot)
  connect(sub1.y, lesThr.u2)
  connect(tanTemTop.T, sub1.u1)
  connect(dTThr.y, sub1.u2)
  connect(tanTemBot.T, greThr.u)
  connect(TRooSet.y, swi1.u1)
  connect(swi1.u2, occSch.occupied)
  connect(TRooNig.y, swi1.u3)
  connect(TOutSwi.y, onOff.reference)
  connect(swi1.y, swi.u1)
  connect(onOff.y, swi.u2)
  connect(TRooOff.y, swi.u3)
  connect(weaBus, weaDat.weaBus)
  connect(conPum.y, pumRad.y)
  connect(TRoo1.T, conRoo1.u_m)
  connect(TRoo2.T, conRoo2.u_m)
  connect(bou.ports[1], boi.port_a)
  connect(gain.u, dpSen.p_rel)
  connect(gain.y, conPum.u_m)
  connect(temRet.port_b, splVal.port_1)
  connect(thrWayVal.port_3, splVal.port_3)
  connect(splVal1.port_3, val2.port_a)
  connect(splVal1.port_1, temSup.port_b)
  connect(splVal1.port_2, val1.port_a)
  connect(temRet.port_a, splVal2.port_1)
  connect(splVal2.port_3, rad2.port_b)
  connect(splVal2.port_2, rad1.port_b)
  connect(weaBus.TDryBul, cooCon.TOut)
  connect(TRoo1.T, cooCon.TRoo)
  connect(fanSup.port_b, damSupByp.port_a)
  connect(cooCon.yF, damSupByp.y)
  connect(hex.port_b1, coo.port_a)
  connect(damSupByp.port_b, coo.port_a)
  connect(coo.port_b, roo1.ports[3])

  connect(coo.port_b, roo2.ports[3])

  connect(lesThr.y, and1.u2)
  connect(lesThrTOut.y, and1.u1)
  connect(damHex.port_b, hex.port_a1)
  connect(damHex.port_a, fanSup.port_b)
  connect(hex.port_a2, damRetByp.port_a)
  connect(damRetByp.port_b, fanRet.port_a)
  connect(damHex.y, cooCon.yHex)
  connect(damRetByp.y, cooCon.yF)
  connect(cooCon.TSupCoo, coo.TSet)
  connect(and1.y, T1.condition)
  connect(greThr.y, T2.condition)
  connect(boiOn.active, booToReaBoi.u)
  connect(pumOn2.active, pumOnSig.u[1])
  connect(boiOn.active, pumOnSig.u[2])
  connect(pumOn.active, pumOnSig.u[3])
  connect(off.outPort[1], T1.inPort)
  connect(T1.outPort, pumOn.inPort[1])
  connect(pumOn.outPort[1], T3.inPort)
  connect(T3.outPort, boiOn.inPort[1])
  connect(boiOn.outPort[1], T2.inPort)
  connect(T2.outPort, pumOn2.inPort[1])
  connect(pumOn2.outPort[1], T4.inPort)
  connect(T4.outPort, off.inPort[1])
  connect(hysPum.y, conPum.trigger)
  connect(hysPum.y, booToRea.u)
  connect(booToRea.y, conPum.u_s)
  connect(conVal.trigger, hysPum.y)
  connect(occ1.y, switch1.u1)
  connect(occ2.y, switch2.u1)
  connect(onOff.u, aveTOut.y)
  connect(weaBus.TDryBul, aveTOut.u)
  connect(weaBus.TDryBul, lesThrTOut.u)
  connect(tan.port_b, splVal3.port_3)
  connect(splVal4.port_3, tan.port_a)
  connect(splVal4.port_1, pumBoi.port_b)
  connect(splVal4.port_2, thrWayVal.port_1)
  connect(splVal.port_2, splVal3.port_2)
  connect(splVal3.port_1, boi.port_a)
end TwoRoomsWithStorage;


within Buildings.Examples.ScalableBenchmarks;
package BuildingVAV "Scalable model for building with VAV system"
end BuildingVAV;


Schedule for cooling setpoint. This block defines room air cooling setpoints.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses;
model CoolSetpoint "Schedule for cooling setpoint"
  extends Modelica.Blocks.Sources.CombiTimeTable(
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    table=[
      0,       273.15+32.0;
      8*3600,  273.15+27.0;
      18*3600, 273.15+32.0;
      24*3600, 273.15+32.0],
    columns={2});
end CoolSetpoint;


Controller for fan on/off and to provide prescribed dP. This model outputs ON/OFF signal to control fan operation.
When the system is in mode like unoccupiedOff, safety, it outputs
false so that fan should be OFF and provide 0 pressure rise;
When the system is in mode like unoccupiedNightSetBack,occupied,unoccupiedWarmUp,
unoccupiedPreCool, it outputs true so that fan should be
ON and provide preRis pressure rise.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses;
block FanOnOffWithDP
  "Controller for fan on/off and to provide prescribed dP"
  import Buildings.Examples.VAVReheat.BaseClasses.Controls.OperationModes;
  parameter Modelica.Units.SI.PressureDifference preRis=850
    "Prescribed pressure difference";
  Modelica.Blocks.Interfaces.RealOutput y(unit="Pa")
    "Supply fan requested pressure rise, or zero if fan should be off"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.ControlBus controlBus
  Modelica.Blocks.Routing.Extractor extractor(
    nin=6,
    index(start=1, fixed=true)) "Extractor for control signal"
  Modelica.Blocks.Sources.Constant off(k=0) "Off signal"
  Modelica.Blocks.Sources.Constant on(k=preRis) "On signal"

equation
  connect(off.y, extractor.u[Integer(OperationModes.unoccupiedOff)])
  connect(off.y, extractor.u[Integer(OperationModes.safety)])
  connect(on.y, extractor.u[Integer(OperationModes.unoccupiedNightSetBack)])
  connect(on.y, extractor.u[Integer(OperationModes.occupied)])
  connect(on.y, extractor.u[Integer(OperationModes.unoccupiedWarmUp)])
  connect(on.y, extractor.u[Integer(OperationModes.unoccupiedPreCool)])
  connect(controlBus.controlMode, extractor.index)
  connect(extractor.y, y)
end FanOnOffWithDP;


Schedule for heating setpoint. This block defines room air heating setpoints.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses;
model HeatSetpoint "Schedule for heating setpoint"
  extends Modelica.Blocks.Sources.CombiTimeTable(
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    table=[
      0,       273.15+13.0;
      8*3600,  273.15+20.0;
      18*3600, 273.15+13.0;
      24*3600, 273.15+13.0],
    columns={2});
end HeatSetpoint;


Schedule for time varying internal loads. This block defines schedule of internal load.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses;
model IntLoad "Schedule for time varying internal loads"
  extends Modelica.Blocks.Sources.CombiTimeTable(
    smoothness=Modelica.Blocks.Types.Smoothness.ConstantSegments,
    extrapolation=Modelica.Blocks.Types.Extrapolation.Periodic,
    table=[
      0,       0.1;
      8*3600,  1.0;
      18*3600, 0.1;
      24*3600, 0.1],
    columns={2});
end IntLoad;


Base classes

within Buildings.Examples.ScalableBenchmarks.BuildingVAV;
package BaseClasses "Base classes"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Supply branch of a VAV system

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses;
model VAVBranch "Supply branch of a VAV system"
  replaceable package MediumA = Modelica.Media.Interfaces.PartialMedium
    "Medium model for air"
  replaceable package MediumW = Modelica.Media.Interfaces.PartialMedium
    "Medium model for water"

  parameter Modelica.Units.SI.PressureDifference dpFixed_nominal(displayUnit=
        "Pa") = 0
    "Pressure drop of duct and other resistances that are in series";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Mass flow rate of this thermal zone";
  parameter Modelica.Units.SI.Volume VRoo "Room volume";

  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRooHeaSet(
    final quantity="ThermodynamicTemperature",
    final unit = "K",
    displayUnit = "degC",
    min=0)
    "Setpoint temperature for room for heating"
  Buildings.Controls.OBC.CDL.Interfaces.RealInput TRooCooSet(
    final quantity="ThermodynamicTemperature",
    final unit = "K",
    displayUnit = "degC",
    min=0)
    "Setpoint temperature for room for cooling"

  Modelica.Blocks.Interfaces.RealInput TRoo(
    final quantity="ThermodynamicTemperature",
    final unit = "K",
    displayUnit = "degC",
    min=0)
    "Measured room temperature"

  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare package Medium = MediumA)
    "Fluid connector a1 (positive design flow direction is from port_a1 to port_b1)"
  Modelica.Fluid.Interfaces.FluidPort_a port_b(
    redeclare package Medium = MediumA)
    "Fluid connector b (positive design flow direction is from port_a1 to port_b1)"
  Modelica.Blocks.Interfaces.RealOutput yDam "Actual VAV damper position"

  Fluid.Actuators.Dampers.PressureIndependent vav(
    dpDamper_nominal(displayUnit="Pa") = 20,
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    dpFixed_nominal=dpFixed_nominal) "VAV box for room"
  Buildings.Fluid.HeatExchangers.DryCoilEffectivenessNTU terHea(
    redeclare package Medium1 = MediumA,
    redeclare package Medium2 = MediumW,
    m1_flow_nominal=m_flow_nominal,
    m2_flow_nominal=m_flow_nominal*1000*(50 - 17)/4200/10,
    Q_flow_nominal=m_flow_nominal*1006*(16.7 - 50),
    configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    dp1_nominal=0,
    from_dp2=true,
    dp2_nominal=0,
    T_a1_nominal=289.85,
    T_a2_nominal=355.35) "Heat exchanger of terminal box"
  Buildings.Fluid.Sources.Boundary_pT sinTer(
    redeclare package Medium = MediumW,
    p(displayUnit="Pa") = 3E5,
    nPorts=1) "Sink for terminal box "
  Buildings.Examples.VAVReheat.BaseClasses.Controls.RoomVAV con
    "Room temperature controller"
  Buildings.Fluid.Sensors.MassFlowRate senMasFlo(
    redeclare package Medium =  MediumA) "Sensor for mass flow rate"
  Modelica.Blocks.Math.Gain fraMasFlo(
    k=1/m_flow_nominal)
    "Fraction of mass flow rate, relative to nominal flow"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup(
    redeclare package Medium = MediumA,
    m_flow_nominal=m_flow_nominal,
    initType=Modelica.Blocks.Types.Init.InitialState) "Supply air temperature"
  Modelica.Blocks.Math.Gain ACH(k=1/VRoo/1.2*3600) "Air change per hour"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear valHea(
    redeclare package Medium = MediumW,
    m_flow_nominal=m_flow_nominal*1000*15/4200/10,
    CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    from_dp=true,
    dpFixed_nominal=6000,
    dpValve_nominal=6000) "Valve at reaheat coil"
  Buildings.Fluid.Sources.Boundary_pT souTer(
    redeclare package Medium = MediumW,
    p(displayUnit="Pa") = 3E5 + 12000,
    nPorts=1,
    T=323.15) "Source for terminal box "
equation
   connect(fraMasFlo.u, senMasFlo.m_flow)
   connect(con.yDam, vav.y)
   connect(terHea.port_b1, TSup.port_a)
   connect(TSup.port_b, vav.port_a)
   connect(vav.port_b, senMasFlo.port_a)
   connect(ACH.u, senMasFlo.m_flow)
   connect(con.yVal, valHea.y)
   connect(souTer.ports[1], terHea.port_a2)
   connect(terHea.port_b2, valHea.port_a)
   connect(valHea.port_b, sinTer.ports[1])
   connect(port_a, terHea.port_a1)
   connect(senMasFlo.port_b, port_b)
   connect(con.TRoo, TRoo)

  connect(con.TRooHeaSet, TRooHeaSet)
  connect(TRooCooSet, con.TRooCooSet)
  connect(vav.y_actual, yDam)
end VAVBranch;


within Buildings.Examples.ScalableBenchmarks.BuildingVAV.Examples;
model OneFloor_OneZone "Closed-loop model with 1 zone in 1 floor"
  extends Modelica.Icons.Example;

  replaceable package MediumA = Buildings.Media.Air(T_default=293.15);
  package MediumW = Buildings.Media.Water "Medium model for water";
  parameter Integer nZon(min=1) = 1  "Number of zones per floor"
  parameter Integer nFlo(min=1) = 1  "Number of floors"
  parameter Modelica.Units.SI.PressureDifference dP_pre=850
    "Prescribed pressure difference";
  parameter Modelica.Units.SI.Volume VRoo[nZon,nFlo]={{6*8*2.7 for j in 1:nFlo}
      for i in 1:nZon} "Room volume";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal_each[nZon,nFlo]=
    7*conv*VRoo[:,:]
    "Nominal flow rate to each zone";
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=nZon*(7*conv)*6*8*2.7
    "Nominal system flow rate";
  constant Real conv=1.2/3600
    "Conversion factor for nominal mass flow rate";

  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.VAVBranch vavTer[nZon,nFlo](
    redeclare each package MediumA = MediumA,
    redeclare each package MediumW = MediumW,
    m_flow_nominal={{m_flow_nominal_each[i, j] for j in 1:nFlo} for i in 1:nZon},
    VRoo={{VRoo[i, j] for j in 1:nFlo} for i in 1:nZon},
    dpFixed_nominal={{220 + 20 for j in 1:nFlo} for i in 1:nZon})
    "Supply branch of VAV system"

  Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.MultiZone buiZon(
    nZon=nZon,
    nFlo=nFlo) "Multizone model with scalable number of zones"
  Buildings.Fluid.Movers.FlowControlled_dp fan[nFlo](
    redeclare each package Medium = MediumA,
    each constantHead=850,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    each m_flow_nominal=0.1,
    each inputType=Buildings.Fluid.Types.InputType.Continuous,
    each nominalValuesDefineDefaultPressureCurve=true)
      "Supply air fan"
  Buildings.Fluid.HeatExchangers.DryCoilEffectivenessNTU hex[nFlo](
    redeclare each package Medium1 = MediumA,
    redeclare each package Medium2 = MediumW,
    each m1_flow_nominal=m_flow_nominal,
    each allowFlowReversal2=false,
    each m2_flow_nominal=m_flow_nominal*1000*(10 - (-20))/4200/10,
    each configuration=Buildings.Fluid.Types.HeatExchangerConfiguration.CounterFlow,
    each Q_flow_nominal=m_flow_nominal*1006*(8.5 - 16.7),
    each dp1_nominal=0,
    each dp2_nominal=0,
    each T_a1_nominal=281.65,
    each T_a2_nominal=323.15) "Heating coil"
  Fluid.HeatExchangers.WetCoilEffectivenessNTU cooCoi[nFlo](
    redeclare each package Medium1 = MediumW,
    redeclare each package Medium2 = MediumA,
    each UA_nominal=m_flow_nominal*1000*15/
        Buildings.Fluid.HeatExchangers.BaseClasses.lmtd(
        T_a1=26.2,
        T_b1=12.8,
        T_a2=6,
        T_b2=16),
    each m1_flow_nominal=m_flow_nominal*1000*15/4200/10,
    each m2_flow_nominal=m_flow_nominal,
    each dp2_nominal=0,
    each dp1_nominal=0,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
      "Cooling coil"
  Buildings.Fluid.FixedResistances.PressureDrop fil[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal,
    each dp_nominal=200 + 200 + 100,
    each from_dp=false,
    each linearized=false) "Filter"
  Buildings.Fluid.Sources.Boundary_pT sinHea[nFlo](
    redeclare each package Medium = MediumW,
    each p=300000,
    each T=318.15,
    each nPorts=1) "Sink for heating coil"
  Buildings.Fluid.Sources.Boundary_pT souHea[nFlo](
    redeclare each package Medium = MediumW,
    each p(displayUnit="Pa") = 300000 + 12000,
    each T=318.15,
    each nPorts=1) "Source for heating coil"
  Buildings.Fluid.Sources.Boundary_pT sinCoo[nFlo](
    redeclare each package Medium = MediumW,
    each p=300000,
    each T=285.15,
    each nPorts=1) "Sink for cooling coil"
  Buildings.Fluid.Sources.Boundary_pT souCoo[nFlo](
    redeclare each package Medium = MediumW,
    each p=3E5 + 12000,
    each T=279.15,
    each nPorts=1) "Source for cooling coil"
  Buildings.Fluid.Sources.Outside amb[nFlo](
    redeclare each package Medium = MediumA,
    each nPorts=2) "Ambient conditions"
  Buildings.Fluid.Actuators.Dampers.MixingBox eco[nFlo](
    redeclare each package Medium = MediumA,
    each mOut_flow_nominal=m_flow_nominal,
    each mRec_flow_nominal=m_flow_nominal,
    each mExh_flow_nominal=m_flow_nominal,
    each dpDamExh_nominal=0.27,
    each dpDamOut_nominal=0.27,
    each dpDamRec_nominal=0.27,
    each dpFixExh_nominal=10,
    each dpFixOut_nominal=10,
    each dpFixRec_nominal=10) "Economizer"
  Buildings.Fluid.Sensors.TemperatureTwoPort TMix[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal) "Mixed air temperature sensor"
  Buildings.Fluid.Sensors.VolumeFlowRate senSupFlo[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal)  "Sensor for supply fan flow rate"
  Buildings.Fluid.Sensors.TemperatureTwoPort TRet[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal) "Return air temperature sensor"
  Buildings.Fluid.Sensors.VolumeFlowRate senRetFlo[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal)  "Sensor for return fan flow rate"
  Buildings.Fluid.Movers.Preconfigured.SpeedControlled_y fanRet[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal,
    each dp_nominal=1.5*110,
    each tau=60,
    each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)
      "Return air fan"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear valHea[nFlo](
    redeclare each package Medium = MediumW,
    each CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    each dpValve_nominal=6000,
    each m_flow_nominal=m_flow_nominal*1000*40/4200/10,
    each from_dp=true,
    each dpFixed_nominal=6000) "Heating coil valve"
  Buildings.Fluid.Actuators.Valves.TwoWayLinear  valCoo[nFlo](
    redeclare each package Medium = MediumW,
    each CvData=Buildings.Fluid.Types.CvTypes.OpPoint,
    each m_flow_nominal=m_flow_nominal*1000*15/4200/10,
    each dpValve_nominal=6000,
    each from_dp=true,
    each dpFixed_nominal=6000) "Cooling coil valve"
  Buildings.Fluid.Sensors.VolumeFlowRate VOut1[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal) "Outside air volume flow rate"
  Buildings.Fluid.Sensors.TemperatureTwoPort TCoiHeaOut[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal) "Heating coil outlet temperature"
  Buildings.Fluid.Sensors.TemperatureTwoPort TSup[nFlo](
    redeclare each package Medium = MediumA,
    each m_flow_nominal=m_flow_nominal) "Supply air temperature sensor"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.ModeSelector modeSelector[nFlo]
    "Finite State Machine for the operational modes"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.Economizer conEco[nFlo](
    each have_reset=true,
    each VOut_flow_min=0.3*m_flow_nominal/1.2)
    "Controller for economizer"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather Data Bus"
  Modelica.Blocks.Routing.RealPassThrough TOut(
    y(final quantity="ThermodynamicTemperature",
      final unit="K",
      displayUnit="degC",
      min=0)) "Outdoor temperature"
  Buildings.Utilities.Math.Average ave[nFlo](each nin=nZon)
    "Compute average of room temperatures"
  Buildings.Utilities.Math.Min min1[nFlo](each nin=nZon)
    "Computes lowest room temperature"
  Buildings.Examples.VAVReheat.BaseClasses.Controls.FanVFD conFanRet[nFlo](
    each xSet_nominal(final unit="m3/s") = m_flow_nominal/1.2,
    each r_N_min=0.2) "Controller for fan"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.ControlBus controlBus[nFlo]
    "Control bus for each floor"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.HeatSetpoint
    TSetHea "Heating setpoint"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.CoolSetpoint
    TSetCoo1 "Cooling setpoint"
  Buildings.Controls.SetPoints.OccupancySchedule occSch(occupancy=3600*{8,18})
    "Occupancy schedule"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.FanOnOffWithDP
    fan_dP_On_Off[nFlo](each preRis=dP_pre)
    "controller outputs fan on or off"
  VAVReheat.BaseClasses.Controls.SupplyAirTemperature conTSup[nFlo](each k=0.01)
    "Supply air temperature controller"
  VAVReheat.BaseClasses.Controls.SupplyAirTemperatureSetpoint TAirSupSet[nFlo]
    "Supply air temperature set point"
equation
  for iFlo in 1:nFlo loop
    connect(eco[iFlo].port_Sup, TMix[iFlo].port_a)
    connect(TMix[iFlo].port_b, fil[iFlo].port_a)
    connect(hex[iFlo].port_b2, sinHea[iFlo].ports[1])
    connect(TRet[iFlo].T, conEco[iFlo].TRet)
    connect(VOut1[iFlo].V_flow, conEco[iFlo].VOut_flow)
    connect(conEco[iFlo].yOA, eco[iFlo].y)
    connect(weaBus, amb[iFlo].weaBus)
    connect(senRetFlo[iFlo].V_flow, conFanRet[iFlo].u_m)
    connect(conFanRet[iFlo].u, senSupFlo[iFlo].V_flow)
    connect(conFanRet[iFlo].y, fanRet[iFlo].y)
    connect(TCoiHeaOut[iFlo].port_b, cooCoi[iFlo].port_a2)
    connect(cooCoi[iFlo].port_b2, fan[iFlo].port_a)
    connect(cooCoi[iFlo].port_b1, sinCoo[iFlo].ports[1])
    connect(cooCoi[iFlo].port_a1, valCoo[iFlo].port_b)
    connect(controlBus[iFlo], conEco[iFlo].controlBus)
    connect(controlBus[iFlo], modeSelector[iFlo].cb)
    connect(controlBus[iFlo], fan_dP_On_Off[iFlo].controlBus)
    connect(min1[iFlo].y, controlBus[iFlo].TRooMin)
    connect(ave[iFlo].y, controlBus[iFlo].TRooAve)
    connect(TOut.y, controlBus[iFlo].TOut)
    connect(TSetHea.y[1], controlBus[iFlo].TRooSetHea)
    connect(TSetCoo1.y[1], controlBus[iFlo].TRooSetCoo)
    connect(occSch.tNexOcc, controlBus[iFlo].dTNexOcc)
    connect(occSch.occupied, controlBus[iFlo].occupied)
    connect(eco[iFlo].port_Exh, amb[iFlo].ports[1])
    connect(senRetFlo[iFlo].port_b, fanRet[iFlo].port_a)
    connect(fanRet[iFlo].port_b, TRet[iFlo].port_a)
    connect(TRet[iFlo].port_b, eco[iFlo].port_Ret)
    connect(hex[iFlo].port_a2, valHea[iFlo].port_b)
    connect(souHea[iFlo].ports[1], valHea[iFlo].port_a)
    connect(valCoo[iFlo].port_a, souCoo[iFlo].ports[1])
    connect(amb[iFlo].ports[2], VOut1[iFlo].port_a)
    connect(VOut1[iFlo].port_b, eco[iFlo].port_Out)
    connect(fil[iFlo].port_b, hex[iFlo].port_a1)
    connect(hex[iFlo].port_b1, TCoiHeaOut[iFlo].port_a)
    connect(fan[iFlo].port_b, TSup[iFlo].port_a)
    connect(TSup[iFlo].port_b, senSupFlo[iFlo].port_a)
    connect(fan_dP_On_Off[iFlo].y, fan[iFlo].dp_in)
  end for;

  for iFlo in 1:nFlo loop
    for iZon in 1:nZon loop
      connect(vavTer[iZon, iFlo].port_b, buiZon.portsIn[iZon, iFlo])
      connect(buiZon.portsOut[iZon, iFlo], senRetFlo[iFlo].port_a)
      connect(buiZon.TRooAir[iZon, iFlo], vavTer[iZon, iFlo].TRoo)
      connect(senSupFlo[iFlo].port_b, vavTer[iZon, iFlo].port_a)
      connect(buiZon.TRooAir[iZon, iFlo], ave[iFlo].u[iZon])
      connect(buiZon.TRooAir[iZon, iFlo], min1[iFlo].u[iZon])
      connect(vavTer[iZon, iFlo].TRooHeaSet, controlBus[iFlo].TRooSetHea)
      connect(vavTer[iZon, iFlo].TRooCooSet, controlBus[iFlo].TRooSetCoo)
    end for;
  end for;

  connect(weaDat.weaBus, weaBus)
  connect(weaBus.TDryBul, TOut.u)
  connect(weaBus, buiZon.weaBus)
  connect(modeSelector.yFan, conFanRet.uFan)
  connect(conTSup.yOA, conEco.uOATSup)
  connect(TSup.T, conTSup.TSup)
  connect(conTSup.yHea, valHea.y)
  connect(conTSup.yCoo, valCoo.y)
  connect(modeSelector.yFan, conTSup.uEna)
  connect(controlBus, TAirSupSet.controlBus)
  connect(TAirSupSet.TSet, conTSup.TSupSet)
  connect(modeSelector.yEco, conEco.uEna)
end OneFloor_OneZone;


Demonstrate model scalability

within Buildings.Examples.ScalableBenchmarks.BuildingVAV;
package Examples "Demonstrate model scalability"
extends Modelica.Icons.ExamplesPackage;
end Examples;


Closed-loop model with 2 zone in 2 floor. The model demonstrates the scalability of model

Buildings.Examples.ScalableBenchmarks.BuildingVAV.Examples.OneFloor_OneZone
by setting it to be a multizone model with 2 zones in 2 floor, i.e.
nFlo=2, nZon=2.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.Examples;
model TwoFloor_TwoZone "Closed-loop model with 2 zone in 2 floor"
  extends Buildings.Examples.ScalableBenchmarks.BuildingVAV.Examples.OneFloor_OneZone(
    nFlo=2,
    nZon=2);
end TwoFloor_TwoZone;


Multiple thermal zone models

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones;
model MultiZone "Multiple thermal zone models"

  package MediumA = Buildings.Media.Air "Medium model";
  parameter Integer nZon(min=1) = 1 "Number of zones per floor"
  parameter Integer nFlo(min=1) = 1 "Number of floors"
  parameter Real ampFactor[nZon]=
    if nZon<=5 then
        {abs(cos(i*3.1415926/(nZon))) for i in 1:nZon}
    else
        {abs(cos(i*3.1415926/5)) for i in 1:nZon}
    "IHG fluctuating amplitude factor";

  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b portsIn[nZon,nFlo](
    redeclare each package Medium = MediumA) "Fluid inlets"
  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b portsOut[nZon,nFlo](
    redeclare each package Medium = MediumA) "Fluid outlets"
  Modelica.Blocks.Interfaces.RealOutput TRooAir[nZon,nFlo](
     each final unit="K",
     each displayUnit="degC")
     "Room air temperatures"
  Modelica.Blocks.Interfaces.RealOutput EHea[nZon,nFlo](
    each final unit="J")
    "Cooling energy provided to the zone from the HVAC system"

  Modelica.Blocks.Interfaces.RealOutput ECoo[nZon,nFlo](
    each final unit="J")
    "Cooling energy provided to the zone from the HVAC system"

  Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.ThermalZone theZon[nZon,nFlo](
    redeclare each package MediumA = MediumA,
    gainFactor={{ampFactor[i] for j in 1:nFlo} for i in 1:nZon})
    "Thermal zone model"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus  "Weather data bus"

equation
  for iZon in 1:nZon-1 loop
    for iFlo in 1:nFlo-1 loop
      connect(theZon[iZon, iFlo].heaPorFlo, theZon[iZon,
          if iFlo == nFlo then 1 else iFlo+1].heaPorCei)
      connect(theZon[iZon, iFlo].heaPorWal1, theZon[if iZon == nZon then 1
          else iZon+1, iFlo].heaPorWal2)
    end for;
  end for;
  for iZon in 1:nZon loop
    for iFlo in 1:nFlo loop
      connect(weaBus, theZon[iZon, iFlo].weaBus)
      connect(portsIn[iZon, iFlo], theZon[iZon, iFlo].portsInOut[1])
      connect(portsOut[iZon, iFlo], theZon[iZon, iFlo].portsInOut[2])
    end for;
  end for;

  connect(theZon.TRooAir, TRooAir)
  connect(theZon.EHea, EHea)
  connect(theZon.ECoo, ECoo)
end MultiZone;


Scalable building envelope model

within Buildings.Examples.ScalableBenchmarks.BuildingVAV;
package ThermalZones "Scalable building envelope model"
end ThermalZones;


Thermal zone model

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones;
model ThermalZone "Thermal zone model"

  replaceable package MediumA = Modelica.Media.Interfaces.PartialMedium
    "Medium model";

  parameter Real gainFactor(start=1) "IHG fluctuating amplitude factor";
  parameter Real VInf_flow=(roo.AFlo*roo.hRoo)*0.5/3600 "Infiltration volume flow rate";

  final parameter Modelica.Units.SI.Angle S_=Buildings.Types.Azimuth.S
    "Azimuth for south walls";
  final parameter Modelica.Units.SI.Angle E_=Buildings.Types.Azimuth.E
    "Azimuth for east walls";
  final parameter Modelica.Units.SI.Angle W_=Buildings.Types.Azimuth.W
    "Azimuth for west walls";
  final parameter Modelica.Units.SI.Angle N_=Buildings.Types.Azimuth.N
    "Azimuth for north walls";
  final parameter Modelica.Units.SI.Angle C_=Buildings.Types.Tilt.Ceiling
    "Tilt for ceiling";
  final parameter Modelica.Units.SI.Angle F_=Buildings.Types.Tilt.Floor
    "Tilt for floor";
  final parameter Modelica.Units.SI.Angle Z_=Buildings.Types.Tilt.Wall
    "Tilt for wall";
  final parameter HeatTransfer.Data.Solids.Plywood matFur(x=0.15, nStaRef=5)
    "Material for furniture"
  final parameter HeatTransfer.Data.Solids.Concrete matCon(
    x=0.1,
    k=1.311,
    c=836,
    nStaRef=5) "Concrete"
  final parameter HeatTransfer.Data.Solids.Plywood matWoo(
    x=0.01,
    k=0.11,
    d=544,
    nStaRef=1) "Wood for exterior construction"
  final parameter HeatTransfer.Data.Solids.Generic matIns(
    x=0.087,
    k=0.049,
    c=836.8,
    d=265,
    nStaRef=5) "Steelframe construction with insulation"
  final parameter HeatTransfer.Data.Solids.GypsumBoard matGyp(
    x=0.0127,
    k=0.16,
    c=830,
    d=784,
    nStaRef=2) "Gypsum board"
  final parameter HeatTransfer.Data.Solids.GypsumBoard matGyp2(
    x=0.025,
    k=0.16,
    c=830,
    d=784,
    nStaRef=2) "Gypsum board"
  final parameter HeatTransfer.Data.OpaqueConstructions.Generic conExtWal(
    final nLay=3,
    material={matWoo,matIns,matGyp}) "Exterior construction"
  final parameter HeatTransfer.Data.OpaqueConstructions.Generic conIntWal(
    final nLay=1,
    material={matGyp2}) "Interior wall construction"
  final parameter HeatTransfer.Data.OpaqueConstructions.Generic conFlo(
    final nLay=1,
    material={matCon}) "Floor construction (opa_a is carpet)"
  final parameter HeatTransfer.Data.Solids.Plywood matCarTra(
    k=0.11,
    d=544,
    nStaRef=1,
    x=0.215/0.11) "Wood for floor"
  final parameter HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false) "Data record for the glazing system"

  Modelica.Blocks.Interfaces.RealOutput TRooAir(
    final unit="K")
    "Room air temperatures"
  Modelica.Blocks.Interfaces.RealOutput EHea(
    final unit="J")
    "Cooling energy provided to the zone from the HVAC system"

  Modelica.Blocks.Interfaces.RealOutput ECoo(
    final unit="J")
    "Cooling energy provided to the zone from the HVAC system"

  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b portsInOut[2](
    redeclare package Medium = MediumA) "Fluid inlets and outlets"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heaPorWal1
    "Heat port connected to common wall"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heaPorFlo
    "Heat port connected to floor"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b heaPorCei
    "Heat port connected to ceiling"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b heaPorWal2
    "Heat port connected to common wall"

  Buildings.ThermalZones.Detailed.MixedAir roo(
    redeclare package Medium = MediumA,
    hRoo=2.7,
    nPorts=4,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    AFlo=6*8,
    datConExtWin(
      layers={conExtWal},
      A={8*2.7},
      glaSys={glaSys},
      wWin={2*3},
      hWin={2},
      fFra={0.001},
      til={Z_},
      azi={S_}),
    datConBou(
      layers={conFlo, conIntWal},
      A={6*8, 6*2.7},
      til={F_, Z_}),
    surBou(
      A={6*8, 6*2.7},
      til={C_, Z_},
      absIR = {conFlo.absIR_a, conIntWal.absIR_a},
      absSol = {conFlo.absSol_a, conIntWal.absSol_a}),
    datConPar(
      layers={conIntWal},
      A={8*2.7/2},
      til={Buildings.Types.Tilt.Wall}),
    nConExt=0,
    nConPar=1,
    nSurBou=2,
    nConBou=2,
    nConExtWin=1)
    "Room model, adapted from BESTEST Case 600 and VAVReheat model (for constructions)"
  Modelica.Blocks.Sources.Constant qConGai_flow(k=579/48) "Convective heat gain"
  Modelica.Blocks.Sources.Constant qRadGai_flow(k=689/48) "Radiative heat gain"
  Modelica.Blocks.Sources.Constant qLatGai_flow(k=146.5/48) "Latent heat gain"
  Modelica.Blocks.Routing.Multiplex3 multiplex3_1 "Sum of heat gain"
  Modelica.Blocks.Sources.Constant uSha(k=0)
    "Control signal for the shading device"
  Buildings.BoundaryConditions.WeatherData.Bus weaBus
    "Weather data bus"
  Modelica.Blocks.Math.Product product1 "Scheduled radiative heat gain"
  Modelica.Blocks.Math.Gain gain(k=gainFactor) "Factorized radiative heat gain"
  Modelica.Blocks.Math.Product product2 "Scheduled convective heat gain"
  Modelica.Blocks.Math.Gain gain1(k=gainFactor)
    "Factorized convective heat gain"
  Modelica.Blocks.Math.Product product3 "Scheduled latent heat gain"
  Modelica.Blocks.Math.Gain gain2(k=gainFactor) "Factorized latent heat gain"
  Modelica.Blocks.Math.Add               powCal(k1=-1)
    "Power calculation, with cooling negative and heating positive"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor rooAirTem
    "Air temperature sensor"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.BaseClasses.IntLoad intLoad(
    table=[0,0.1;
           ((gainFactor - 0.5) + 8)*3600,1.0;
           ((gainFactor - 0.5) + 18)*3600,0.1;
           24*3600,0.1]) "Internal load schedule"
  Fluid.Sources.MassFlowSource_WeatherData
                                  souExf(
    redeclare package Medium = MediumA,
    use_m_flow_in=false,
    m_flow=-VInf_flow*1.2,
    nPorts=1) "Source model for air exfiltration"

  Fluid.Sources.MassFlowSource_WeatherData
                                  souInf2(
    redeclare package Medium = MediumA,
    use_m_flow_in=false,
    m_flow=VInf_flow*1.2,
    nPorts=1)               "Source model for air infiltration"
protected
  Fluid.Sensors.EnthalpyFlowRate senEntFloSupAir(
    redeclare package Medium = MediumA, m_flow_nominal=0.2)
    "Supply air sensible enthalpy flow rate"
  Fluid.Sensors.EnthalpyFlowRate senEntFloRetAir(
    redeclare package Medium = MediumA, m_flow_nominal=0.2)
    "Return air sensible enthalpy flow rate"
  Controls.OBC.CDL.Reals.Max PHea "Heating power"
  Controls.OBC.CDL.Reals.Min PCoo "Cooling power"
  Controls.OBC.CDL.Reals.Sources.Constant con0(k=0)
    "Outputs 0 to compute heating or cooling power"
  Modelica.Blocks.Continuous.Integrator intEHea(initType=Modelica.Blocks.Types.Init.InitialState)
    "Integrator to convert power to energy"
  Modelica.Blocks.Continuous.Integrator intECoo(initType=Modelica.Blocks.Types.Init.InitialState)
    "Integrator to convert power to energy"
equation
  connect(multiplex3_1.y, roo.qGai_flow)
  connect(roo.surf_conBou[1], heaPorFlo)
  connect(roo.surf_conBou[2], heaPorWal1)
  connect(roo.surf_surBou[1], heaPorCei)
  connect(roo.surf_surBou[1], heaPorWal2)
  connect(uSha.y, roo.uSha[1])
  connect(weaBus, roo.weaBus)
  connect(qLatGai_flow.y, product3.u1)
  connect(product3.y, gain2.u)
  connect(product2.y, gain1.u)
  connect(product1.y, gain.u)
  connect(gain1.y, multiplex3_1.u2[1])
  connect(qConGai_flow.y, product2.u1)
  connect(qRadGai_flow.y, product1.u1)
  connect(gain.y, multiplex3_1.u1[1])
  connect(gain2.y, multiplex3_1.u3[1])
  connect(intLoad.y[1], product1.u2)
  connect(product1.u2, product2.u2)
  connect(product1.u2, product3.u2)
  connect(rooAirTem.T, TRooAir)
  connect(roo.heaPorAir, rooAirTem.port)

  connect(portsInOut[1], senEntFloSupAir.port_a)
  connect(senEntFloSupAir.port_b, roo.ports[1])
  connect(senEntFloRetAir.H_flow, powCal.u1)
  connect(senEntFloSupAir.H_flow, powCal.u2)
  connect(intEHea.y, EHea)
  connect(ECoo, intECoo.y)
  connect(intECoo.u, PCoo.y)
  connect(PHea.y, intEHea.u)
  connect(con0.y, PHea.u2)
  connect(con0.y, PCoo.u1)
  connect(PHea.u1, powCal.y)
  connect(PCoo.u2, powCal.y)
  connect(senEntFloRetAir.port_b, portsInOut[2])
  connect(senEntFloRetAir.port_a, roo.ports[2])
  connect(souInf2.ports[1], roo.ports[3])
  connect(souExf.ports[1], roo.ports[4])
  connect(souInf2.weaBus, weaBus)
  connect(souExf.weaBus, weaBus)
end ThermalZone;


Validation of the multi-zone model. This model validates
Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.MultiZone by setting
number of floors and zones to nFlo=2, nZon=6 respectively.

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.Validation;
model MultiZone "Validation of the multi-zone model"
  extends Modelica.Icons.Example;

  parameter Integer nZon(min=1) = 6 "Number of zones per floor"
  parameter Integer nFlo(min=1) = 1 "Number of floors"

  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
    "Weather data"
  Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones.MultiZone multiZone(
    nZon=nZon,
    nFlo=nFlo) "Multizone model"

equation
  connect(weaDat.weaBus, multiZone.weaBus)
end MultiZone;


Collection of validation models

within Buildings.Examples.ScalableBenchmarks.BuildingVAV.ThermalZones;
package Validation "Collection of validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;