Multiple-zone VAV

within Buildings.Templates.AirHandlersFans;
model VAVMultiZone "Multiple-zone VAV"
/*
  HACK: In Dymola only (ticket SR00860858-01), bindings for the parameter record
  cannot be made final if propagation from a top-level record (whole building)
  is needed.
  Instead those parameter declarations are annoted with enable=false
  in the record class.
*/
  extends Buildings.Templates.AirHandlersFans.Interfaces.PartialAirHandler(
    nZon(final min=2),
    redeclare final Buildings.Templates.AirHandlersFans.Configuration.VAVMultiZone cfg(
      final nFanSup=if fanSupDra.typ <> Buildings.Templates.Components.Types.Fan.None then
        fanSupDra.nFan elseif fanSupBlo.typ <> Buildings.Templates.Components.Types.Fan.None
        then fanSupBlo.nFan else 0,
      final nFanRet=secOutRel.nFanRet,
      final nFanRel=secOutRel.nFanRel,
      final typCoiHeaPre=coiHeaPre.typ,
      final typCoiCoo=coiCoo.typ,
      final typCoiHeaReh=coiHeaReh.typ,
      final typValCoiHeaPre=coiHeaPre.typVal,
      final typValCoiCoo=coiCoo.typVal,
      final typValCoiHeaReh=coiHeaReh.typVal,
      final typDamOut=secOutRel.typDamOut,
      final typDamOutMin=secOutRel.typDamOutMin,
      final typDamRet=secOutRel.typDamRet,
      final typDamRel=secOutRel.typDamRel,
      final typSecOut=secOutRel.typSecOut,
      final typCtl=ctl.typ,
      final buiPreCon=ctl.buiPreCon,
      final stdVen=ctl.stdVen),
    redeclare Buildings.Templates.AirHandlersFans.Data.VAVMultiZone dat,
    final typ=Buildings.Templates.AirHandlersFans.Types.Configuration.SingleDuct,
    final have_porRel=secOutRel.typ <> Types.OutdoorReliefReturnSection.MixedAirNoRelief,
    final have_souChiWat=coiCoo.have_sou,
    final have_souHeaWat=coiHeaPre.have_sou or coiHeaReh.have_sou,
    final typFanSup=if
      fanSupDra.typ <> Buildings.Templates.Components.Types.Fan.None then
      fanSupDra.typ elseif fanSupBlo.typ <> Buildings.Templates.Components.Types.Fan.None
      then fanSupBlo.typ else Buildings.Templates.Components.Types.Fan.None,
    final typFanRel=secOutRel.typFanRel,
    final typFanRet=secOutRel.typFanRet,
    final nFanSup=if
      fanSupDra.typ <> Buildings.Templates.Components.Types.Fan.None then
      fanSupDra.nFan elseif fanSupBlo.typ <> Buildings.Templates.Components.Types.Fan.None
      then fanSupBlo.nFan else 0,
    final nFanRel=secOutRel.nFanRel,
    final nFanRet=secOutRel.nFanRet,
    final mChiWat_flow_nominal=if coiCoo.have_sou then dat.coiCoo.mWat_flow_nominal else 0,
    final mHeaWat_flow_nominal=(if coiHeaPre.have_sou then dat.coiHeaPre.mWat_flow_nominal else 0) +
      (if coiHeaReh.have_sou then dat.coiHeaReh.mWat_flow_nominal else 0),
    final QChiWat_flow_nominal=if coiCoo.have_sou then dat.coiCoo.Q_flow_nominal else 0,
    final QHeaWat_flow_nominal=(if coiHeaPre.have_sou then dat.coiHeaPre.Q_flow_nominal else 0) +
      (if coiHeaReh.have_sou then dat.coiHeaReh.Q_flow_nominal else 0));

  final parameter Boolean have_senPreBui=
    secOutRel.typSecRel==Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefDamper or
    secOutRel.typSecRel==Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefFan or
    secOutRel.typSecRel==Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReturnFan and
    secOutRel.typCtlFanRet==Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.BuildingPressure
    "Set to true if building static pressure sensor is used"

  /*
  RFE: Currently only the configuration with economizer is supported.
  Hence, no choices annotation, but still replaceable to access parameter
  dialog box of the component.
  */
  inner replaceable Buildings.Templates.AirHandlersFans.Components.OutdoorReliefReturnSection.MixedAirWithDamper
    secOutRel(
    redeclare final package MediumAir = MediumAir,
    final typCtlFanRet=ctl.typCtlFanRet,
    final typCtlEco=ctl.typCtlEco,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversalAir,
    dat(
      final mOutMin_flow_nominal=dat.mOutMin_flow_nominal,
      final damOut=dat.damOut,
      final damOutMin=dat.damOutMin,
      final damRel=dat.damRel,
      final damRet=dat.damRet,
      final fanRel=dat.fanRel,
      final fanRet=dat.fanRet))
     "Outdoor/relief/return air section"

  Buildings.Templates.Components.Sensors.Temperature TAirMix(
    redeclare final package Medium = MediumAir,
    final have_sen=ctl.use_TMix,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Averaging,
    final m_flow_nominal=mAirSup_flow_nominal,
    final allowFlowReversal=allowFlowReversalAir)
    "Mixed air temperature sensor"

  inner replaceable Buildings.Templates.Components.Fans.None fanSupBlo
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
      redeclare final package Medium = MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversalAir,
      final dat=dat.fanSup,
      final have_senFlo=ctl.typCtlFanRet==
        Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured)
    "Supply fan - Blow through"

  Buildings.Templates.Components.Sensors.Temperature TAirCoiHeaLvg(
    redeclare final package Medium = MediumAir,
    final have_sen=coiHeaPre.typ <> Buildings.Templates.Components.Types.Coil.None
         and coiCoo.typ <> Buildings.Templates.Components.Types.Coil.None,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Averaging,
    final m_flow_nominal=mAirSup_flow_nominal,
    final allowFlowReversal=allowFlowReversalAir)
    "Heating coil leaving air temperature sensor"

  Buildings.Templates.Components.Sensors.Temperature TAirCoiCooLvg(
    redeclare final package Medium = MediumAir,
    final have_sen=coiCoo.typ <> Buildings.Templates.Components.Types.Coil.None
         and coiHeaReh.typ <> Buildings.Templates.Components.Types.Coil.None,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Averaging,
    final m_flow_nominal=mAirSup_flow_nominal,
    final allowFlowReversal=allowFlowReversalAir)
    "Cooling coil leaving air temperature sensor"

  inner replaceable Buildings.Templates.Components.Fans.SingleVariable fanSupDra
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
      redeclare final package Medium = MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversalAir,
      final dat=dat.fanSup,
      final have_senFlo=ctl.typCtlFanRet==
        Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured)
    "Supply fan - Draw through"

  Buildings.Templates.Components.Sensors.Temperature TAirSup(
    redeclare final package Medium = MediumAir,
    final have_sen=true,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Standard,
    final m_flow_nominal=mAirSup_flow_nominal,
    final allowFlowReversal=allowFlowReversalAir)
    "Supply air temperature sensor"

  Buildings.Templates.Components.Sensors.DifferentialPressure pBui_rel(
    redeclare final package Medium = MediumAir,
    final have_sen=have_senPreBui,
    final text_flip=true)
    "Building static pressure"

  Buildings.Fluid.Sources.Outside out(
    redeclare final package Medium=MediumAir,
    final nPorts=3)
    "Outdoor conditions"
  Buildings.Fluid.Sources.Boundary_pT bui(
    redeclare final package Medium = MediumAir,
    final use_p_in=have_senPreBui,
    final nPorts=1)
    "Building absolute pressure in representative space"

  Buildings.Templates.Components.Sensors.Temperature TAirRet(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversalAir,
    final have_sen=
      secOutRel.have_eco and
      (ctl.typCtlEco==Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialDryBulb or
       ctl.typCtlEco==Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedDryBulbWithDifferentialDryBulb),
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Standard,
    final m_flow_nominal=mAirRet_flow_nominal)
    "Return air temperature sensor"

  Buildings.Templates.Components.Sensors.SpecificEnthalpy hAirRet(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversalAir,
    final have_sen=
      secOutRel.have_eco and
      ctl.typCtlEco==Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb,
    final m_flow_nominal=mAirRet_flow_nominal)
    "Return air enthalpy sensor"

  Buildings.Templates.Components.Sensors.DifferentialPressure pAirSup_rel(
    redeclare final package Medium = MediumAir,
    final have_sen=true)
    "Duct static pressure sensor"

  inner replaceable Buildings.Templates.Components.Coils.WaterBasedHeating coiHeaPre(
    redeclare final package MediumHeaWat=MediumHeaWat,
    final typVal=Buildings.Templates.Components.Types.Valve.TwoWayModulating)
    constrainedby Buildings.Templates.Components.Interfaces.PartialCoil(
      final dat=dat.coiHeaPre,
      redeclare final package MediumAir=MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversalAir=allowFlowReversalAir,
      final allowFlowReversalLiq=allowFlowReversalLiq,
      final show_T=show_T)
    "Heating coil in preheat position"

  inner replaceable Buildings.Templates.Components.Coils.WaterBasedCooling coiCoo(
    redeclare final package MediumChiWat=MediumChiWat,
    final typVal=Buildings.Templates.Components.Types.Valve.TwoWayModulating)
    constrainedby Buildings.Templates.Components.Interfaces.PartialCoil(
      final dat=dat.coiCoo,
      redeclare final package MediumAir=MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversalAir=allowFlowReversalAir,
      final allowFlowReversalLiq=allowFlowReversalLiq,
      final show_T=show_T)
    "Cooling coil"
  inner replaceable Buildings.Templates.Components.Coils.None coiHeaReh
    constrainedby Buildings.Templates.Components.Interfaces.PartialCoil(
      final dat=dat.coiHeaReh,
      redeclare final package MediumAir=MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversalAir=allowFlowReversalAir,
      final allowFlowReversalLiq=allowFlowReversalLiq,
      final show_T=show_T)
    "Heating coil in reheat position"
  Buildings.Fluid.FixedResistances.Junction junHeaWatSup(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWat_flow_nominal*{1,-1,-1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_souHeaWat
    "HHW supply junction"
  Buildings.Fluid.FixedResistances.Junction junHeaWatRet(
    redeclare final package Medium = MediumHeaWat,
    final m_flow_nominal=mHeaWat_flow_nominal*{1,-1,1},
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    dp_nominal=fill(0, 3),
    final portFlowDirection_1=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_3=if allowFlowReversalLiq then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving) if have_souHeaWat
    "HHW return junction"
  inner replaceable Buildings.Templates.AirHandlersFans.Components.Controls.G36VAVMultiZone ctl
    constrainedby
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialControllerVAVMultizone(
      final dat=dat.ctl,
      final nZon=nZon,
      final typFanSup=typFanSup,
      final typFanRel=typFanRel,
      final typFanRet=typFanRet,
      final nFanSup=nFanSup,
      final nFanRel=nFanRel,
      final nFanRet=nFanRet)
    "Control selections"

initial equation
  assert(typFanSup<>Buildings.Templates.Components.Types.Fan.None,
    "In "+ getInstanceName() + ": "+
    "The template is configured with no supply fan, which is not supported.");
  assert(not (fanSupBlo.typ<>Buildings.Templates.Components.Types.Fan.None and
    fanSupDra.typ<>Buildings.Templates.Components.Types.Fan.None),
    "In "+ getInstanceName() + ": "+
    "The template is configured with both a blow-through fan and a draw-through fan, which is not supported.");
equation
  /* Control point connection - start */
  connect(TAirMix.y, bus.TAirMix);
  connect(TAirCoiHeaLvg.y, bus.TAirCoiHeaLvg);
  connect(TAirSup.y, bus.TAirSup);
  connect(pAirSup_rel.y, bus.pAirSup_rel);
  connect(hAirRet.y, bus.hAirRet);
  connect(TAirRet.y, bus.TAirRet);
  connect(fanSupDra.bus, bus.fanSup);
  connect(fanSupBlo.bus, bus.fanSup);
  connect(coiHeaPre.bus, bus.coiHea);
  connect(coiCoo.bus, bus.coiCoo);
  connect(coiHeaReh.bus, bus.coiHea);
  connect(secOutRel.bus, bus);
  connect(bui.p_in, bus.pBui);
  connect(pBui_rel.y, bus.pBui_rel);
  /* Control point connection - stop */

  connect(port_aChiWat, coiCoo.port_aSou)
  connect(coiCoo.port_bSou, port_bChiWat)
  connect(busWea,coiCoo.busWea)
  connect(TAirMix.port_b, fanSupBlo.port_a)
  connect(coiHeaReh.port_b, fanSupDra.port_a)
  connect(busWea, out.weaBus)
  connect(pBui_rel.port_b, out.ports[1])
  connect(bui.ports[1], pBui_rel.port_a)

  connect(ctl.busTer, busTer)
  connect(ctl.bus, bus)
  connect(port_Ret, hAirRet.port_a)
  connect(hAirRet.port_b, TAirRet.port_a)
  connect(coiHeaPre.port_b, TAirCoiHeaLvg.port_a)
  connect(TAirCoiHeaLvg.port_b, coiCoo.port_a)
  connect(coiCoo.port_b, TAirCoiCooLvg.port_a)
  connect(TAirCoiCooLvg.port_b, coiHeaReh.port_a)
  connect(secOutRel.port_Sup, TAirMix.port_a)
  connect(secOutRel.port_bPre, out.ports[2])
  connect(port_Rel, secOutRel.port_Rel)
  connect(port_Out, secOutRel.port_Out)
  connect(TAirSup.port_b, port_Sup)
  connect(TAirSup.port_b, pAirSup_rel.port_a)
  connect(fanSupDra.port_b, TAirSup.port_a)
  connect(port_aHeaWat, junHeaWatSup.port_1)
  connect(port_bHeaWat, junHeaWatRet.port_2)
  connect(junHeaWatSup.port_3, coiHeaReh.port_aSou)
  connect(coiHeaReh.port_bSou, junHeaWatRet.port_3)
  connect(coiHeaPre.port_bSou, junHeaWatRet.port_1)
  connect(junHeaWatSup.port_2, coiHeaPre.port_aSou)
  connect(out.ports[3], pAirSup_rel.port_b)
  connect(secOutRel.port_Ret, TAirRet.port_b)
  connect(fanSupBlo.port_b, coiHeaPre.port_a)
end VAVMultiZone;


Package with component models

within Buildings.Templates.AirHandlersFans;
package Components "Package with component models"
  extends Modelica.Icons.VariantsPackage;
end Components;


Guideline 36 controller.

within Buildings.Templates.AirHandlersFans.Components.Controls;
block G36VAVMultiZone
  "Guideline 36 controller"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialControllerVAVMultizone(
      final typ=Buildings.Templates.AirHandlersFans.Types.Controller.G36VAVMultiZone);

  parameter String idZon[nZon]
    "Zone (or terminal unit) names"

  parameter String namGro[:]
    "Name of zone groups"

  parameter String namGroZon[nZon]
    "Name of group which each zone belongs to"

  final parameter Integer nGro(final min=1)=
    size(namGro, 1)
    "Number of zone groups"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ASHRAEClimateZone ashCliZon=
    datAll.ashCliZon
    "ASHRAE climate zone"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.Title24ClimateZone tit24CliZon=
    datAll.tit24CliZon
    "California Title 24 climate zone"

  final parameter Boolean isZonInGro[nGro, nZon]=
    {{namGro[i]==namGroZon[j]  for j in 1:nZon} for i in 1:nGro}
    "True if zone belongs to group"

  final parameter Integer isZonInGroInt[nGro, nZon]=
    {{if isZonInGro[i, j] then 1 else 0 for j in 1:nZon} for i in 1:nGro}
    "1 if zone belongs to group, 0 otherwise"

  final parameter Integer isZonInGroIntTra[nZon, nGro]=
    {{isZonInGroInt[i, j] for i in 1:size(isZonInGroInt, 1)} for j in 1:size(isZonInGroInt, 2)}
    "Transpose of isZonInGroInt: 1 if zone belongs to group, 0 otherwise"

  final parameter Integer nZonPerGro[nGro](each final min=1) = {
    sum(isZonInGroInt[i]) for i in 1:nGro}
    "Number of zones that each group contains"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil typCoiCoo=
    if coiCoo.typ==Buildings.Templates.Components.Types.Coil.WaterBasedCooling then
      Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
    elseif coiCoo.typ==Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage or
      coiCoo.typ==Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed then
      Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.DXCoil
    else Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.None
    "Type of cooling coil"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil typCoiHea=
    if coiHeaPre.typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating or
      coiHeaReh.typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating
      then Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased
    elseif coiHeaPre.typ==Buildings.Templates.Components.Types.Coil.ElectricHeating or
      coiHeaPre.typ==Buildings.Templates.Components.Types.Coil.ElectricHeating
      then Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.Electric
    else Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.None
    "Type of cooling coil"

  parameter Boolean have_perZonRehBox=false
    "Set to true if there are any VAV-reheat boxes on perimeter zones"

  /*
  *  Parameters for Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Controller
  */

  final parameter Modelica.Units.SI.VolumeFlowRate VOutUnc_flow_nominal=
    dat.VOutUnc_flow_nominal
    "Uncorrected design outdoor air flow rate, including diversity where applicable";
  final parameter Modelica.Units.SI.VolumeFlowRate VOutTot_flow_nominal=
    dat.VOutTot_flow_nominal
    "Design total outdoor air flow rate";
  final parameter Modelica.Units.SI.VolumeFlowRate VOutAbsMin_flow_nominal=
    dat.VOutAbsMin_flow_nominal
    "Design outdoor air flow rate when all zones with CO2 sensors or occupancy sensors are unpopulated";
  final parameter Modelica.Units.SI.VolumeFlowRate VOutMin_flow_nominal=
    dat.VOutMin_flow_nominal
    "Design minimum outdoor air flow rate when all zones are occupied at their design population, including diversity";

  final parameter Modelica.Units.SI.PressureDifference dpDamOutMinAbs=
    dat.dpDamOutMinAbs
    "Differential pressure across the minimum outdoor air damper that provides the absolute minimum outdoor airflow";
  final parameter Modelica.Units.SI.PressureDifference dpDamOutMin_nominal=
    dat.dpDamOutMin_nominal
    "Differential pressure across the minimum outdoor air damper that provides the design minimum outdoor airflow";

  final parameter Modelica.Units.SI.PressureDifference pAirSupSet_rel_max=
    dat.pAirSupSet_rel_max
    "Maximum supply duct static pressure setpoint";

  final parameter Modelica.Units.SI.PressureDifference pAirRetSet_rel_min=
    dat.pAirRetSet_rel_min
    "Return fan minimum discharge static pressure setpoint";

  final parameter Modelica.Units.SI.PressureDifference pAirRetSet_rel_max=
    dat.pAirRetSet_rel_max
    "Return fan maximum discharge static pressure setpoint";

  final parameter Real yFanSup_min=
    dat.yFanSup_min
    "Lowest allowed fan speed if fan is on";

  final parameter Modelica.Units.SI.Temperature TAirSupSet_min(
    displayUnit="degC")=dat.TAirSupSet_min
    "Lowest supply air temperature setpoint";

  final parameter Modelica.Units.SI.Temperature TAirSupSet_max(
    displayUnit="degC")=dat.TAirSupSet_max
    "Highest supply air temperature setpoint";

  final parameter Modelica.Units.SI.Temperature TOutRes_min(
    displayUnit="degC")=dat.TOutRes_min
    "Lowest value of the outdoor air temperature reset range";

  final parameter Modelica.Units.SI.Temperature TOutRes_max(
    displayUnit="degC")=dat.TOutRes_max
    "Highest value of the outdoor air temperature reset range";

  final parameter Real yFanRel_min=
    dat.yFanRel_min
    "Minimum relief fan speed";

  final parameter Real yFanRet_min=
    dat.yFanRet_min
    "Minimum return fan speed";

  final parameter Modelica.Units.SI.VolumeFlowRate dVFanRet_flow=
    dat.dVFanRet_flow
    "Airflow differential between supply and return fans to maintain building pressure at setpoint";

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.Controller ctl(
    final eneStd=stdEne,
    final venStd=stdVen,
    final ashCliZon=ashCliZon,
    final tit24CliZon=tit24CliZon,
    final have_frePro=have_frePro,
    final freSta=typFreSta,
    final minOADes=typSecOut,
    final buiPreCon=buiPreCon,
    final ecoHigLimCon=typCtlEco,
    final cooCoi=typCoiCoo,
    final heaCoi=typCoiHea,
    final have_perZonRehBox=have_perZonRehBox,
    final VUncDesOutAir_flow=VOutUnc_flow_nominal,
    final VDesTotOutAir_flow=VOutTot_flow_nominal,
    final VAbsOutAir_flow=VOutAbsMin_flow_nominal,
    final VDesOutAir_flow=VOutAbsMin_flow_nominal,
    final pMaxSet=pAirSupSet_rel_max,
    final supFanSpe_min=yFanSup_min,
    final retFanSpe_min=yFanRet_min,
    final TSupCoo_min=TAirSupSet_min,
    final TSupCoo_max=TAirSupSet_max,
    final TOut_min=TOutRes_min,
    final TOut_max=TOutRes_max,
    final have_CO2Sen=have_CO2Sen,
    final dpAbsMinOutDam=dpDamOutMinAbs,
    final dpDesMinOutDam=dpDamOutMin_nominal,
    final difFloSet=dVFanRet_flow,
    final p_rel_RetFan_min=pAirRetSet_rel_min,
    final p_rel_RetFan_max=pAirRetSet_rel_max)
    "AHU controller"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.ASHRAE62_1.SumZone
    aggZonVen_A621(
    final nZon=nZon,
    final nGro=nGro,
    final zonGroMat=isZonInGroInt,
    final zonGroMatTra=isZonInGroIntTra)
    if stdVen==Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Aggregate zone level ventilation signals - ASHRAE 62.1"

  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.OutdoorAirFlow.Title24.SumZone
    aggZonVen_T24(
    final nZon=nZon,
    final nGro=nGro,
    final zonGroMat=isZonInGroInt,
    final have_CO2Sen=have_CO2Sen)
    if stdVen==Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Aggregate zone level ventilation signals - California Title 24"

  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.ZoneStatusDuplicator repSigZon(
    final nZon=nZon,
    final nZonGro=nGro)
    "Replicate zone signals"

  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.GroupStatus staGro[nGro](
    final nBuiZon=fill(nZon, nGro),
    final nGroZon=nZonPerGro,
    final zonGroMsk=isZonInGro)
    "Evaluate zone group status"

  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.OperationMode opeModSel[nGro](
    final nZon=nZonPerGro)
    "Operation mode selection for each zone group"

  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator TAirSupSet(
    final nout=nZon)
    "Pass signal to terminal unit bus"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqZonTemRes(
    final nin=nZon,
    final k=fill(1, nZon))
    "Sum up signals"
  Buildings.Controls.OBC.CDL.Integers.MultiSum reqZonPreRes(
    final nin=nZon,
    final k=fill(1, nZon))
    "Sum up signals"

  Buildings.Controls.OBC.CDL.Logical.Sources.Constant u1FreSta(k=false)
    "RFE: Freezestat and freezestat reset are currently not modeled"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant u1SofSwiRes(k=false)
    "RFE: Freezestat and freezestat reset are currently not modeled"
  Buildings.Controls.OBC.CDL.Routing.BooleanScalarReplicator y1FanSup_actual(
    final nout=nZon)
    "Pass signal to terminal unit bus"
  Buildings.Controls.OBC.CDL.Routing.RealScalarReplicator TAirSup(
    final nout=nZon)
    "Pass signal to terminal unit bus"
  Buildings.Controls.OBC.CDL.Routing.IntegerVectorReplicator intVecRep(
    final nin=nGro,
    final nout=nZon)
    "Repeat group signal nZon times"
  Buildings.Controls.OBC.CDL.Integers.MultiSum asgOpeMod[nZon](
    each final nin=nGro,
    final k=isZonInGroIntTra)
    "Assign group operating mode to each zone belonging to group"
  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.ZoneGroupSystem ahuMod(
    final nGro=nGro)
    "Compute the AHU operating mode"
equation
  /* Control point connection - start */

  // Inputs from AHU bus
  connect(bus.pAirSup_rel, ctl.dpDuc);
  connect(bus.TOut, ctl.TOut);
  connect(bus.TAirSup, ctl.TAirSup);
  if typSecOut==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper then
    connect(bus.VOut_flow, ctl.VAirOut_flow);
  end if;
  if typSecOut==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow then
    connect(bus.VOutMin_flow, ctl.VAirOut_flow);
  end if;

  connect(bus.dpAirOutMin, ctl.dpMinOutDam);
  connect(bus.hAirOut, ctl.hAirOut);
  connect(bus.TAirRet, ctl.TAirRet);
  connect(bus.hAirRet, ctl.hAirRet);
  connect(bus.pBui_rel, ctl.dpBui);

  connect(bus.TAirMix, ctl.TAirMix);

  connect(bus.fanSup.y1_actual, ctl.u1SupFan);
  connect(bus.fanRel.y1_actual, ctl.u1RelFan);

  connect(bus.fanSup.V_flow, ctl.VAirSup_flow);
  connect(bus.fanRet.V_flow, ctl.VAirRet_flow);

  connect(bus.fanSup.y1_actual, y1FanSup_actual.u);
  connect(bus.TAirSup, TAirSup.u);

  // Inputs from terminal bus
  connect(busTer.yReqZonPreRes, reqZonPreRes.u);
  connect(busTer.yReqZonTemRes, reqZonTemRes.u);

  connect(busTer.VAdjPopBreZon_flow, aggZonVen_A621.VAdjPopBreZon_flow);
  connect(busTer.VAdjAreBreZon_flow, aggZonVen_A621.VAdjAreBreZon_flow);
  connect(busTer.VAirDis_flow, aggZonVen_A621.VZonPri_flow);
  connect(busTer.VMinOA_flow, aggZonVen_A621.VMinOA_flow);

  connect(busTer.VZonAbsMin_flow, aggZonVen_T24.VZonAbsMin_flow);
  connect(busTer.VZonDesMin_flow, aggZonVen_T24.VZonDesMin_flow);
  connect(busTer.yCO2, aggZonVen_T24.uCO2);

  connect(busTer.y1OveOccZon, repSigZon.zonOcc);
  connect(busTer.y1OccSch, repSigZon.u1Occ);
  connect(busTer.tNexOcc, repSigZon.tNexOcc);
  connect(busTer.yCooTim, repSigZon.uCooTim);
  connect(busTer.yWarTim, repSigZon.uWarTim);
  connect(busTer.yOccHeaHig, repSigZon.u1OccHeaHig);
  connect(busTer.yHigOccCoo, repSigZon.u1HigOccCoo);
  connect(busTer.yUnoHeaHig, repSigZon.u1UnoHeaHig);
  connect(busTer.TZonHeaUnoSet, repSigZon.THeaSetOff);
  connect(busTer.yEndSetBac, repSigZon.u1EndSetBac);
  connect(busTer.yHigUnoCoo, repSigZon.u1HigUnoCoo);
  connect(busTer.TZonCooUnoSet, repSigZon.TCooSetOff);
  connect(busTer.yEndSetUp, repSigZon.u1EndSetUp);
  connect(busTer.TZon, repSigZon.TZon);
  connect(busTer.y1Win, repSigZon.u1Win);

  // Outputs to AHU bus
  connect(ctl.yMinOutDam, bus.damOutMin.y);
  connect(ctl.y1MinOutDam, bus.damOutMin.y1);
  connect(ctl.yRetDam, bus.damRet.y);
  connect(ctl.yRelDam, bus.damRel.y);
  connect(ctl.y1RelDam, bus.damRel.y1);
  connect(ctl.yOutDam, bus.damOut.y);
  connect(ctl.y1EneCHWPum, bus.y1PumChiWat);
  connect(ctl.y1SupFan, bus.fanSup.y1);
  connect(ctl.ySupFan, bus.fanSup.y);
  connect(ctl.y1RetFan, bus.fanRet.y1);
  connect(ctl.yRetFan, bus.fanRet.y);
  connect(ctl.y1RelFan, bus.fanRel.y1);
  connect(ctl.yRelFan, bus.fanRel.y);
  connect(ctl.yCooCoi, bus.coiCoo.y);
  connect(ctl.yHeaCoi, bus.coiHea.y);

  connect(ctl.yAla, bus.ala);

  connect(ctl.yChiWatResReq, bus.reqChiWatRes);
  connect(ctl.yChiPlaReq, bus.reqChiWatPla);
  connect(ctl.yHotWatResReq, bus.reqHeaWatRes);
  connect(ctl.yHotWatPlaReq, bus.reqHeaWatPla);

  // Outputs to terminal unit bus
  connect(TAirSupSet.y, busTer.TAirSupSet);
  connect(TAirSup.y, busTer.TAirSup);
  connect(y1FanSup_actual.y, busTer.y1FanSup_actual);

  /* Control point connection - stop */

  connect(staGro.uGroOcc, opeModSel.u1Occ)
  connect(staGro.nexOcc, opeModSel.tNexOcc)
  connect(staGro.yCooTim, opeModSel.maxCooDowTim)
  connect(staGro.yWarTim, opeModSel.maxWarUpTim)
  connect(staGro.yOccHeaHig, opeModSel.u1OccHeaHig)
  connect(staGro.yHigOccCoo, opeModSel.u1HigOccCoo)
  connect(staGro.yEndSetBac, opeModSel.u1EndSetBac)
  connect(staGro.TZonMin, opeModSel.TZonMin)
  connect(staGro.yHotZon, opeModSel.totHotZon)
  connect(staGro.ySetUp, opeModSel.u1SetUp)
  connect(staGro.yEndSetUp, opeModSel.u1EndSetUp)
  connect(staGro.yOpeWin, opeModSel.uOpeWin)
  connect(reqZonTemRes.y,ctl. uZonTemResReq)
  connect(reqZonPreRes.y,ctl. uZonPreResReq)

  connect(repSigZon.y1ZonOcc, staGro.zonOcc)
  connect(repSigZon.y1Occ, staGro.u1Occ)
  connect(repSigZon.ytNexOcc, staGro.tNexOcc)
  connect(repSigZon.yCooTim, staGro.uCooTim)
  connect(repSigZon.yWarTim, staGro.uWarTim)
  connect(repSigZon.y1OccHeaHig, staGro.u1OccHeaHig)
  connect(repSigZon.y1HigOccCoo, staGro.u1HigOccCoo)
  connect(repSigZon.y1UnoHeaHig, staGro.u1UnoHeaHig)
  connect(repSigZon.yTHeaSetOff, staGro.THeaSetOff)
  connect(repSigZon.y1EndSetBac, staGro.u1EndSetBac)
  connect(repSigZon.y1HigUnoCoo, staGro.u1HigUnoCoo)
  connect(repSigZon.yTCooSetOff, staGro.TCooSetOff)
  connect(repSigZon.y1EndSetUp, staGro.u1EndSetUp)
  connect(repSigZon.yTZon, staGro.TZon)
  connect(repSigZon.y1Win, staGro.u1Win)
  connect(staGro.yColZon, opeModSel.totColZon)
  connect(staGro.ySetBac, opeModSel.u1SetBac)
  connect(aggZonVen_A621.VSumAdjPopBreZon_flow, ctl.VSumAdjPopBreZon_flow)
  connect(aggZonVen_A621.VSumAdjAreBreZon_flow, ctl.VSumAdjAreBreZon_flow)
  connect(aggZonVen_A621.VSumZonPri_flow, ctl.VSumZonPri_flow)
  connect(aggZonVen_A621.uOutAirFra_max, ctl.uOutAirFra_max)
  connect(aggZonVen_T24.VSumZonAbsMin_flow, ctl.VSumZonAbsMin_flow)
  connect(aggZonVen_T24.VSumZonDesMin_flow, ctl.VSumZonDesMin_flow)
  connect(aggZonVen_T24.yMaxCO2, ctl.uCO2Loo_max)
  connect(ctl.TAirSupSet, TAirSupSet.u)
  connect(opeModSel.yOpeMod, aggZonVen_A621.uOpeMod)
  connect(opeModSel.yOpeMod, aggZonVen_T24.uOpeMod)
  connect(opeModSel.yOpeMod, intVecRep.u)
  connect(asgOpeMod.y, busTer.yOpeMod)
  connect(intVecRep.y, asgOpeMod.u)
  connect(opeModSel.yOpeMod, ahuMod.uOpeMod)
  connect(ahuMod.yAhuOpeMod, ctl.uAhuOpeMod)

  connect(u1FreSta.y, ctl.u1FreSta)
  connect(u1SofSwiRes.y, ctl.u1SofSwiRes)
end G36VAVMultiZone;


Open loop controller. This is an open loop controller providing control inputs
for the templates within

Buildings.Templates.AirHandlersFans.
It is mainly used for testing purposes.

within Buildings.Templates.AirHandlersFans.Components.Controls;
block OpenLoop "Open loop controller"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialControllerVAVMultizone(
      final typ=Buildings.Templates.AirHandlersFans.Types.Controller.OpenLoop);

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yDamOut(k=1)
 if secOutRel.typDamOut == Buildings.Templates.Components.Types.Damper.Modulating
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant yDamOut1(k=true)
 if secOutRel.typDamOut == Buildings.Templates.Components.Types.Damper.TwoPosition
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yDamOutMin(k=1)
 if secOutRel.typDamOutMin == Buildings.Templates.Components.Types.Damper.Modulating
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant yDamOutMin1(k=true)
 if secOutRel.typDamOutMin == Buildings.Templates.Components.Types.Damper.TwoPosition
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yDamRet(k=1)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yDamRel(k=1)
 if secOutRel.typDamRel == Buildings.Templates.Components.Types.Damper.Modulating
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant yDamRel1(k=true)
 if secOutRel.typDamRel == Buildings.Templates.Components.Types.Damper.TwoPosition
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yCoiCoo(k=1) if coiCoo.typ
     == Buildings.Templates.Components.Types.Coil.WaterBasedCooling or coiCoo.typ
     == Buildings.Templates.Components.Types.Coil.EvaporatorVariableSpeed
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant yCoiCooSta(k=1)
    if coiCoo.typ == Buildings.Templates.Components.Types.Coil.EvaporatorMultiStage
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yFanSup(k=1)
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1FanSup(k=true)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yCoiHea(k=1)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yFanRet(k=1)
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1FanRet(k=true)

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yFanRel(k=1)
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1FanRel(k=true)
equation
  /* Control point connection - start */

  connect(yCoiCoo.y, bus.coiCoo.y);
  connect(yCoiHea.y, bus.coiHea.y);
  connect(yCoiCooSta.y, bus.coiCoo.y);

  connect(y1FanSup.y, bus.fanSup.y1);
  connect(yFanSup.y, bus.fanSup.y);
  connect(y1FanRel.y, bus.fanRel.y1);
  connect(yFanRel.y, bus.fanRel.y);
  connect(y1FanRet.y, bus.fanRet.y1);
  connect(yFanRet.y, bus.fanRet.y);

  connect(yDamOut.y, bus.damOut.y);
  connect(yDamOut1.y, bus.damOut.y1);
  connect(yDamOutMin.y, bus.damOutMin.y);
  connect(yDamOutMin1.y, bus.damOutMin.y1);
  connect(yDamRel.y, bus.damRel.y);
  connect(yDamRel1.y, bus.damRel.y1);
  connect(yDamRet.y, bus.damRet.y);
  /* Control point connection - stop */
end OpenLoop;


Controllers

within Buildings.Templates.AirHandlersFans.Components;
package Controls "Controllers"
  extends Modelica.Icons.VariantsPackage;
end Controls;


within Buildings.Templates.AirHandlersFans.Components;
package Data "Records for design and operating parameters"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


No heat recovery. This model represents a configuration with no heat recovery unit.
It resolves to four fluid ports that are not connected
to each other and for which pressure conditions must be provided.

within Buildings.Templates.AirHandlersFans.Components.HeatRecovery;
model None "No heat recovery"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialHeatRecovery(
     final typ=Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None);
end None;


Models for heat recovery

within Buildings.Templates.AirHandlersFans.Components;
package HeatRecovery "Models for heat recovery"
  extends Modelica.Icons.VariantsPackage;
end HeatRecovery;


Interface classes

within Buildings.Templates.AirHandlersFans.Components;
package Interfaces "Interface classes"
  extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Interface class for AHU controller. This partial class provides a standard interface for air handler controllers.

within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial block PartialController "Interface class for AHU controller"

  parameter Buildings.Templates.AirHandlersFans.Types.Controller typ
    "Type of controller"

  parameter Integer nZon
    "Number of served zones";

  outer parameter Buildings.Templates.Data.AllSystems datAll
    "Top-level (whole building) system parameters";

  parameter Buildings.Templates.Components.Types.Fan typFanSup
    "Type of supply fan";
  parameter Buildings.Templates.Components.Types.Fan typFanRel
    "Type of relief fan";
  parameter Buildings.Templates.Components.Types.Fan typFanRet
    "Type of return fan";
  parameter Integer nFanSup
    "Number of supply fans";
  parameter Integer nFanRel
    "Number of relief fans";
  parameter Integer nFanRet
    "Number of return fans";

  replaceable parameter
    Buildings.Templates.AirHandlersFans.Components.Data.PartialController dat(
    final typ=typ,
    final typFanSup=typFanSup,
    final typFanRel=typFanRel,
    final typFanRet=typFanRet)
    "Design and operating parameters"

  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus
    "AHU control bus"
  Buildings.Templates.ZoneEquipment.Interfaces.Bus busTer[nZon]
    "Terminal unit control bus"
end PartialController;


Interface class for multiple-zone VAV controller. This partial class provides a standard interface for multiple-zone VAV controllers.

within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial block PartialControllerVAVMultizone
  "Interface class for multiple-zone VAV controller"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialController(
      redeclare Buildings.Templates.AirHandlersFans.Components.Data.VAVMultiZoneController
        dat(
          typSecOut=secOutRel.typSecOut,
          buiPreCon=buiPreCon,
          stdVen=stdVen));

  outer replaceable
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorReliefReturnSection
    secOutRel "Outdoor/relief/return air section";
  outer replaceable Buildings.Templates.Components.Coils.None coiCoo
    "Cooling coil";
  outer replaceable Buildings.Templates.Components.Coils.None coiHeaPre
    "Heating coil (preheat position)";
  outer replaceable Buildings.Templates.Components.Coils.None coiHeaReh
    "Heating coil (reheat position)";

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer typCtlEco=
    Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedDryBulb
    "Economizer control type"

  parameter Buildings.Templates.AirHandlersFans.Types.ControlFanReturn typCtlFanRet=
    Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured
    "Return fan control type"

  parameter Boolean use_TMix=true
    "Set to true if mixed air temperature measurement is enabled"

  parameter Boolean have_frePro=true
    "Set to true to include freeze protection"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat typFreSta=
    Buildings.Controls.OBC.ASHRAE.G36.Types.FreezeStat.No_freeze_stat
    "Option for low limit (freeze) protection"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection typSecOut=
    secOutRel.typSecOut
    "Type of outdoor air section"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl
    buiPreCon=if secOutRel.typSecRel == Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefDamper
       then Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
       elseif secOutRel.typSecRel == Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefFan
       then Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefFan
       elseif secOutRel.typSecRel == Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReturnFan
       then (if typCtlFanRet == Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured
       then Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanMeasuredAir
       elseif typCtlFanRet == Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.BuildingPressure
       then Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReturnFanDp
       else Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper)
       else Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper
    "Type of building pressure control system"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.EnergyStandard stdEne=
    datAll.stdEne
    "Energy standard"

  final parameter Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard stdVen=
    datAll.stdVen
    "Ventilation standard"

  parameter Boolean have_CO2Sen=false
    "Set to true if there are zones with CO2 sensor"

initial equation
  if typ==Buildings.Templates.AirHandlersFans.Types.Controller.G36VAVMultiZone then
    // We check the fallback "else" clause.
    if buiPreCon == Buildings.Controls.OBC.ASHRAE.G36.Types.PressureControl.ReliefDamper then
      assert(secOutRel.typSecRel==Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefDamper,
       "In "+ getInstanceName() + ": "+
       "The system configuration is incompatible with available options for building pressure control.");
    end if;
  end if;
end PartialControllerVAVMultizone;


Interface class for heat recovery

within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial model PartialHeatRecovery "Interface class for heat recovery"

  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"

  parameter Buildings.Templates.AirHandlersFans.Types.HeatRecovery typ
    "Equipment type"

  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"

  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus
    if typ <> Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None
    "Control bus"
  Modelica.Fluid.Interfaces.FluidPort_a port_aOut(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None
    "Outdoor air inlet"
  Modelica.Fluid.Interfaces.FluidPort_b port_bOut(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None
    "Outdoor air outlet"
  Modelica.Fluid.Interfaces.FluidPort_a port_aRel(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None
    "Relief/exhaust air inlet"
  Modelica.Fluid.Interfaces.FluidPort_b port_bRel(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None
    "Relief/exhaust air outlet"
end PartialHeatRecovery;


within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial model PartialOutdoorReliefReturnSection
  "Interface class for outdoor/relief/return air section"

  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"

  parameter Buildings.Templates.AirHandlersFans.Types.OutdoorReliefReturnSection typ
    "Outdoor/relief/return air section type"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection typSecOut
    "Outdoor air section type"
  parameter Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection typSecRel
    "Relief/return air section type"
  parameter Buildings.Templates.Components.Types.Damper typDamOut
    "Outdoor air damper type"
  parameter Buildings.Templates.Components.Types.Damper typDamOutMin
    "Minimum outdoor air damper type"
  parameter Buildings.Templates.Components.Types.Damper typDamRel
    "Relief damper type"
  parameter Buildings.Templates.Components.Types.Damper typDamRet
    "Return damper type"
  parameter Buildings.Templates.Components.Types.Fan typFanRel
    "Relief fan type"
  parameter Buildings.Templates.Components.Types.Fan typFanRet
    "Return fan type"
  parameter Integer nFanRet(
    start=if typFanRet==Buildings.Templates.Components.Types.Fan.None then 0 else 1)
    "Number of return fans"
  parameter Integer nFanRel(
    start=if typFanRel==Buildings.Templates.Components.Types.Fan.None then 0 else 1)
    "Number of relief fans"
  parameter Boolean have_eco
    "Set to true in case of economizer function"
  parameter Boolean have_recHea = false
    "Set to true in case of heat recovery"
  parameter Buildings.Templates.AirHandlersFans.Types.ControlFanReturn typCtlFanRet=
    Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured
    "Return fan control type"
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer typCtlEco=
    Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedDryBulb
    "Economizer control type"

  parameter
    Buildings.Templates.AirHandlersFans.Components.Data.OutdoorReliefReturnSection
    dat(
      final typDamOut=typDamOut,
      final typDamOutMin=typDamOutMin,
      final typDamRet=typDamRet,
      final typDamRel=typDamRel,
      final typFanRel=typFanRel,
      final typFanRet=typFanRet)
    "Design and operating parameters"

  final parameter Modelica.Units.SI.MassFlowRate mAirSup_flow_nominal=
    dat.damOut.m_flow_nominal
    "Supply air mass flow rate";
  final parameter Modelica.Units.SI.MassFlowRate mAirRet_flow_nominal=
    dat.damRet.m_flow_nominal
    "Return air mass flow rate";
  final parameter Modelica.Units.SI.MassFlowRate mOutMin_flow_nominal=
    dat.mOutMin_flow_nominal
    "Minimum outdoor air mass flow rate at design conditions";

  final parameter Modelica.Units.SI.PressureDifference dpDamOut_nominal=
    dat.damOut.dp_nominal
    "Outdoor air damper pressure drop";
  final parameter Modelica.Units.SI.PressureDifference dpDamOutMin_nominal=
    dat.damOutMin.dp_nominal
    "Minimum outdoor air damper pressure drop";
  final parameter Modelica.Units.SI.PressureDifference dpDamRel_nominal=
    dat.damRel.dp_nominal
    "Relief air damper pressure drop";
  final parameter Modelica.Units.SI.PressureDifference dpDamRet_nominal=
    dat.damRet.dp_nominal
    "Return air damper pressure drop";

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

  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"

  Modelica.Fluid.Interfaces.FluidPort_b port_Rel(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.OutdoorReliefReturnSection.MixedAirNoRelief
    "Relief (exhaust) air"
  Modelica.Fluid.Interfaces.FluidPort_a port_Out(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Outdoor air intake"
  Modelica.Fluid.Interfaces.FluidPort_b port_Sup(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Supply air"
  Modelica.Fluid.Interfaces.FluidPort_a port_Ret(
    redeclare final package Medium =MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Return air"
  Modelica.Fluid.Interfaces.FluidPort_b port_bPre(
    redeclare final package Medium = MediumAir)
    "Optional fluid connector for differential pressure sensor"
  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus "Control bus"

end PartialOutdoorReliefReturnSection;


Interface class for outdoor air section

within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial model PartialOutdoorSection "Interface class for outdoor air section"

  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection typ
    "Outdoor air section type"
  final parameter Buildings.Templates.Components.Types.Damper typDamOut=
    if typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper
    or typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    or typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    then Buildings.Templates.Components.Types.Damper.Modulating
    else Buildings.Templates.Components.Types.Damper.None
    "Outdoor air damper type"
  final parameter Buildings.Templates.Components.Types.Damper typDamOutMin=
    if typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper
    then Buildings.Templates.Components.Types.Damper.None
    elseif typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow
    then Buildings.Templates.Components.Types.Damper.Modulating
    elseif typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure
    then Buildings.Templates.Components.Types.Damper.TwoPosition
    else Buildings.Templates.Components.Types.Damper.None
    "Minimum outdoor air damper type"
  parameter Boolean have_recHea
    "Set to true in case of heat recovery";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer typCtlEco
    "Economizer control type";

  parameter
    Buildings.Templates.AirHandlersFans.Components.Data.OutdoorReliefReturnSection
    dat "Design and operating parameters";

  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=
    dat.damOut.m_flow_nominal
    "Air mass flow rate";
  final parameter Modelica.Units.SI.MassFlowRate mOutMin_flow_nominal=
    dat.mOutMin_flow_nominal
    "Minimum outdoor air mass flow rate";

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

  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"

  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Fluid connector a (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Fluid connector b (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHeaRec(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default)) if have_recHea
    "Optional fluid connector for heat recovery"
  Modelica.Fluid.Interfaces.FluidPort_b port_bHeaRec(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default)) if have_recHea
    "Optional fluid connector for heat recovery"
  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus
    "Control bus"
end PartialOutdoorSection;


within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial model PartialOutdoorSectionDedicatedDampers
  "Base class for modeling separate dampers for ventilation and economizer"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorSection;

  Buildings.Templates.Components.Actuators.Damper damOut(
    redeclare final package Medium = MediumAir,
    final typ=typDamOut,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damOut)
    "Economizer outdoor air damper"
  Buildings.Templates.Components.Actuators.Damper damOutMin(
    redeclare final package Medium = MediumAir,
    final typ=typDamOutMin,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damOutMin)
    "Minimum outdoor air damper"

  Buildings.Templates.Components.Sensors.Temperature TOut(
    redeclare final package Medium =  MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=true,
    final m_flow_nominal=mOutMin_flow_nominal)
    "Outdoor air temperature sensor"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VOutMin_flow(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow,
    final m_flow_nominal=mOutMin_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.AFMS)
    "Minimum outdoor air volume flow rate sensor"
  Buildings.Templates.Components.Sensors.SpecificEnthalpy hAirOut(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=
      typCtlEco==Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedEnthalpyWithFixedDryBulb or
      typCtlEco==Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb,
    final m_flow_nominal=mOutMin_flow_nominal)
    "Outdoor air enthalpy sensor"
  Buildings.Templates.Components.Sensors.DifferentialPressure dpAirOutMin(
    redeclare final package Medium = MediumAir,
    final have_sen=typ==Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure)
    "Minimum outdoor air damper differential pressure sensor"
  Buildings.Fluid.FixedResistances.Junction junInl(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=m_flow_nominal*{1,-1,-1},
    dp_nominal=fill(0,3),
    final energyDynamics=energyDynamics) "Inlet fluid junction"
  Fluid.FixedResistances.Junction junOut(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal=m_flow_nominal*{1,-1,1},
    dp_nominal=fill(0, 3),
    final energyDynamics=energyDynamics) "Outlet fluid junction"
equation
  /* Control point connection - start */
  connect(damOut.bus, bus.damOut);
  connect(damOutMin.bus, bus.damOutMin);
  connect(TOut.y, bus.TOut);
  connect(hAirOut.y, bus.hAirOut);
  connect(VOutMin_flow.y, bus.VOutMin_flow);
  connect(dpAirOutMin.y, bus.dpAirOutMin);
  /* Control point connection - end */
  connect(TOut.port_b, VOutMin_flow.port_a)
  connect(damOutMin.port_b, hAirOut.port_a)
  connect(hAirOut.port_b, TOut.port_a)
  connect(damOutMin.port_a, dpAirOutMin.port_a)
  connect(dpAirOutMin.port_b, damOutMin.port_b)
  connect(damOut.port_a, junInl.port_2)
  connect(port_a, junInl.port_1)
  connect(junInl.port_3, damOutMin.port_a)
  connect(port_b, junOut.port_2)
  connect(damOut.port_b, junOut.port_1)
  connect(VOutMin_flow.port_b, junOut.port_3)
end PartialOutdoorSectionDedicatedDampers;


within Buildings.Templates.AirHandlersFans.Components.Interfaces;
partial model PartialReliefReturnSection "Interface class for relief/return air section"

  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"

  parameter Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection typ
    "Relief/return air section type"
  parameter Buildings.Templates.Components.Types.Damper typDamRel
    "Relief damper type"
  parameter Buildings.Templates.Components.Types.Fan typFanRel
    "Relief fan type"
  parameter Buildings.Templates.Components.Types.Fan typFanRet
    "Return fan type"
  parameter Integer nFanRet(
    start=if typFanRet==Buildings.Templates.Components.Types.Fan.None then 0 else 1)
    "Number of return fans"
  parameter Integer nFanRel(
    start=if typFanRel==Buildings.Templates.Components.Types.Fan.None then 0 else 1)
    "Number of relief fans"

  parameter Boolean have_recHea
    "Set to true in case of heat recovery";
  parameter Buildings.Templates.AirHandlersFans.Types.ControlFanReturn typCtlFanRet
    "Return fan control type";
  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer typCtlEco
    "Economizer control type";

  parameter
    Buildings.Templates.AirHandlersFans.Components.Data.OutdoorReliefReturnSection
    dat "Design and operating parameters";

  final parameter Modelica.Units.SI.MassFlowRate m_flow_nominal=
    if typFanRet <> Buildings.Templates.Components.Types.Fan.None then dat.fanRet.m_flow_nominal
    elseif typFanRel <> Buildings.Templates.Components.Types.Fan.None then dat.fanRel.m_flow_nominal
    elseif typDamRel <> Buildings.Templates.Components.Types.Damper.None then dat.damRel.m_flow_nominal
    else dat.damRet.m_flow_nominal
    "Air mass flow rate"

  final parameter Modelica.Units.SI.PressureDifference dpFan_nominal=
    if typFanRel <> Buildings.Templates.Components.Types.Fan.None then
      dat.fanRel.dp_nominal
    elseif typFanRet <> Buildings.Templates.Components.Types.Fan.None then
      dat.fanRet.dp_nominal
    else 0
    "Relief/return fan total pressure rise"

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

  parameter Boolean allowFlowReversal = true
    "= false to simplify equations, assuming, but not enforcing, no flow reversal"

  Modelica.Fluid.Interfaces.FluidPort_a port_a(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    "Fluid connector a (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_b port_b(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.NoRelief
    "Fluid connector b (positive design flow direction is from port_a to port_b)"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHeaRec(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversal then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default)) if have_recHea
    "Optional fluid connector for heat recovery"
  Modelica.Fluid.Interfaces.FluidPort_b port_bHeaRec(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default)) if have_recHea
    "Optional fluid connector for heat recovery"
  Modelica.Fluid.Interfaces.FluidPort_b port_bRet(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversal then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.NoReturn
    "Optional fluid connector for return branch"
  Modelica.Fluid.Interfaces.FluidPort_b port_bPre(
    redeclare final package Medium = MediumAir)
    "Fluid connector for differential pressure sensor"
  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus
    "Control bus"
  Buildings.Fluid.FixedResistances.Junction splEco(
    redeclare final package Medium = MediumAir,
    final m_flow_nominal={1,-1,-1}*m_flow_nominal,
    final dp_nominal=fill(0, 3),
    final energyDynamics=energyDynamics,
    final portFlowDirection_1=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Entering,
    final portFlowDirection_2=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving,
    final portFlowDirection_3=if allowFlowReversal then
      Modelica.Fluid.Types.PortFlowDirection.Bidirectional
      else Modelica.Fluid.Types.PortFlowDirection.Leaving)
    "Splitter with air economizer"
  Buildings.Templates.Components.Sensors.DifferentialPressure pAirRet_rel(
    redeclare final package Medium = MediumAir,
    final have_sen=typFanRet<>Buildings.Templates.Components.Types.Fan.None and
      typCtlFanRet==Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.BuildingPressure)
    "Return fan discharge static pressure sensor"
equation
  /* Control point connection - start */
  connect(pAirRet_rel.y, bus.pAirRet_rel);
  /* Control point connection - end */
  connect(splEco.port_3, port_bRet)
  connect(pAirRet_rel.port_a, splEco.port_1)
  connect(pAirRet_rel.port_b, port_bPre)
end PartialReliefReturnSection;


Mixed air system with return air damper

within Buildings.Templates.AirHandlersFans.Components.OutdoorReliefReturnSection;
model MixedAirWithDamper "Mixed air system with return air damper"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.OutdoorReliefReturnSection.MixedAirWithDamper,
    final typSecOut=secOut.typ,
    final typSecRel=secRel.typ,
    final typDamOut=secOut.typDamOut,
    final typDamOutMin=secOut.typDamOutMin,
    final typDamRel=secRel.typDamRel,
    final typDamRet=damRet.typ,
    final typFanRel=secRel.typFanRel,
    final typFanRet=secRel.typFanRet,
    final nFanRel=secRel.nFanRel,
    final nFanRet=secRel.nFanRet,
    final have_eco=true,
    final have_recHea=recHea.typ<>Buildings.Templates.AirHandlersFans.Types.HeatRecovery.None);

  replaceable
    Buildings.Templates.AirHandlersFans.Components.OutdoorSection.SingleDamper
    secOut constrainedby
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorSection(
      redeclare final package MediumAir = MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversal,
      final dat=dat,
      final have_recHea=have_recHea,
      final typCtlEco=typCtlEco)
    "Outdoor air section"

  replaceable
    Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection.ReturnFan
    secRel constrainedby
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
      redeclare final package MediumAir = MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversal,
      final dat=dat,
      final have_recHea=have_recHea,
      final typCtlFanRet=typCtlFanRet,
      final typCtlEco=typCtlEco)
    "Relief/return air section"

  Buildings.Templates.Components.Actuators.Damper damRet(
    redeclare final package Medium = MediumAir,
    final typ=Buildings.Templates.Components.Types.Damper.Modulating,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damRet,
    final text_rotation=90)
    "Return damper"

  // Currently only the configuration without heat recovery is supported.
  replaceable Buildings.Templates.AirHandlersFans.Components.HeatRecovery.None recHea
    constrainedby
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialHeatRecovery(
      redeclare final package MediumAir = MediumAir,
      final allowFlowReversal=allowFlowReversal)
    "Heat recovery"

equation
  /* Control point connection - start */
  connect(damRet.bus, bus.damRet);
  connect(bus, secRel.bus);
  connect(secOut.bus, bus);
  connect(recHea.bus, bus);
  /* Control point connection - end */
  connect(port_Rel, secRel.port_b)
  connect(secRel.port_a, port_Ret)
  connect(secRel.port_bRet, damRet.port_a)
  connect(port_Out, secOut.port_a)
  connect(secOut.port_b, port_Sup)
  connect(damRet.port_b, port_Sup)
  connect(secRel.port_bPre, port_bPre)
  connect(recHea.port_aRel, secRel.port_bHeaRec)
  connect(secRel.port_aHeaRec, recHea.port_bRel)
  connect(recHea.port_aOut, secOut.port_bHeaRec)
  connect(recHea.port_bOut, secOut.port_aHeaRec)
end MixedAirWithDamper;


within Buildings.Templates.AirHandlersFans.Components;
package OutdoorReliefReturnSection "Models for outdoor/relief/return air section"
  extends Modelica.Icons.VariantsPackage;
end OutdoorReliefReturnSection;


Separate dampers for ventilation and economizer, with airflow measurement station. This model represents a configuration with an air economizer and
minimum OA control with a separate minimum OA damper and airflow measurement.

within Buildings.Templates.AirHandlersFans.Components.OutdoorSection;
model DedicatedDampersAirflow
  "Separate dampers for ventilation and economizer, with airflow measurement station"
  extends Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorSectionDedicatedDampers(
    final typ=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersAirflow);
end DedicatedDampersAirflow;


Separate dampers for ventilation and economizer, with differential pressure sensor. This model represents a configuration with an air economizer and
minimum OA control with a separate minimum OA damper and differential
pressure control.

within Buildings.Templates.AirHandlersFans.Components.OutdoorSection;
model DedicatedDampersPressure
  "Separate dampers for ventilation and economizer, with differential pressure sensor"
  extends Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorSectionDedicatedDampers(
    final typ=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.DedicatedDampersPressure);
end DedicatedDampersPressure;


Models for outdoor air section

within Buildings.Templates.AirHandlersFans.Components;
package OutdoorSection "Models for outdoor air section"
  extends Modelica.Icons.VariantsPackage;
end OutdoorSection;


within Buildings.Templates.AirHandlersFans.Components.OutdoorSection;
model SingleDamper
  "Single damper for ventilation and economizer, with airflow measurement station"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialOutdoorSection(
    final typ=Buildings.Controls.OBC.ASHRAE.G36.Types.OutdoorAirSection.SingleDamper);

  Buildings.Templates.Components.Actuators.Damper damOut(
    redeclare final package Medium = MediumAir,
    final typ=typDamOut,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damOut)
    "Outdoor air damper"

  Buildings.Templates.Components.Sensors.VolumeFlowRate VOut_flow(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=true,
    final m_flow_nominal=m_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.AFMS)
    "Outdoor air volume flow rate sensor"
  Buildings.Templates.Components.Sensors.Temperature TOut(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=true,
    final m_flow_nominal=m_flow_nominal)
    "Outdoor air temperature sensor"
  Buildings.Templates.Components.Sensors.SpecificEnthalpy hAirOut(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversal,
    final have_sen=typCtlEco == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.FixedEnthalpyWithFixedDryBulb
      or typCtlEco == Buildings.Controls.OBC.ASHRAE.G36.Types.ControlEconomizer.DifferentialEnthalpyWithFixedDryBulb,
    final m_flow_nominal=m_flow_nominal) "Outdoor air enthalpy sensor"

equation
  /* Control point connection - start */
  connect(damOut.bus, bus.damOut);
  connect(TOut.y, bus.TOut);
  connect(hAirOut.y, bus.hAirOut);
  connect(VOut_flow.y, bus.VOut_flow);
  /* Control point connection - end */
  connect(TOut.port_b, VOut_flow.port_a)
  connect(VOut_flow.port_b, port_b)

  connect(damOut.port_b, hAirOut.port_a)
  connect(hAirOut.port_b, TOut.port_a)
  connect(port_a, damOut.port_a)
end SingleDamper;


No relief branch

within Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection;
model NoRelief "No relief branch"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.NoRelief,
    final typDamRel=Buildings.Templates.Components.Types.Damper.None,
    final typFanRel=Buildings.Templates.Components.Types.Fan.None,
    final typFanRet=fanRet.typ,
    final nFanRel=0,
    final nFanRet=fanRet.nFan);

  replaceable Buildings.Templates.Components.Fans.None fanRet
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
      redeclare final package Medium = MediumAir,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversal,
      final dat=dat.fanRet,
      final have_senFlo=
        typCtlFanRet==Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured,
      final text_flip=true)
    "Return fan"

equation
  /* Control point connection - start */
  connect(fanRet.bus, bus.fanRet);
  /* Control point connection - end */
  connect(fanRet.port_b, splEco.port_1)
  connect(fanRet.port_a, port_a)
end NoRelief;


No return branch

within Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection;
model NoReturn "No return branch"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.NoReturn,
    final typDamRel=damRel.typ,
    final typFanRel=Buildings.Templates.Components.Types.Fan.None,
    final typFanRet=fanRet.typ,
    final nFanRel=0,
    final nFanRet=fanRet.nFan);

  Buildings.Templates.Components.Actuators.Damper damRel(
    redeclare final package Medium = MediumAir,
    final typ=Buildings.Templates.Components.Types.Damper.TwoPosition,
    final dat=dat.damRel,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final text_flip=true)
    "Relief damper"
  replaceable Buildings.Templates.Components.Fans.SingleVariable fanRet
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
      redeclare final package Medium = MediumAir,
      final dat=dat.fanRet,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversal,
      final have_senFlo=
        typCtlFanRet==Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured,
      final text_flip=true)
    "Return fan"

equation
  /* Control point connection - start */
  connect(fanRet.bus, bus.fanRet);
  connect(damRel.bus, bus.damRel);
  /* Control point connection - end */
  connect(port_b, damRel.port_b)
  connect(damRel.port_a, splEco.port_2)
  connect(splEco.port_1, fanRet.port_b)
  connect(fanRet.port_a, port_a)
end NoReturn;


Models for relief/return air section

within Buildings.Templates.AirHandlersFans.Components;
package ReliefReturnSection "Models for relief/return air section"
  extends Modelica.Icons.VariantsPackage;
end ReliefReturnSection;


Modulating relief damper without fan

within Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection;
model ReliefDamper "Modulating relief damper without fan"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefDamper,
    final typDamRel=damRel.typ,
    final typFanRel=Buildings.Templates.Components.Types.Fan.None,
    final typFanRet=Buildings.Templates.Components.Types.Fan.None,
    final nFanRel=0,
    final nFanRet=0);

  Buildings.Templates.Components.Actuators.Damper damRel(
    redeclare final package Medium = MediumAir,
    final typ=Buildings.Templates.Components.Types.Damper.Modulating,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damRel,
    final text_flip=true,
    typBla=Buildings.Templates.Components.Types.DamperBlades.Opposed)
    "Relief damper"
equation
  /* Control point connection - start */
  connect(damRel.bus, bus.damRel);
  /* Control point connection - end */
  connect(port_b, damRel.port_b)
  connect(damRel.port_a, splEco.port_2)
  connect(splEco.port_1, port_a)
end ReliefDamper;


within Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection;
model ReliefFan "Relief fan with two-position relief damper"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReliefFan,
    final typDamRel=damRel.typ,
    final typFanRel=fanRel.typ,
    final typFanRet=Buildings.Templates.Components.Types.Fan.None,
    final nFanRel=fanRel.nFan,
    final nFanRet=0);

  Buildings.Templates.Components.Actuators.Damper damRel(
    redeclare final package Medium = MediumAir,
    final typ=Buildings.Templates.Components.Types.Damper.TwoPosition,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final dat=dat.damRel,
    final text_flip=true)
    "Relief damper"
  replaceable Buildings.Templates.Components.Fans.SingleVariable fanRel
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
    redeclare final package Medium = MediumAir,
    final dat=dat.fanRel,
    final energyDynamics=energyDynamics,
    final allowFlowReversal=allowFlowReversal,
    final have_senFlo=false,
    final text_flip=true,
    typSin=Buildings.Templates.Components.Types.FanSingle.Propeller)
    "Relief fan"
equation
  /* Control point connection - start */
  connect(fanRel.bus, bus.fanRel);
  connect(damRel.bus, bus.damRel);
  /* Control point connection - end */
  connect(port_b, damRel.port_b)
  connect(damRel.port_a, fanRel.port_b)
  connect(fanRel.port_a, splEco.port_2)
  connect(splEco.port_1, port_a)
end ReliefFan;


within Buildings.Templates.AirHandlersFans.Components.ReliefReturnSection;
model ReturnFan "Return fan with modulating relief damper"
  extends
    Buildings.Templates.AirHandlersFans.Components.Interfaces.PartialReliefReturnSection(
    final typ=Buildings.Templates.AirHandlersFans.Types.ReliefReturnSection.ReturnFan,
    final typDamRel=damRel.typ,
    final typFanRel=Buildings.Templates.Components.Types.Fan.None,
    final typFanRet=fanRet.typ,
    final nFanRel=0,
    final nFanRet=fanRet.nFan);

  Buildings.Templates.Components.Actuators.Damper damRel(
    redeclare final package Medium = MediumAir,
    final typ=Buildings.Templates.Components.Types.Damper.Modulating,
    final dat=dat.damRel,
    use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
    final allowFlowReversal=allowFlowReversal,
    final text_flip=true)
    "Relief damper"
  replaceable Buildings.Templates.Components.Fans.SingleVariable fanRet
    constrainedby Buildings.Templates.Components.Interfaces.PartialFan(
      redeclare final package Medium = MediumAir,
      final dat=dat.fanRet,
      final energyDynamics=energyDynamics,
      final allowFlowReversal=allowFlowReversal,
      final have_senFlo=
        typCtlFanRet==Buildings.Templates.AirHandlersFans.Types.ControlFanReturn.AirflowMeasured,
      final text_flip=true)
    "Return fan"

equation
  /* Control point connection - start */
  connect(fanRet.bus, bus.fanRet);
  connect(damRel.bus, bus.damRel);
  /* Control point connection - end */
  connect(port_b, damRel.port_b)
  connect(fanRet.port_b, splEco.port_1)
  connect(damRel.port_a, splEco.port_2)
  connect(fanRet.port_a, port_a)
end ReturnFan;


Records for configuration parameters

within Buildings.Templates.AirHandlersFans;
package Configuration "Records for configuration parameters"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Configuration;


within Buildings.Templates.AirHandlersFans;
package Data "Records for design and operating parameters"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Interface classes

within Buildings.Templates.AirHandlersFans;
package Interfaces "Interface classes"
extends Modelica.Icons.InterfacesPackage;
end Interfaces;


Interface class for air handler

within Buildings.Templates.AirHandlersFans.Interfaces;
partial model PartialAirHandler "Interface class for air handler"
  inner replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"
  inner replaceable package MediumChiWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "CHW medium"
  inner replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "HHW medium"

  parameter Buildings.Templates.AirHandlersFans.Types.Configuration typ
    "Type of system"

  replaceable parameter
    Buildings.Templates.AirHandlersFans.Configuration.PartialAirHandler cfg(
    final typ=typ,
    final typFanSup=typFanSup,
    final typFanRel=typFanRel,
    final typFanRet=typFanRet,
    final have_souChiWat=have_souChiWat,
    final have_souHeaWat=have_souHeaWat)
    "Configuration parameters"

  inner parameter Integer nZon(min=1)
    "Number of served zones"

  replaceable parameter
    Buildings.Templates.AirHandlersFans.Data.PartialAirHandler dat(
    cfg=cfg)
    "Design and operating parameters"

  final parameter String id=dat.id
   "System tag"

  parameter Boolean have_porRel=
    typ==Buildings.Templates.AirHandlersFans.Types.Configuration.ExhaustOnly
    "Set to true for relief (exhaust) fluid port"
  parameter Boolean have_souChiWat
    "Set to true if system uses CHW"
  parameter Boolean have_souHeaWat
    "Set to true if system uses HHW"

  inner parameter Buildings.Templates.Components.Types.Fan typFanSup
    "Type of supply fan"
  inner parameter Buildings.Templates.Components.Types.Fan typFanRet
    "Type of return fan"
  inner parameter Buildings.Templates.Components.Types.Fan typFanRel
    "Type of relief fan"
  parameter Integer nFanSup
    "Number of supply fans"
  parameter Integer nFanRet
    "Number of return fans"
  parameter Integer nFanRel
    "Number of relief fans"

  // Design parameters
  final parameter Modelica.Units.SI.MassFlowRate mAirSup_flow_nominal=
    dat.mAirSup_flow_nominal
    "Supply air mass flow rate"
  final parameter Modelica.Units.SI.MassFlowRate mAirRet_flow_nominal=
    dat.mAirRet_flow_nominal
    "Return air mass flow rate"
  parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal
    "Total CHW mass flow rate"
  parameter Modelica.Units.SI.MassFlowRate mHeaWat_flow_nominal
    "Total HHW mass flow rate"
  parameter Modelica.Units.SI.HeatFlowRate QChiWat_flow_nominal
    "Total CHW heat flow rate"
  parameter Modelica.Units.SI.HeatFlowRate QHeaWat_flow_nominal
    "Total HHW heat flow rate"

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

  final parameter Boolean allowFlowReversalAir=true
    "= true to allow flow reversal, false restricts to design direction - Air side"
  parameter Boolean allowFlowReversalLiq=true
    "= true to allow flow reversal, false restricts to design direction - CHW and HW side"
  parameter Boolean show_T = false
    "= true, if actual temperature at ports of subcomponents is computed"

  Modelica.Fluid.Interfaces.FluidPort_a port_Out(
    redeclare final package Medium = MediumAir,
    m_flow(min=if allowFlowReversalAir then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.Configuration.ExhaustOnly
    "Outdoor air intake"
  Modelica.Fluid.Interfaces.FluidPort_b port_Sup(
    redeclare final package Medium =MediumAir,
    m_flow(max=if allowFlowReversalAir then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default)) if typ
     == Buildings.Templates.AirHandlersFans.Types.Configuration.SupplyOnly or typ ==
    Buildings.Templates.AirHandlersFans.Types.Configuration.SingleDuct
    "Supply air"
  Modelica.Fluid.Interfaces.FluidPort_b port_SupCol(
    redeclare final package Medium =MediumAir,
    m_flow(max=if allowFlowReversalAir then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ == Buildings.Templates.AirHandlersFans.Types.Configuration.DualDuct
    "Dual duct cold deck air supply"
  Modelica.Fluid.Interfaces.FluidPort_b port_SupHot(
    redeclare final package Medium =MediumAir,
    m_flow(max=if allowFlowReversalAir then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ == Buildings.Templates.AirHandlersFans.Types.Configuration.DualDuct
    "Dual duct hot deck air supply"
  Modelica.Fluid.Interfaces.FluidPort_a port_Ret(
    redeclare final package Medium =MediumAir,
    m_flow(min=if allowFlowReversalAir then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.Configuration.SupplyOnly
    "Return air"
  Modelica.Fluid.Interfaces.FluidPort_b port_Rel(
    redeclare final package Medium = MediumAir,
    m_flow(max=if allowFlowReversalAir then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumAir.h_default, nominal=MediumAir.h_default))
    if typ <> Buildings.Templates.AirHandlersFans.Types.Configuration.SupplyOnly and have_porRel
    "Relief (exhaust) air"
  Modelica.Fluid.Interfaces.FluidPort_b port_bChiWat(
    redeclare final package Medium = MediumChiWat,
    m_flow(max=if allowFlowReversalLiq then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumChiWat.h_default, nominal=MediumChiWat.h_default))
    if have_souChiWat
    "CHW return port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aChiWat(
    redeclare final package Medium = MediumChiWat,
    m_flow(min=if allowFlowReversalLiq then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumChiWat.h_default, nominal=MediumChiWat.h_default))
    if have_souChiWat
    "CHW supply port"
  Modelica.Fluid.Interfaces.FluidPort_b port_bHeaWat(
    redeclare final package Medium = MediumHeaWat,
    m_flow(max=if allowFlowReversalLiq then +Modelica.Constants.inf else 0),
    h_outflow(start=MediumHeaWat.h_default, nominal=MediumHeaWat.h_default))
    if have_souHeaWat
    "HHW return port"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHeaWat(
    redeclare final package Medium = MediumHeaWat,
    m_flow(min=if allowFlowReversalLiq then -Modelica.Constants.inf else 0),
    h_outflow(start=MediumHeaWat.h_default, nominal=MediumHeaWat.h_default))
    if have_souHeaWat
    "HHW supply port"
  Buildings.Templates.AirHandlersFans.Interfaces.Bus bus
    "AHU control bus"
  Buildings.BoundaryConditions.WeatherData.Bus busWea
    "Weather bus"
  Buildings.Templates.ZoneEquipment.Interfaces.Bus busTer[nZon]
    "Terminal unit control bus"
end PartialAirHandler;


Package with validation models

within Buildings.Templates.AirHandlersFans;
package Validation "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;
end Validation;


Validation model for multiple-zone VAV

within Buildings.Templates.AirHandlersFans.Validation;
model VAVMultiZone "Validation model for multiple-zone VAV"
  extends Modelica.Icons.Example;
  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium";
  replaceable package MediumChiWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Cooling medium (such as CHW)";
  replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Heating medium (such as HHW)";

  inner parameter UserProject.Data.AllSystems datAll(
    final VAV_1(cfg=VAV_1.cfg))
    "Design and operating parameters"

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

  Buildings.Templates.AirHandlersFans.VAVMultiZone VAV_1(
    nZon=2,
    ctl(
      idZon={"Box_1","Box_1"},
      namGro={"Floor_1"},
      namGroZon={"Floor_1","Floor_1"}),
    final dat=datAll.VAV_1,
    redeclare final package MediumAir = MediumAir,
    redeclare final package MediumChiWat = MediumChiWat,
    final energyDynamics=energyDynamics)
    "Air handling unit"
  Buildings.Fluid.Sources.Boundary_pT bouOut(
    redeclare final package Medium =MediumAir,
    nPorts=2)
    "Boundary conditions for outdoor environment"
  Buildings.Fluid.Sources.Boundary_pT bouBui(
    redeclare final package Medium =MediumAir,
    nPorts=3)
    "Boundary conditions for indoor environment"
  Fluid.FixedResistances.PressureDrop res(
    redeclare final package Medium=MediumAir,
    m_flow_nominal=1, dp_nominal=100)
  Fluid.FixedResistances.PressureDrop res1(
    redeclare final package Medium = MediumAir,
    m_flow_nominal=1,
    dp_nominal=100)
  Fluid.Sensors.Pressure pBui(redeclare final package Medium = MediumAir)
    "Building absolute pressure in representative space"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
    Modelica.Utilities.Files.loadResource(
    "modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  Fluid.FixedResistances.PressureDrop res2(
    redeclare final package Medium = MediumAir,
    m_flow_nominal=1,
    dp_nominal=100)
  Fluid.FixedResistances.PressureDrop res3(
    redeclare final package Medium = MediumAir,
    m_flow_nominal=1,
    dp_nominal=100)
  Fluid.Sources.Boundary_pT bouHeaWat(
    redeclare final package Medium = MediumHeaWat,
    nPorts=2) if VAV_1.have_souHeaWat
    "Boundary conditions for HHW distribution system"
  Fluid.Sources.Boundary_pT bouChiWat(
    redeclare final package Medium = MediumChiWat,
    nPorts=2) if VAV_1.have_souChiWat
    "Boundary conditions for CHW distribution system"
  UserProject.VAVBoxControlPoints sigVAVBox[VAV_1.nZon](each final stdVen=
        datAll.stdVen) if VAV_1.ctl.typ == Buildings.Templates.AirHandlersFans.Types.Controller.G36VAVMultiZone
    "Control signals from VAV box"
  ZoneEquipment.Validation.UserProject.BASControlPoints sigBAS(
    final nZon=VAV_1.nZon)
    "BAS control points"
  ZoneEquipment.Validation.UserProject.ZoneControlPoints sigZon[VAV_1.nZon]
    "Zone control points"
protected
  Interfaces.Bus busAHU
  "Gateway bus"

equation
  connect(bouHeaWat.ports[1], VAV_1.port_aHeaWat)
  connect(bouChiWat.ports[2], VAV_1.port_bChiWat)
  connect(VAV_1.port_bHeaWat, bouHeaWat.ports[2])
  connect(VAV_1.port_aChiWat, bouChiWat.ports[1])
  connect(bouOut.ports[1], res.port_a)
  connect(res.port_b, VAV_1.port_Out)
  connect(VAV_1.port_Sup, res1.port_a)
  connect(res1.port_b, bouBui.ports[1])
  connect(bouBui.ports[2], pBui.port)
  connect(weaDat.weaBus, VAV_1.busWea)
  connect(busAHU, VAV_1.bus)
  connect(VAV_1.port_Rel, res2.port_a)
  connect(res2.port_b, bouOut.ports[2])
  connect(VAV_1.port_Ret, res3.port_b)
  connect(res3.port_a, bouBui.ports[3])
  connect(pBui.p, busAHU.pBui)
  connect(sigVAVBox.bus, VAV_1.busTer)

  connect(sigBAS.busTer, VAV_1.busTer)
  connect(sigZon.bus, VAV_1.busTer)
end VAVMultiZone;


Package with configured models

within Buildings.Templates.AirHandlersFans.Validation;
package UserProject "Package with configured models"
  extends Modelica.Icons.VariantsPackage;
end UserProject;


Emulation of VAV box control points. This class generates signals typically provided by the terminal
unit controller.
It is aimed for validation purposes only.

within Buildings.Templates.AirHandlersFans.Validation.UserProject;
block VAVBoxControlPoints "Emulation of VAV box control points"
  extends Modelica.Blocks.Icons.Block;

  parameter Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard stdVen
    "Ventilation standard"

  Buildings.Templates.ZoneEquipment.Interfaces.Bus bus
    "Terminal unit control bus"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant tNexOcc(final k=3600)
    "Time next occupancy"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant VAirDis_flow(final k=1)
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant yReqZonTemRes(final k=1)
    "Request"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant yReqZonPreRes(final k=1)
    "Request"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TAirDis(final k=303.15)
    "Discharge temperature"

  Controls.OBC.CDL.Integers.Sources.Constant uOpeMod(
    k=Buildings.Controls.OBC.ASHRAE.G36.Types.OperationModes.occupied)
    "Operating mode"
  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.ZoneStatus sta
    "Evaluate zone temperature status"
  Controls.OBC.CDL.Reals.Sources.Constant cooDowTim(final k=1800)
                  "Cooling down time"
  Controls.OBC.CDL.Reals.Sources.Constant warUpTim(final k=1800)
                  "Warm-up time"
  Controls.OBC.ASHRAE.G36.VentilationZones.Title24.Setpoints setMinOA_T24(
    VOccMin_flow=2.5e-3,
    VAreMin_flow=3e-3,
    VMin_flow=5e-3) if stdVen==
    Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.California_Title_24
    "Zone level calculation of the minimum outdoor airflow setpoint"
  Buildings.Controls.OBC.ASHRAE.G36.VentilationZones.ASHRAE62_1.Setpoints setMinOA_62_1(
    VAreBreZon_flow=3e-3,
    VPopBreZon_flow=2.5e-3,
    VMin_flow=5.5e-3) if stdVen==
    Buildings.Controls.OBC.ASHRAE.G36.Types.VentilationStandard.ASHRAE62_1
    "Zone level calculation of the minimum outdoor airflow setpoint"
equation
  connect(tNexOcc.y, bus.tNexOcc);
  connect(TAirDis.y, bus.TAirDis);
  connect(VAirDis_flow.y, bus.VAirDis_flow);
  connect(yReqZonTemRes.y, bus.yReqZonTemRes);
  connect(yReqZonPreRes.y, bus.yReqZonPreRes);

  connect(bus.y1Win, setMinOA_62_1.u1Win);
  connect(bus.TZon, setMinOA_62_1.TZon);
  connect(bus.TAirDis, setMinOA_62_1.TDis);

  connect(setMinOA_62_1.VAdjPopBreZon_flow, bus.VAdjPopBreZon_flow);
  connect(setMinOA_62_1.VOccZonMin_flow, bus.VOccZonMin_flow);
  connect(setMinOA_62_1.VAdjAreBreZon_flow, bus.VAdjAreBreZon_flow);
  connect(setMinOA_62_1.VMinOA_flow, bus.VMinOA_flow);

  connect(setMinOA_T24.VZonAbsMin_flow, bus.VZonAbsMin_flow);
  connect(setMinOA_T24.VZonDesMin_flow, bus.VZonDesMin_flow);
  connect(setMinOA_T24.VOccZonMin_flow, bus.VOccZonMin_flow);
  connect(setMinOA_T24.yCO2, bus.yCO2);
  connect(setMinOA_T24.VMinOA_flow, bus.VMinOA_flow);

  connect(cooDowTim.y, sta.cooDowTim);
  connect(warUpTim.y, sta.warUpTim);
  connect(bus.u1Win, sta.u1Win);
  connect(bus.TZon, sta.TZon);
  connect(bus.TZonHeaOccSet, sta.TOccHeaSet);
  connect(bus.TZonCooOccSet, sta.TOccCooSet);
  connect(bus.TZonHeaUnoSet, sta.TUnoHeaSet);
  connect(bus.TZonCooUnoSet, sta.TUnoCooSet);

  connect(sta.yCooTim, bus.yCooTim);
  connect(sta.yWarTim, bus.yWarTim);
  connect(sta.yOccHeaHig, bus.yOccHeaHig);
  connect(sta.yHigOccCoo, bus.yHigOccCoo);
  connect(sta.yUnoHeaHig, bus.yUnoHeaHig);
  connect(sta.yEndSetBac, bus.yEndSetBac);
  connect(sta.yHigUnoCoo, bus.yHigUnoCoo);
  connect(sta.yEndSetUp, bus.yEndSetUp);

  connect(uOpeMod.y, setMinOA_62_1.uOpeMod)
end VAVBoxControlPoints;


within Buildings.Templates.AirHandlersFans.Validation.UserProject;
package Data "Package with classes for storing system parameters"
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Package with component models

within Buildings.Templates;
package Components "Package with component models"
  extends Modelica.Icons.VariantsPackage;
end Components;


Package with type definitions

within Buildings.Templates.Components;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;
  type Chiller = enumeration(
      AirCooled
      "Air-cooled compression chiller",
      None
      "No chiller",
      WaterCooled
      "Water-cooled compression chiller")
    "Enumeration to specify the type of chiller";
  type Coil = enumeration(
      ElectricHeating
      "Modulating electric heating coil",
      EvaporatorMultiStage
      "Evaporator coil with multi-stage compressor",
      EvaporatorVariableSpeed
      "Evaporator coil with variable speed compressor",
      None
      "No coil",
      WaterBasedCooling
      "Chilled water coil",
      WaterBasedHeating
      "Hot water coil")
    "Enumeration to configure the coil";
  type Cooler = enumeration(
      None
      "No external cooler (typically for air-cooled chillers)",
      CoolingTowerClosed
      "Closed-circuit cooling tower",
      CoolingTowerOpen
      "Open-circuit cooling tower",
      DryCooler
      "Dry cooler")
    "Enumeration to configure the condenser water cooling equipment";
  type Damper = enumeration(
      Modulating
      "Modulating damper",
      None
      "No damper",
      PressureIndependent
      "Pressure independent damper",
      TwoPosition
      "Two-position damper")
    "Enumeration to configure the damper";
  type DamperBlades = enumeration(
      Opposed
      "Opposed blades",
      Parallel
      "Parallel blades",
      VAV
      "VAV damper")
    "Enumeration to specify the type of damper blades";
  type Fan = enumeration(
      None
      "No fan",
      SingleConstant
      "Single fan - Constant speed",
      SingleVariable
      "Single fan - Variable speed",
      ArrayVariable
      "Fan array - Variable speed")
    "Enumeration to configure the fan";
  type FanSingle = enumeration(
      Housed
      "Housed centrifugal fan",
      Plug
      "Plug fan",
      Propeller
      "Propeller fan")
    "Enumeration to specify the type of single fan";
  type HeatPump = enumeration(
      AirToWater
      "Air-to-water heat pump",
      WaterToWater
      "Water(or brine)-to-water heat pump")
    "Enumeration to specify the type of heat pump";
  type HeatPumpModel = enumeration(
      EquationFit
      "Heat pump model based on the equation fit method")
    "Enumeration to specify the heat pump model";
  type IntegrationPoint = enumeration(
      None
      "None",
      Return
      "Return side",
      Supply
      "Supply side") "Enumeration to specify the integration point of equipment";
  type Pump = enumeration(
      None
      "No pump",
      Single
      "Single pump",
      Multiple
      "Multiple pumps in parallel")
    "Enumeration to configure the pump";
  type PumpArrangement = enumeration(
      Dedicated "Dedicated pumps",
      Headered "Headered pumps") "Enumeration to specify the pump arrangement";
  type Sensor = enumeration(
      DifferentialPressure
      "Differential pressure",
      HumidityRatio
      "Humidity ratio",
      PPM
      "PPM",
      RelativeHumidity
      "Relative humidity",
      SpecificEnthalpy
      "Specific enthalpy",
      Temperature
      "Temperature",
      VolumeFlowRate
      "Volume flow rate")
    "Enumeration to configure the sensor";
  type SensorTemperature = enumeration(
      Standard
      "Standard sensor",
      Averaging
      "Averaging sensor",
      InWell
      "Sensor in well")
    "Enumeration to specify the type of temperature sensor";
  type SensorVolumeFlowRate = enumeration(
      AFMS
      "Airflow measuring station",
      FlowCross
      "Flow cross",
      FlowMeter
      "Flow meter")
    "Enumeration to specify the type of volume flow rate sensor";
  // RFE: Add support for PICV.
  type Valve = enumeration(
      None
      "No valve",
      ThreeWayModulating
      "Three-way modulating valve",
      ThreeWayTwoPosition
      "Three-way two-position valve",
      TwoWayModulating
      "Two-way modulating valve",
      TwoWayTwoPosition
      "Two-way two-position valve")
    "Enumeration to configure the valve";
  type ValveCharacteristicTwoWay = enumeration(
      EqualPercentage
      "Equal percentage",
      Linear
      "Linear",
      PressureIndependent
      "Pressure independent (mass flow rate only dependent of input signal)",
      Table
      "Table-specified")
    "Enumeration to specify the characteristic of two-way valves"
  type ValveCharacteristicThreeWay = enumeration(
      EqualPercentageLinear
      "Equal percentage (direct) and linear (bypass)",
      Linear
      "Linear (both direct and bypass)",
      Table
      "Table-specified (both direct and bypass)")
    "Enumeration to specify the characteristic of the bypass valve"
end Types;