Interface class for heat pump plant

within Buildings.Templates.Plants.HeatPumps.Interfaces;
partial model PartialHeatPumpPlant
  "Interface class for heat pump plant"
  replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "HW medium"
  replaceable package MediumHotWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "DHW medium"
  replaceable package MediumChiWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "CHW medium"
  /*
  Derived classes representing AWHP shall use:
  redeclare final package MediumSou = MediumAir
  */
  replaceable package MediumSou=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Source-side medium"
  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium"
  // The current implementation only supports plants that provide HHW.
  final parameter Boolean have_heaWat=true
    "Set to true if the plant provides HW"
  parameter Boolean have_chiWat=true
    "Set to true if the plant provides CHW"
  // RFE: To be exposed for templates that include optional DHW service.
  final parameter Boolean have_hotWat=false
    "Set to true if the plant provides DHW"
  parameter Boolean have_hrc_select(
    start=false)=false
    "Set to true for plants with a sidestream heat recovery chiller"
  final parameter Boolean have_hrc=if have_heaWat and have_chiWat then have_hrc_select
    else false
    "Set to true for plants with sidestream heat recovery chiller"
  parameter Buildings.Templates.Components.Types.HeatPump typ
    "Type of heat pump"
  parameter Buildings.Templates.Plants.HeatPumps.Configuration.HeatPumpPlant cfg(
    final cpChiWat_default=cpChiWat_default,
    final cpHeaWat_default=cpHeaWat_default,
    final cpSou_default=cpSou_default,
    final have_chiWat=have_chiWat,
    final have_heaWat=have_heaWat,
    final have_hrc=have_hrc,
    final have_hotWat=have_hotWat,
    final have_pumHeaWatPriVar=have_pumHeaWatPriVar,
    final have_pumChiWatPriVar=have_pumChiWatPriVar,
    final have_pumChiWatPriDed=have_pumChiWatPriDed,
    final have_valChiWatMinByp=have_valChiWatMinByp,
    final have_valHeaWatMinByp=have_valHeaWatMinByp,
    final have_valHpInlIso=have_valHpInlIso,
    final have_valHpOutIso=have_valHpOutIso,
    final is_rev=is_rev,
    final nHp=nHp,
    final nPumChiWatPri=nPumChiWatPri,
    final nPumChiWatSec=nPumChiWatSec,
    final nPumHeaWatPri=nPumHeaWatPri,
    final nPumHeaWatSec=nPumHeaWatSec,
    final rhoChiWat_default=rhoChiWat_default,
    final rhoHeaWat_default=rhoHeaWat_default,
    final rhoSou_default=rhoSou_default,
    final typ=typ,
    final typArrPumPri=typArrPumPri,
    final typDis=typDis,
    final typPumChiWatPri=typPumChiWatPri,
    final typPumHeaWatPri=typPumHeaWatPri,
    final typPumChiWatSec=typPumChiWatSec,
    final typPumHeaWatSec=typPumHeaWatSec,
    final typTanChiWat=typTanChiWat,
    final typTanHeaWat=typTanHeaWat,
    final typCtl=ctl.typ,
    final nAirHan=ctl.nAirHan,
    final nEquZon=ctl.nEquZon,
    final have_senDpHeaWatRemWir=ctl.have_senDpHeaWatRemWir,
    final nSenDpHeaWatRem=ctl.nSenDpHeaWatRem,
    final have_senDpChiWatRemWir=ctl.have_senDpChiWatRemWir,
    final nSenDpChiWatRem=ctl.nSenDpChiWatRem,
    final have_inpSch=ctl.have_inpSch)
    "Configuration parameters"
  parameter Buildings.Templates.Plants.HeatPumps.Data.HeatPumpPlant dat(
    cfg=cfg)
    "Design and operating parameters"
  // RFE(AntoineGautier): Allow specifying subset of units dedicated to HW, CHW or DHW production.
  parameter Integer nHp(
    final min=1,
    start=1)
    "Total number of heat pumps"
  parameter Boolean is_rev
    "Set to true for reversible heat pumps, false for heating only"
  // Plants with AWHP.
  parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis_select1(
    start=Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)=
    Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    "Type of distribution system"
  // Plants with WWHP.
  parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis_select2(
    start=Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2)
    "Type of distribution system"
  final parameter Buildings.Templates.Plants.HeatPumps.Types.Distribution typDis=
    if typ == Buildings.Templates.Components.Types.HeatPump.AirToWater then typDis_select1
    else typDis_select2
    "Type of distribution system"
  final parameter Boolean have_valHpInlIso=if not have_chiWat and typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Dedicated then false
    else true
    "Set to true for isolation valves at HP inlet"
  final parameter Boolean have_valHpOutIso=if not have_chiWat and typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Dedicated then false
    elseif nHp == 1 then false elseif have_pumChiWatPriDed then false else true
    "Set to true for isolation valves at HP outlet"
  parameter Buildings.Templates.Components.Types.PumpArrangement typArrPumPri=
    Buildings.Templates.Components.Types.PumpArrangement.Dedicated
    "Type of primary pump arrangement"
  final parameter Boolean have_bypHeaWatFix=
    have_heaWat and (
    typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2)
    "Set to true if the HW loop has a fixed bypass"
  final parameter Boolean have_valHeaWatMinByp=have_heaWat and
    typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only
    "Set to true if the HW loop has a minimum flow bypass valve"
  // Constant primary - variable secondary plants.
  parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri_select1(
    start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)=
    Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable
    "Type of primary HW pumps"
  // Constant primary-only plants and variable primary plants require variable speed pumps.
  final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumHeaWatPri=
    if have_heaWat then (
      if typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
      then typPumHeaWatPri_select1 else Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)
    else Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None
    "Type of primary HW pumps"
  final parameter Boolean have_pumHeaWatPriVar=
    typPumHeaWatPri == Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable
    "Set to true for variable speed primary HW pumps"
  parameter Integer nPumHeaWatPri_select(
    final min=0,
    start=0)=nHp
    "Number of primary HW pumps"
  final parameter Integer nPumHeaWatPri=if have_heaWat then (if typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Headered then nPumHeaWatPri_select
    else nHp) else 0
    "Number of primary HW pumps"
  parameter Buildings.Templates.Components.Types.IntegrationPoint typTanHeaWat_select(
    start=Buildings.Templates.Components.Types.IntegrationPoint.None)=
    Buildings.Templates.Components.Types.IntegrationPoint.Supply
    "Specify if there is a HW buffer tank and where it is integrated into the system"
  final parameter Buildings.Templates.Components.Types.IntegrationPoint typTanHeaWat=
    if have_heaWat then typTanHeaWat_select
    else Buildings.Templates.Components.Types.IntegrationPoint.None
    "Specify if there is a HW buffer tank and where it is integrated into the system"
  // RFE: Only centralized secondary HW pumps are currently supported for primary-secondary plants.
  final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumHeaWatSec=
    if have_heaWat and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2)
    then Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    else Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Type of secondary HW pumps"
  // Primary-secondary plants.
  parameter Integer nPumHeaWatSec_select(
    final min=0)=nHp
    "Number of secondary HW pumps"
  final parameter Integer nPumHeaWatSec(
    final min=0)=if not have_heaWat or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only
    then 0 else nPumHeaWatSec_select
    "Number of secondary HW pumps"
  // Plants with dedicated primary pumps.
  parameter Boolean have_pumChiWatPriDed_select(
    start=false)=false
    "Set to true for plants with separate dedicated primary CHW pumps"
  final parameter Boolean have_pumChiWatPriDed=if have_chiWat and typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Dedicated then have_pumChiWatPriDed_select
    else false
    "Set to true for plants with separate dedicated primary CHW pumps"
  final parameter Boolean have_bypChiWatFix=
    have_chiWat and (
    typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2)
    "Set to true if the CHW loop has a fixed bypass"
  final parameter Boolean have_valChiWatMinByp=have_chiWat and
    typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only
    "Set to true if the CHW loop has a minimum flow bypass valve"
  // Constant primary - variable secondary plants with separate dedicated primary CHW pumps or headered primary pumps.
  parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri_select1(
    start=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)=
    typPumHeaWatPri
    "Type of primary CHW pumps"
  // Constant primary-only plants and variable primary plants require variable speed pumps.
  final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary typPumChiWatPri=
    if have_pumChiWatPriDed
      or have_chiWat and typArrPumPri==Buildings.Templates.Components.Types.PumpArrangement.Headered
    then (if typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    then typPumChiWatPri_select1 else  Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable)
    else Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.None
    "Type of primary CHW pumps"
  final parameter Boolean have_pumChiWatPriVar=
    typPumChiWatPri == Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Variable
    "Set to true for variable speed primary CHW pumps"
  // Plants with headered primary CHW pumps.
  parameter Integer nPumChiWatPri_select(
    final min=0,
    start=0)=nHp
    "Number of primary CHW pumps"
  final parameter Integer nPumChiWatPri=if have_chiWat and typArrPumPri ==
    Buildings.Templates.Components.Types.PumpArrangement.Headered then nPumChiWatPri_select
    elseif have_pumChiWatPriDed then nHp else 0
    "Number of primary CHW pumps"
  parameter Buildings.Templates.Components.Types.IntegrationPoint typTanChiWat_select(
    start=Buildings.Templates.Components.Types.IntegrationPoint.None)=
    Buildings.Templates.Components.Types.IntegrationPoint.Return
    "Specify if there is a CHW buffer tank and where it is integrated into the system"
  final parameter Buildings.Templates.Components.Types.IntegrationPoint typTanChiWat=
    if have_chiWat then typTanChiWat_select
    else Buildings.Templates.Components.Types.IntegrationPoint.None
    "Specify if there is a CHW buffer tank and where it is integrated into the system"
  // RFE: Currently, only centralized secondary CHW pumps are supported for primary-secondary plants.
  final parameter Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary typPumChiWatSec=
    if have_chiWat and (typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Constant1Variable2
    or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1And2)
    then Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.Centralized
    else Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    "Type of secondary CHW pumps"
  parameter Integer nPumChiWatSec_select(
    final min=0)=nHp
    "Number of secondary CHW pumps"
  final parameter Integer nPumChiWatSec(
    final min=0)=if not have_chiWat or typDis == Buildings.Templates.Plants.HeatPumps.Types.Distribution.Variable1Only
    then 0 else nPumChiWatSec_select
    "Number of secondary CHW pumps"
  // Design and operating parameters.
  final parameter Modelica.Units.SI.MassFlowRate mHeaWatPri_flow_nominal=if have_heaWat
    then dat.hp.mHeaWatHp_flow_nominal * nHp else 0
    "Primary HW mass flow rate"
  final parameter Modelica.Units.SI.MassFlowRate mHeaWat_flow_nominal=if have_heaWat
    then (if typPumHeaWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    then mHeaWatPri_flow_nominal else sum(dat.pumHeaWatSec.m_flow_nominal)) else 0
    "HW mass flow rate (total, distributed to consumers)"
  final parameter Modelica.Units.SI.HeatFlowRate capHea_nominal=if have_heaWat
    then abs(dat.hp.capHeaHp_nominal) * nHp else 0
    "Heating capacity - All units";
  final parameter Modelica.Units.SI.HeatFlowRate QHea_flow_nominal=
    capHea_nominal
    "Heating heat flow rate - All units";
  final parameter Modelica.Units.SI.Temperature THeaWatSup_nominal=dat.ctl.THeaWatSup_nominal
    "Maximum HW supply temperature";
  final parameter Modelica.Units.SI.Temperature THeaWatRet_nominal=
    THeaWatSup_nominal - QHea_flow_nominal / cpHeaWat_default /
    mHeaWat_flow_nominal
    "HW return temperature";
  final parameter Modelica.Units.SI.MassFlowRate mChiWatPri_flow_nominal=if have_chiWat
    then dat.hp.mChiWatHp_flow_nominal * nHp else 0
    "Primary CHW mass flow rate"
  final parameter Modelica.Units.SI.MassFlowRate mChiWat_flow_nominal=if have_chiWat
    then (if typPumChiWatSec == Buildings.Templates.Plants.HeatPumps.Types.PumpsSecondary.None
    then mChiWatPri_flow_nominal else sum(dat.pumChiWatSec.m_flow_nominal)) else 0
    "CHW mass flow rate - Total, distributed to consumers"
  final parameter Modelica.Units.SI.HeatFlowRate capCoo_nominal=if have_chiWat
    then abs(dat.hp.capCooHp_nominal) * nHp else 0
    "Cooling capacity - All units";
  final parameter Modelica.Units.SI.HeatFlowRate QCoo_flow_nominal=-
    capCoo_nominal
    "Cooling heat flow rate - All units";
  final parameter Modelica.Units.SI.Temperature TChiWatSup_nominal=dat.ctl.TChiWatSup_nominal
    "Minimum CHW supply temperature";
  final parameter Modelica.Units.SI.Temperature TChiWatRet_nominal=if is_rev
    then TChiWatSup_nominal - QCoo_flow_nominal / cpChiWat_default /
    mChiWat_flow_nominal else Buildings.Templates.Data.Defaults.TChiWatRet
    "CHW return temperature - Each heat pump"
  final parameter Modelica.Units.SI.Temperature TSouHea_nominal=dat.hp.TSouHeaHp_nominal
    "OAT or source fluid supply temperature (evaporator entering) in heating mode - Each heat pump";
  final parameter Modelica.Units.SI.Temperature TSouCoo_nominal=dat.hp.TSouCooHp_nominal
    "OAT or source fluid supply temperature (evaporator entering) in cooling mode - Each heat pump";
  // Dynamics and miscellaneous parameters.
  final parameter Modelica.Fluid.Types.Dynamics energyDynamics=
    Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  parameter Boolean allowFlowReversal=true
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)"
  parameter Boolean linearized = false
    "= true, use linear relation between m_flow and dp for all valves"
  parameter Boolean show_T=false
    "= true, if actual temperature at port is computed"
  final parameter MediumHeaWat.Density rhoHeaWat_default=MediumHeaWat.density(staHeaWat_default)
    "HW default density"
  final parameter MediumHeaWat.SpecificHeatCapacity cpHeaWat_default=
    MediumHeaWat.specificHeatCapacityCp(staHeaWat_default)
    "HW default specific heat capacity"
  final parameter MediumHeaWat.ThermodynamicState staHeaWat_default=MediumHeaWat.setState_pTX(
    T=THeaWatSup_nominal,
    p=MediumHeaWat.p_default,
    X=MediumHeaWat.X_default)
    "HW default state"
  final parameter MediumChiWat.Density rhoChiWat_default=MediumChiWat.density(staChiWat_default)
    "CHW default density"
  final parameter MediumChiWat.SpecificHeatCapacity cpChiWat_default=
    MediumChiWat.specificHeatCapacityCp(staChiWat_default)
    "CHW default specific heat capacity"
  final parameter MediumChiWat.ThermodynamicState staChiWat_default=MediumChiWat.setState_pTX(
    T=TChiWatSup_nominal,
    p=MediumChiWat.p_default,
    X=MediumChiWat.X_default)
    "CHW default state"
  /*
  Source fluid default state = heating mode:
  - Impact of difference between TSouHea_nominal and TSouCoo_nominal on cp is about 0.5 %.
  - Impact of difference between TSouHea_nominal and TSouCoo_nominal on rho is about 2 %,
    with rhoSouHea_nominal > rhoSouCoo_nominal, so conservative for pump sizing.
  */
  final parameter MediumSou.Density rhoSou_default=MediumSou.density(staSou_default)
    "Source fluid default density"
  final parameter MediumSou.SpecificHeatCapacity cpSou_default=MediumSou.specificHeatCapacityCp(staSou_default)
    "Source fluid default specific heat capacity"
  final parameter MediumSou.ThermodynamicState staSou_default=MediumSou.setState_pTX(
    T=TSouHea_nominal,
    p=MediumSou.p_default,
    X=MediumSou.X_default)
    "Source fluid default state"
  Modelica.Fluid.Interfaces.FluidPort_a port_aHeaWat(
    redeclare final package Medium=MediumHeaWat,
    m_flow(
      final min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    h_outflow(
      start=MediumHeaWat.h_default,
      nominal=MediumHeaWat.h_default))
    if have_heaWat
    "HW return"
  Modelica.Fluid.Interfaces.FluidPort_b port_bHeaWat(
    redeclare final package Medium=MediumHeaWat,
    m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    h_outflow(
      start=MediumHeaWat.h_default,
      nominal=MediumHeaWat.h_default))
    if have_heaWat
    "HW supply"
  Modelica.Fluid.Interfaces.FluidPort_a port_aChiWat(
    redeclare final package Medium=MediumChiWat,
    m_flow(
      final min=if allowFlowReversal then - Modelica.Constants.inf else 0),
    h_outflow(
      start=MediumChiWat.h_default,
      nominal=MediumChiWat.h_default))
    if have_chiWat
    "CHW return"
  Modelica.Fluid.Interfaces.FluidPort_b port_bChiWat(
    redeclare final package Medium=MediumChiWat,
    m_flow(
      max=if allowFlowReversal then + Modelica.Constants.inf else 0),
    h_outflow(
      start=MediumChiWat.h_default,
      nominal=MediumChiWat.h_default))
    if have_chiWat
    "CHW supply"
  Buildings.Templates.Plants.HeatPumps.Interfaces.Bus bus
    "Plant control bus"
  Buildings.Templates.AirHandlersFans.Interfaces.Bus busAirHan[cfg.nAirHan]
    if cfg.nAirHan > 0
    "Air handling unit control bus"
  Buildings.Templates.ZoneEquipment.Interfaces.Bus busEquZon[cfg.nEquZon]
    if cfg.nEquZon > 0
    "Terminal unit control bus"
  BoundaryConditions.WeatherData.Bus busWea
    "Weather bus"
  replaceable Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController ctl
    constrainedby
    Buildings.Templates.Plants.HeatPumps.Components.Interfaces.PartialController(
      final cfg=cfg,
      final dat=dat.ctl)
    "Plant controller"
  // Miscellaneous
  Buildings.Fluid.Sources.Outside out(
    redeclare replaceable package Medium=Buildings.Media.Air,
    nPorts=1)
    "Outdoor air conditions"
  Buildings.Fluid.Sensors.Temperature TOut(
    redeclare replaceable package Medium=Buildings.Media.Air,
    warnAboutOnePortConnection=false)
    "OA temperature"
initial equation
  if typArrPumPri == Buildings.Templates.Components.Types.PumpArrangement.Dedicated then
    assert(nPumHeaWatPri == nHp, "In " + getInstanceName() + ": " +
      "In case of dedicated primary HW pumps, the number pumps (=" + String(nPumHeaWatPri) +
      ") must be equal to the number of heat pumps (=" + String(nHp) + ").");
  end if;
  if have_pumChiWatPriDed then
    assert(nPumChiWatPri == nHp, "In " + getInstanceName() + ": " +
      "In case of separate dedicated primary CHW pumps, the number pumps (=" +
      String(nPumChiWatPri) + ") must be equal to the number of heat pumps (=" +
      String(nHp) + ").");
  end if;
equation
  /* Control point connection - start */
                                         connect(TOut.T, bus.TOut);
  /* Control point connection - stop */
                                       connect(bus, ctl.bus)
  connect(ctl.busAirHan, busAirHan)
  connect(ctl.busEquZon, busEquZon)
  connect(busWea, out.weaBus)
  connect(out.ports[1], TOut.port)
end PartialHeatPumpPlant;


Validation of AWHP plant template

within Buildings.Templates.Plants.HeatPumps.Validation;
model AirToWater
  "Validation of AWHP plant template"
  extends Modelica.Icons.Example;
  replaceable package Medium=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Main medium (common for CHW and HW)";
  parameter Boolean have_chiWat=true
    "Set to true if the plant provides CHW"
  inner parameter UserProject.Data.AllSystems datAll(
    pla(
      final cfg=pla.cfg))
    "Plant parameters"
  parameter Boolean allowFlowReversal=true
    "= true to allow flow reversal, false restricts to design direction (port_a -> port_b)"
  parameter Modelica.Fluid.Types.Dynamics energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial
    "Type of energy balance: dynamic (3 initialization options) or steady state"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=Modelica.Utilities.Files.loadResource(
      "modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"))
    "Outdoor conditions"
  Fluid.HeatExchangers.SensibleCooler_T loaHeaWat(
    redeclare final package Medium=Medium,
    final m_flow_nominal=pla.mHeaWat_flow_nominal,
    show_T=true,
    final dp_nominal=0,
    final energyDynamics=energyDynamics,
    tau=300,
    QMin_flow=- pla.capHea_nominal)
    "HW system approximated by prescribed return temperature"
  Fluid.HeatExchangers.Heater_T loaChiWat(
    redeclare final package Medium=Medium,
    final m_flow_nominal=pla.mChiWat_flow_nominal,
    show_T=true,
    final dp_nominal=0,
    final energyDynamics=energyDynamics,
    tau=300,
    QMax_flow=pla.capCoo_nominal)
    if have_chiWat
    "CHW system system approximated by prescribed return temperature"
  Fluid.Actuators.Valves.TwoWayEqualPercentage valDisHeaWat(
    redeclare final package Medium=Medium,
    m_flow_nominal=pla.mHeaWat_flow_nominal,
    dpValve_nominal=3E4,
    dpFixed_nominal=datAll.pla.ctl.dpHeaWatRemSet_max[1] - 3E4)
    "Distribution system approximated by variable flow resistance"
  Fluid.Actuators.Valves.TwoWayEqualPercentage valDisChiWat(
    redeclare final package Medium=Medium,
    m_flow_nominal=pla.mChiWat_flow_nominal,
    dpValve_nominal=3E4,
    dpFixed_nominal=datAll.pla.ctl.dpChiWatRemSet_max[1] - 3E4)
    if have_chiWat
    "Distribution system approximated by variable flow resistance"
  Buildings.Templates.Plants.HeatPumps.AirToWater pla(
    redeclare final package MediumHeaWat=Medium,
    have_hrc_select=true,
    final dat=datAll.pla,
    final have_chiWat=have_chiWat,
    nHp=3,
    typPumHeaWatPri_select1=Buildings.Templates.Plants.HeatPumps.Types.PumpsPrimary.Constant,
    final allowFlowReversal=allowFlowReversal,
    linearized=true,
    show_T=true,
    ctl(
      nAirHan=1,
      nEquZon=0),
    is_dpBalYPumSetCal=true)
    "Heat pump plant"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TDum(
    k=293.15,
    y(final unit="K",
      displayUnit="degC"))
    "Placeholder signal for request generator"
  Fluid.Sensors.RelativePressure dpHeaWatRem[1](
    redeclare each final package Medium=Medium)
    "HW differential pressure at one remote location"
  Fluid.Sensors.RelativePressure dpChiWatRem[1](
    redeclare each final package Medium=Medium)
    if have_chiWat
    "CHW differential pressure at one remote location"
  Buildings.Controls.OBC.ASHRAE.G36.AHUs.MultiZone.VAV.SetPoints.PlantRequests reqPlaRes(
    final heaCoi=Buildings.Controls.OBC.ASHRAE.G36.Types.HeatingCoil.WaterBased,
    final cooCoi=if have_chiWat then Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.WaterBased
      else Buildings.Controls.OBC.ASHRAE.G36.Types.CoolingCoil.None)
    "Plant and reset request"
  AirHandlersFans.Interfaces.Bus busAirHan
    "AHU control bus"
  Interfaces.Bus busPla
    "Plant control bus"
  Buildings.Controls.OBC.CDL.Reals.Sources.TimeTable ratFlo(
    table=[
      0, 0, 0;
      5, 0, 0;
      7, 1, 0;
      12, 0.2, 0.2;
      16, 0, 1;
      22, 0.1, 0.1;
      24, 0, 0],
    timeScale=3600)
    "Source signal for flow rate ratio – Index 1 for HW, 2 for CHW"
  Buildings.Controls.OBC.CDL.Reals.PID ctlEquZon[if have_chiWat then 2 else 1](
    each k=0.1,
    each Ti=60,
    each final reverseActing=true)
    "Zone equipment controller"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter norFlo[if have_chiWat
    then 2 else 1](
    k=if have_chiWat then {1 / pla.mHeaWat_flow_nominal, 1 / pla.mChiWat_flow_nominal}
      else {1 / pla.mHeaWat_flow_nominal})
    "Normalize flow rate"
  Fluid.Sensors.MassFlowRate mChiWat_flow(
    redeclare final package Medium=Medium)
    if have_chiWat
    "CHW mass flow rate"
  Fluid.Sensors.MassFlowRate mHeaWat_flow(
    redeclare final package Medium=Medium)
    "HW mass flow rate"
  Buildings.Controls.OBC.CDL.Reals.AddParameter TChiWatRet(
    p=pla.TChiWatRet_nominal - pla.TChiWatSup_nominal)
    if have_chiWat
    "Prescribed CHW return temperature"
  Buildings.Controls.OBC.CDL.Reals.AddParameter THeaWatRet(
    p=pla.THeaWatRet_nominal - pla.THeaWatSup_nominal)
    "Prescribed HW return temperature"
  Buildings.Controls.OBC.CDL.Reals.Max max2
    "Limit prescribed HWRT"
  Buildings.Controls.OBC.CDL.Reals.Min min1
    if have_chiWat
    "Limit prescribed CHWRT"
  Buildings.Controls.OBC.CDL.Integers.Multiply mulInt[4]
    "Importance multiplier"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant cst[4](
    each k=10)
    "Constant"
  Buildings.Fluid.FixedResistances.PressureDrop pipHeaWat(
    redeclare final package Medium=Medium,
    final m_flow_nominal=pla.mHeaWat_flow_nominal,
    final dp_nominal=Buildings.Templates.Data.Defaults.dpHeaWatLocSet_max - max(datAll.pla.ctl.dpHeaWatRemSet_max))
    "Piping"
  Buildings.Fluid.FixedResistances.PressureDrop pipChiWat(
    redeclare final package Medium=Medium,
    final m_flow_nominal=pla.mChiWat_flow_nominal,
    final dp_nominal=Buildings.Templates.Data.Defaults.dpChiWatLocSet_max - max(datAll.pla.ctl.dpChiWatRemSet_max))
    if have_chiWat
    "Piping"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con(
    k=293.15)
    "Constant limiting prescribed return temperature"
  Controls.Utilities.PlaceholderInteger ph[2](
    each final have_inp=have_chiWat,
    each final u_internal=0)
    "Placeholder value"
equation
  if have_chiWat then
    connect(mulInt[3].y, busAirHan.reqResChiWat)
    connect(mulInt[4].y, busAirHan.reqPlaChiWat)
  end if;
  connect(weaDat.weaBus, pla.busWea)
  connect(pla.port_bChiWat, loaChiWat.port_a)
  connect(loaChiWat.port_b, valDisChiWat.port_a)
  connect(loaHeaWat.port_b, valDisHeaWat.port_a)
  connect(pla.port_bHeaWat, loaHeaWat.port_a)
  connect(loaChiWat.port_a, dpChiWatRem[1].port_a)
  connect(dpHeaWatRem[1].port_a, loaHeaWat.port_a)
  connect(TDum.y, reqPlaRes.TAirSup)
  connect(TDum.y, reqPlaRes.TAirSupSet)
  connect(busAirHan, pla.busAirHan[1])
  connect(pla.bus, busPla)
  connect(valDisChiWat.y_actual, reqPlaRes.uCooCoiSet)
  connect(valDisHeaWat.y_actual, reqPlaRes.uHeaCoiSet)
  connect(valDisChiWat.port_b, mChiWat_flow.port_a)
  connect(mChiWat_flow.port_b, dpChiWatRem[1].port_b)
  connect(valDisHeaWat.port_b, mHeaWat_flow.port_a)
  connect(mHeaWat_flow.port_b, dpHeaWatRem[1].port_b)
  connect(mHeaWat_flow.m_flow, norFlo[1].u)
  connect(mChiWat_flow.m_flow, norFlo[2].u)
  connect(norFlo.y, ctlEquZon.u_m)
  connect(ratFlo.y[1:(if have_chiWat then 2 else 1)], ctlEquZon.u_s)
  connect(ctlEquZon[2].y, valDisChiWat.y)
  connect(ctlEquZon[1].y, valDisHeaWat.y)
  connect(busPla.THeaWatPriSup, THeaWatRet.u)
  connect(busPla.TChiWatPriSup, TChiWatRet.u)
  connect(TChiWatRet.y, min1.u1)
  connect(min1.y, loaChiWat.TSet)
  connect(max2.y, loaHeaWat.TSet)
  connect(cst.y, mulInt.u1)
  connect(mulInt[1].y, busAirHan.reqResHeaWat)
  connect(mulInt[2].y, busAirHan.reqPlaHeaWat)
  connect(pipHeaWat.port_b, pla.port_aHeaWat)
  connect(pipChiWat.port_b, pla.port_aChiWat)
  connect(mChiWat_flow.port_b, pipChiWat.port_a)
  connect(mHeaWat_flow.port_b, pipHeaWat.port_a)
  connect(con.y, min1.u2)
  connect(con.y, max2.u1)
  connect(THeaWatRet.y, max2.u2)
  connect(reqPlaRes.yChiWatResReq, ph[1].u)
  connect(reqPlaRes.yChiPlaReq, ph[2].u)
  connect(reqPlaRes.yHotWatResReq, mulInt[1].u2)
  connect(reqPlaRes.yHotWatPlaReq, mulInt[2].u2)
  connect(ph[1].y, mulInt[3].u2)
  connect(ph[2].y, mulInt[4].u2)
  connect(dpChiWatRem.p_rel, busPla.dpChiWatRem)
  connect(dpHeaWatRem.p_rel, busPla.dpHeaWatRem)
end AirToWater;


Package with validation models

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


Package with configured models

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


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


Compute the design pressure drop of a balancing valve. Given the design mass flow rate, the design pressure drop
of all equipment in series, the pump parameters and the
pump speed, the function returns the pressure drop
of a balancing valve at design flow, so that the total
pressure drop is equal to the pump head.

within Buildings.Templates.Utilities;
function computeBalancingPressureDrop
  "Compute the design pressure drop of a balancing valve"
  extends Modelica.Icons.Function;
  input Modelica.Units.SI.MassFlowRate m_flow_nominal
    "Design mass flow rate (target)";
  input Modelica.Units.SI.PressureDifference dp_nominal
    "Pressure drop of equipment in series at design flow rate";
  input Buildings.Templates.Components.Data.PumpSingle datPum
    "Pump parameters";
  input Real r_N(unit="1")=1
    "Relative revolution, r_N=N/N_nominal";
  output Modelica.Units.SI.PressureDifference dpBal_nominal
    "Pressure drop of balancing valve at design flow rate";
protected
  Modelica.Units.SI.PressureDifference dpPum_nominal =
    Buildings.Fluid.Movers.BaseClasses.Characteristics.pressure(
    V_flow=m_flow_nominal / datPum.rho_default,
    r_N=r_N,
    d=Buildings.Utilities.Math.Functions.splineDerivatives(
      x=datPum.per.pressure.V_flow,
      y=datPum.per.pressure.dp),
    dpMax=max(datPum.per.pressure.dp),
    V_flow_max=max(datPum.per.pressure.V_flow),
    per=Buildings.Fluid.Movers.BaseClasses.Characteristics.flowParametersInternal(
      n=size(datPum.per.pressure.V_flow, 1),
      V_flow=datPum.per.pressure.V_flow,
      dp=datPum.per.pressure.dp))
    "Pump head at target design flow";
algorithm
  dpBal_nominal := dpPum_nominal - dp_nominal;
end computeBalancingPressureDrop;


Package with utility functions

within Buildings.Templates;
package Utilities "Package with utility functions"
  extends Modelica.Icons.Package;
end Utilities;


Zone equipment

within Buildings.Templates;
package ZoneEquipment "Zone equipment"
  extends Modelica.Icons.Package;
end ZoneEquipment;


Package with type definitions

within Buildings.Templates.ZoneEquipment;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;
  type Configuration = enumeration(
      DualDuct
      "Dual duct system",
      FanPowered
      "Fan-powered system",
      Induction
      "Induction system",
      VAVBoxCoolingOnly
      "VAV terminal unit cooling only",
      VAVBoxReheat
      "VAV terminal unit with reheat")
    "Enumeration to configure the terminal unit";
  type Controller = enumeration(
      G36VAVBoxCoolingOnly
      "Guideline 36 controller for VAV terminal unit cooling only",
      G36VAVBoxReheat
      "Guideline 36 controller for VAV terminal unit with reheat",
      OpenLoop
      "Open loop controller")
      "Enumeration to configure the terminal unit controller";
end Types;


VAV terminal unit cooling only.

within Buildings.Templates.ZoneEquipment;
model VAVBoxCoolingOnly "VAV terminal unit cooling only"
  extends Buildings.Templates.ZoneEquipment.Interfaces.VAVBox(
    final typ=Buildings.Templates.ZoneEquipment.Types.Configuration.VAVBoxCoolingOnly,
    redeclare final Buildings.Templates.Components.Coils.None coiHea,
    redeclare replaceable
      Buildings.Templates.ZoneEquipment.Components.Controls.G36VAVBoxCoolingOnly ctl
      "Guideline 36 controller for VAV terminal unit cooling only");
end VAVBoxCoolingOnly;


VAV terminal unit with reheat.

within Buildings.Templates.ZoneEquipment;
model VAVBoxReheat "VAV terminal unit with reheat"
  extends Buildings.Templates.ZoneEquipment.Interfaces.VAVBox(
    final typ=Buildings.Templates.ZoneEquipment.Types.Configuration.VAVBoxReheat,
    redeclare replaceable
      Buildings.Templates.ZoneEquipment.Components.Controls.G36VAVBoxReheat ctl
      "Guideline 36 controller for VAV terminal unit with reheat");
end VAVBoxReheat;


Package with component models

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


Guideline 36 controller for VAV terminal unit cooling only.

within Buildings.Templates.ZoneEquipment.Components.Controls;
block G36VAVBoxCoolingOnly
  "Guideline 36 controller for VAV terminal unit cooling only"
  extends
    Buildings.Templates.ZoneEquipment.Components.Interfaces.ControllerG36VAVBox(
    final typ=Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly);
end G36VAVBoxCoolingOnly;


Guideline 36 controller.

within Buildings.Templates.ZoneEquipment.Components.Controls;
block G36VAVBoxReheat
  "Guideline 36 controller"
  extends Buildings.Templates.ZoneEquipment.Components.Interfaces.ControllerG36VAVBox(
    final typ=Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat);
end G36VAVBoxReheat;


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

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

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

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yDamVAV(k=1)
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant yCoiHea(k=1)
equation
  /* Control point connection - start */
  connect(yDamVAV.y, bus.damVAV.y);
  connect(yCoiHea.y, bus.coiHea.y);
  /* Control point connection - end */
end OpenLoop;


<html>
<p>
All control blocks that form the control sequence of a system
are instantiated into one single class, a so-called control section.
This package contains such control sections.
</p>
</html>

within Buildings.Templates.ZoneEquipment.Components;
package Controls
  extends Modelica.Icons.VariantsPackage;
end Controls;


<html>
<p>
This package provides records for design and operating parameters.
</p>
</html>

within Buildings.Templates.ZoneEquipment.Components;
package Data
  extends Modelica.Icons.MaterialPropertiesPackage;
end Data;


Guideline 36 controller for VAV terminal unit.

within Buildings.Templates.ZoneEquipment.Components.Interfaces;
block ControllerG36VAVBox "Guideline 36 controller for VAV terminal unit"
  extends
    Buildings.Templates.ZoneEquipment.Components.Interfaces.PartialControllerVAVBox;

  parameter Boolean have_occSen=false
    "Set to true if the zone has occupancy sensor"

  parameter Boolean have_winSen=false
    "Set to true if the zone has window status sensor"

  final parameter Boolean have_hotWatCoi=
    coiHea.typ==Buildings.Templates.Components.Types.Coil.WaterBasedHeating
    "Set to true if the system has hot water coil";

  final parameter Modelica.Units.SI.VolumeFlowRate VAirCooSet_flow_max=
    dat.VAirCooSet_flow_max
    "Zone maximum cooling airflow setpoint";

  final parameter Modelica.Units.SI.VolumeFlowRate VAirSet_flow_min=
    dat.VAirSet_flow_min
    "Zone minimum airflow setpoint";

  final parameter Modelica.Units.SI.VolumeFlowRate VAirHeaSet_flow_max=
    dat.VAirHeaSet_flow_max
    "Zone maximum heating airflow setpoint";

  final parameter Modelica.Units.SI.VolumeFlowRate VAirHeaSet_flow_min=
    dat.VAirHeaSet_flow_min
    "Zone minimum heating airflow setpoint";

  final parameter Modelica.Units.SI.TemperatureDifference dTAirDisHea_max(
    displayUnit="K")=
    dat.dTAirDisHea_max
    "Zone maximum discharge air temperature above heating setpoint";

  final parameter Modelica.Units.SI.VolumeFlowRate VOutMinOcc_flow(
    final min=0,
    start=1)=dat.VOutMinOcc_flow
    "Zone minimum outdoor airflow for occupants"
  final parameter Modelica.Units.SI.VolumeFlowRate VOutMinAre_flow(
    final min=0,
    start=1)=dat.VOutMinAre_flow
    "Zone minimum outdoor airflow for building area"

  final parameter Real VOutAre_flow(
    final unit = "m3/s")=
    dat.VOutAre_flow
    "Outdoor air flow rate per unit area"

  final parameter Real VOutOcc_flow(
    final unit = "m3/s")=
    dat.VOutOcc_flow
    "Outdoor air flow rate per occupant"

  final parameter Real effAirDisHea=
    dat.effAirDisHea
    "Zone air distribution effectiveness during heating";

  final parameter Real effAirDisCoo=
     dat.effAirDisCoo
    "Zone air distribution effectiveness during cooling";

  Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.Reheat.Controller ctlReh(
    final venStd=stdVen,
    final have_winSen=have_winSen,
    final have_occSen=have_occSen,
    final have_CO2Sen=have_CO2Sen,
    final have_hotWatCoi=have_hotWatCoi,
    final VOccMin_flow=VOutMinOcc_flow,
    final VAreMin_flow=VOutMinAre_flow,
    final VAreBreZon_flow=VOutAre_flow,
    final VPopBreZon_flow=VOutOcc_flow,
    final VMin_flow=VAirSet_flow_min,
    final VCooMax_flow=VAirCooSet_flow_max,
    final VHeaMin_flow=VAirHeaSet_flow_min,
    final VHeaMax_flow=VAirHeaSet_flow_max,
    final dTDisZonSetMax=dTAirDisHea_max,
    final zonDisEff_cool=effAirDisCoo,
    final zonDisEff_heat=effAirDisHea)
    if typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat
    "Terminal unit with reheat controller"

  Buildings.Controls.OBC.ASHRAE.G36.TerminalUnits.CoolingOnly.Controller ctlCoo(
    final venStd=stdVen,
    final have_winSen=have_winSen,
    final have_occSen=have_occSen,
    final have_CO2Sen=have_CO2Sen,
    final VOccMin_flow=VOutMinOcc_flow,
    final VAreMin_flow=VOutMinAre_flow,
    final VAreBreZon_flow=VOutAre_flow,
    final VPopBreZon_flow=VOutOcc_flow,
    final VMin_flow=VAirSet_flow_min,
    final VCooMax_flow=VAirCooSet_flow_max,
    final zonDisEff_cool=effAirDisCoo,
    final zonDisEff_heat=effAirDisHea)
    if typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly
    "Terminal unit cooling only controller"

  Buildings.Controls.OBC.ASHRAE.G36.ThermalZones.Setpoints TZonSet(
    final have_occSen=have_occSen,
    final have_winSen=have_winSen)
    "Compute zone temperature setpoints"

  Buildings.Controls.OBC.ASHRAE.G36.ZoneGroups.ZoneStatus zonSta(
    final have_winSen=have_winSen)
    "Evaluate zone temperature status"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooDowWarUpTim(k=3600)
    "RFE: Optimal start (using global OA temperature not associated with any AHU) not implemented"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant setAdj(k=0)
    "RFE: Setpoint adjustment by the occupant is not implemented in the template"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant cooSetAdj(k=0)
    "RFE: Setpoint adjustment by the occupant is not implemented in the template"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant heaSetAdj(k=0)
    "RFE: Setpoint adjustment by the occupant is not implemented in the template"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant uCooDemLimLev(k=0)
    "RFE: Setpoint adjustment by demand limit is not implemented in the template"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant uHeaDemLimLev(k=0)
    "RFE: Setpoint adjustment by demand limit is not implemented in the template"

equation
  /* Control point connection - start */

  // Inputs from bus
  connect(bus.TZon, ctlReh.TZon);
  connect(bus.y1Win, ctlReh.u1Win);
  connect(bus.y1Occ, ctlReh.u1Occ);
  connect(bus.ppmCO2, ctlReh.ppmCO2);
  connect(bus.ppmCO2Set, ctlReh.ppmCO2Set);
  connect(bus.yOpeMod, ctlReh.uOpeMod);
  connect(bus.TAirDis, ctlReh.TDis);
  connect(bus.VAirDis_flow, ctlReh.VDis_flow);
  connect(bus.TAirSup, ctlReh.TSup);
  connect(bus.TAirSupSet, ctlReh.TSupSet);
  connect(bus.y1FanSup_actual, ctlReh.u1Fan);
  connect(bus.y1PlaHeaWat, ctlReh.u1HotPla);
  connect(bus.yOveFloSet, ctlReh.oveFloSet);
  connect(bus.yOveDamPos, ctlReh.oveDamPos);
  connect(bus.y1OveHeaOff, ctlReh.uHeaOff);

  connect(bus.TZon, ctlCoo.TZon);
  connect(bus.y1Win, ctlCoo.u1Win);
  connect(bus.y1Occ, ctlCoo.u1Occ);
  connect(bus.ppmCO2, ctlCoo.ppmCO2);
  connect(bus.ppmCO2Set, ctlCoo.ppmCO2Set);
  connect(bus.yOpeMod, ctlCoo.uOpeMod);
  connect(bus.TAirDis, ctlCoo.TDis);
  connect(bus.VAirDis_flow, ctlCoo.VDis_flow);
  connect(bus.TAirSup, ctlCoo.TSup);
  connect(bus.y1FanSup_actual, ctlCoo.u1Fan);
  connect(bus.yOveFloSet, ctlCoo.oveFloSet);
  connect(bus.yOveDamPos, ctlCoo.oveDamPos);

  connect(bus.y1Occ, TZonSet.u1Occ);
  connect(bus.y1Win, TZonSet.u1Win);

  connect(bus.y1Win, zonSta.u1Win);
  connect(bus.TZon, zonSta.TZon);
  connect(bus.TZonCooOccSet, zonSta.TOccCooSet);
  connect(bus.TZonCooUnoSet, zonSta.TUnoCooSet);
  connect(bus.TZonHeaOccSet, zonSta.TOccHeaSet);
  connect(bus.TZonHeaUnoSet, zonSta.TUnoHeaSet);

  connect(bus.yOpeMod, TZonSet.uOpeMod);
  connect(bus.dTSetAdj, TZonSet.setAdj);
  connect(bus.dTHeaSetAdj, TZonSet.heaSetAdj);
  connect(bus.uCooDemLimLev, TZonSet.uCooDemLimLev);
  connect(bus.uHeaDemLimLev, TZonSet.uHeaDemLimLev);
  connect(bus.TZonCooOccSet, TZonSet.TOccCooSet);
  connect(bus.TZonCooUnoSet, TZonSet.TUnoCooSet);
  connect(bus.TZonHeaOccSet, TZonSet.TOccHeaSet);
  connect(bus.TZonHeaUnoSet, TZonSet.TUnoHeaSet);

  // Outputs to bus
  connect(ctlReh.yDam, bus.damVAV.y);
  connect(ctlReh.yVal, bus.coiHea.y);
  connect(ctlReh.VAdjPopBreZon_flow, bus.VAdjPopBreZon_flow);
  connect(ctlReh.VAdjAreBreZon_flow, bus.VAdjAreBreZon_flow);
  connect(ctlReh.VMinOA_flow, bus.VMinOA_flow);
  connect(ctlReh.VZonAbsMin_flow, bus.VZonAbsMin_flow);
  connect(ctlReh.VZonDesMin_flow, bus.VZonDesMin_flow);
  connect(ctlReh.yCO2, bus.yCO2);

  connect(ctlReh.yZonTemResReq, bus.yReqZonTemRes);
  connect(ctlReh.yZonPreResReq, bus.yReqZonPreRes);

  connect(ctlCoo.yDam, bus.damVAV.y);
  connect(ctlCoo.VAdjPopBreZon_flow, bus.VAdjPopBreZon_flow);
  connect(ctlCoo.VAdjAreBreZon_flow, bus.VAdjAreBreZon_flow);
  connect(ctlCoo.VMinOA_flow, bus.VMinOA_flow);
  connect(ctlCoo.VZonAbsMin_flow, bus.VZonAbsMin_flow);
  connect(ctlCoo.VZonDesMin_flow, bus.VZonDesMin_flow);
  connect(ctlCoo.yCO2, bus.yCO2);

  connect(ctlCoo.yZonTemResReq, bus.yZonTemResReq);
  connect(ctlCoo.yZonPreResReq, bus.yZonPreResReq);

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

  /* Control point connection - end */

  connect(TZonSet.TCooSet, ctlReh.TCooSet)
  connect(TZonSet.THeaSet, ctlReh.THeaSet)
  connect(uCooDemLimLev.y, TZonSet.uCooDemLimLev)
  connect(uHeaDemLimLev.y, TZonSet.uHeaDemLimLev)
  connect(cooSetAdj.y, TZonSet.cooSetAdj)
  connect(heaSetAdj.y, TZonSet.heaSetAdj)
  connect(setAdj.y, TZonSet.setAdj)
  connect(TZonSet.TCooSet, ctlCoo.TCooSet)
  connect(TZonSet.THeaSet, ctlCoo.THeaSet)
  connect(cooDowWarUpTim.y, zonSta.cooDowTim)
  connect(cooDowWarUpTim.y, zonSta.warUpTim)
end ControllerG36VAVBox;


Interface classes

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


Interface class for terminal unit controller. This partial class provides a standard interface for terminal unit controllers.

within Buildings.Templates.ZoneEquipment.Components.Interfaces;
partial block PartialController "Interface class for terminal unit controller"

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

  replaceable parameter
    Buildings.Templates.ZoneEquipment.Components.Data.PartialController dat(
      final typ=typ)
      "Design and operating parameters"

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

  Buildings.Templates.ZoneEquipment.Interfaces.Bus bus
    "Terminal unit control bus"
end PartialController;


Interface class for VAV terminal unit controller. This partial class provides a standard interface for VAV terminal unit controllers.

within Buildings.Templates.ZoneEquipment.Components.Interfaces;
partial block PartialControllerVAVBox
  "Interface class for VAV terminal unit controller"
  extends
    Buildings.Templates.ZoneEquipment.Components.Interfaces.PartialController(
      redeclare
      Buildings.Templates.ZoneEquipment.Components.Data.VAVBoxController dat(
        stdVen=stdVen));

  parameter Boolean have_CO2Sen=false
    "Set to true if the zone has CO2 sensor"

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

  outer replaceable Buildings.Templates.Components.Coils.None coiHea
    "Heating coil";
end PartialControllerVAVBox;


Records for configuration parameters

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


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


Interface classes

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


Interface class for air terminal unit

within Buildings.Templates.ZoneEquipment.Interfaces;
partial model PartialAirTerminal
  "Interface class for air terminal unit"

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

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

  replaceable parameter
    Buildings.Templates.ZoneEquipment.Configuration.PartialAirTerminal cfg(
    final typ=typ,
    final have_souChiWat=have_souChiWat,
    final have_souHeaWat=have_souHeaWat)
    "Configuration parameters"

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

  parameter Boolean have_souChiWat
    "Set to true if system uses CHW"
  parameter Boolean have_souHeaWat
    "Set to true if system uses HHW"

  replaceable parameter Buildings.Templates.ZoneEquipment.Data.PartialAirTerminal dat
    "Design and operating parameters"

  // Design parameters
  final parameter Modelica.Units.SI.MassFlowRate mAir_flow_nominal=
    dat.mAir_flow_nominal
    "Discharge air mass flow rate"
  parameter Modelica.Units.SI.MassFlowRate mAirPri_flow_nominal
    "Primary 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_Sup(
    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.ZoneEquipment.Types.Configuration.DualDuct
    "Supply air from AHU"
  Modelica.Fluid.Interfaces.FluidPort_a port_SupCol(
    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.ZoneEquipment.Types.Configuration.DualDuct
    "Dual duct cold deck air supply from AHU"
  Modelica.Fluid.Interfaces.FluidPort_a port_SupHot(
    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.ZoneEquipment.Types.Configuration.DualDuct
    "Dual duct hot deck air supply from AHU"
  Modelica.Fluid.Interfaces.FluidPort_b port_Dis(
    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))
    "Discharge air"
  Modelica.Fluid.Interfaces.FluidPort_a port_Ret(
    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.ZoneEquipment.Types.Configuration.FanPowered
     or typ == Buildings.Templates.ZoneEquipment.Types.Configuration.Induction
    "Return air"

  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"
  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"

  Buildings.Templates.ZoneEquipment.Interfaces.Bus bus
    "Terminal unit control bus"
end PartialAirTerminal;


Interface class for VAV terminal unit

within Buildings.Templates.ZoneEquipment.Interfaces;
model VAVBox "Interface class for VAV terminal unit"
  extends Buildings.Templates.ZoneEquipment.Interfaces.PartialAirTerminal(
    redeclare final Buildings.Templates.ZoneEquipment.Configuration.VAVBox cfg(
      typCoiHea=coiHea.typ,
      typValCoiHea=coiHea.typVal,
      typDamVAV=damVAV.typ,
      typCtl=ctl.typ,
      stdVen=ctl.stdVen),
    redeclare Buildings.Templates.ZoneEquipment.Data.VAVBox dat,
    final have_souChiWat=false,
    final have_souHeaWat=coiHea.have_sou,
    final mAirPri_flow_nominal=mAir_flow_nominal,
    final mChiWat_flow_nominal=0,
    final mHeaWat_flow_nominal=if coiHea.have_sou then dat.coiHea.mWat_flow_nominal else 0,
    final QChiWat_flow_nominal=0,
    final QHeaWat_flow_nominal=if coiHea.have_sou then dat.coiHea.Q_flow_nominal else 0);

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

  Buildings.Templates.Components.Actuators.Damper damVAV(
      redeclare final package Medium = MediumAir,
      final typ=Buildings.Templates.Components.Types.Damper.Modulating,
      use_strokeTime=energyDynamics<>Modelica.Fluid.Types.Dynamics.SteadyState,
      final allowFlowReversal=allowFlowReversalAir,
      final show_T=show_T,
      final dat=datDamVAV,
      typBla=Buildings.Templates.Components.Types.DamperBlades.VAV)
    "VAV damper"

  inner replaceable Buildings.Templates.ZoneEquipment.Components.Controls.OpenLoop ctl
    constrainedby
    Buildings.Templates.ZoneEquipment.Components.Interfaces.PartialControllerVAVBox(
      final dat=dat.ctl)
    "Control selections"

  Buildings.Templates.Components.Sensors.Temperature TAirDis(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversalAir,
    final have_sen=ctl.typ==Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat or
      ctl.typ==Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly,
    final m_flow_nominal=mAir_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorTemperature.Standard)
    "Discharge air temperature sensor"
  Buildings.Templates.Components.Sensors.VolumeFlowRate VAirDis_flow(
    redeclare final package Medium = MediumAir,
    final allowFlowReversal=allowFlowReversalAir,
    final have_sen=ctl.typ==Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat or
      ctl.typ==Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly,
    final m_flow_nominal=mAir_flow_nominal,
    final typ=Buildings.Templates.Components.Types.SensorVolumeFlowRate.FlowCross)
    "Airflow sensor"
protected
  parameter Buildings.Templates.Components.Data.Damper datDamVAV(
    final typ=damVAV.typ,
    final m_flow_nominal=dat.damVAV.m_flow_nominal,
    final dp_nominal=dat.damVAV.dp_nominal,
    final dpFixed_nominal=if damVAV.typ == Buildings.Templates.Components.Types.Damper.None
      then 0 else dat.coiHea.dpAir_nominal)
    "Local record for VAV damper with lumped flow resistance";
  parameter Buildings.Templates.Components.Data.Coil datCoiHea(
    final typ=coiHea.typ,
    final typVal=coiHea.typVal,
    final have_sou=coiHea.have_sou,
    final mAir_flow_nominal=dat.coiHea.mAir_flow_nominal,
    final mWat_flow_nominal=dat.coiHea.mWat_flow_nominal,
    final dpWat_nominal=dat.coiHea.dpWat_nominal,
    final dpValve_nominal=dat.coiHea.dpValve_nominal,
    final cap_nominal=dat.coiHea.cap_nominal,
    final TWatEnt_nominal=dat.coiHea.TWatEnt_nominal,
    final TAirEnt_nominal=dat.coiHea.TAirEnt_nominal,
    final dpAir_nominal=if damVAV.typ == Buildings.Templates.Components.Types.Damper.None
      then dat.coiHea.dpAir_nominal else 0)
    "Local record for coil with lumped flow resistance";
equation
  /* Control point connection - start */
  connect(damVAV.bus, bus.damVAV);
  connect(coiHea.bus, bus.coiHea);
  connect(TAirDis.y, bus.TAirDis);
  connect(VAirDis_flow.y, bus.VAirDis_flow);
  /* Control point connection - end */
  connect(port_aHeaWat, coiHea.port_aSou)
  connect(coiHea.port_bSou, port_bHeaWat)
  connect(damVAV.port_b,coiHea. port_a)
  connect(bus,ctl. bus)
  connect(coiHea.port_b, TAirDis.port_a)
  connect(TAirDis.port_b, port_Dis)

  connect(port_Sup, VAirDis_flow.port_a)
  connect(VAirDis_flow.port_b, damVAV.port_a)
end VAVBox;


Package with validation models

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


within Buildings.Templates.ZoneEquipment.Validation;
model VAVBoxCoolingOnly "Validation model for VAV terminal unit cooling only"
  extends Modelica.Icons.Example;

  replaceable package MediumAir=Buildings.Media.Air
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Air medium";
  replaceable package MediumHeaWat=Buildings.Media.Water
    constrainedby Modelica.Media.Interfaces.PartialMedium
    "Heating medium (such as HHW)";

  inner parameter UserProject.Data.AllSystems datAll(
    final VAVBox_1(cfg=VAVBox_1.cfg))
    "System parameters"

  Fluid.Sources.Boundary_pT bouPri(
    redeclare final package Medium = MediumAir,
    p=MediumAir.p_default + 200,
    nPorts=1) "Boundary conditions for primary air distribution system"
  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.Sources.Boundary_pT bouBui(
    redeclare final package Medium = MediumAir,
    nPorts=1) "Boundary conditions for indoor environment"

  replaceable Buildings.Templates.ZoneEquipment.VAVBoxCoolingOnly VAVBox_1(
    final dat=datAll.VAVBox_1,
    redeclare final package MediumAir = MediumAir,
    redeclare final package MediumHeaWat = MediumHeaWat)
    "Terminal unit"

  Fluid.Sources.Boundary_pT bouHeaWat(
    redeclare final package Medium = MediumHeaWat,
    nPorts=2) if VAVBox_1.have_souHeaWat
    "Boundary conditions for HHW distribution system"
  UserProject.VAVMZControlPoints sigAirHan if VAVBox_1.ctl.typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly
     or VAVBox_1.ctl.typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat
    "Control signals from AHU"
  UserProject.ZoneControlPoints sigZon
    if VAVBox_1.ctl.typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly
    or VAVBox_1.ctl.typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat
    "Control signals from zone-level equipment"
  UserProject.PlantControlPoints sigPla if VAVBox_1.ctl.typ ==
    Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxCoolingOnly or
    VAVBox_1.ctl.typ == Buildings.Templates.ZoneEquipment.Types.Controller.G36VAVBoxReheat
    "Control signals from AHU"
  UserProject.BASControlPoints sigBAS
    "BAS control points"
equation
  connect(bouPri.ports[1], res.port_a)
  connect(bouBui.ports[1], res1.port_b)
  connect(res.port_b, VAVBox_1.port_Sup)
  connect(VAVBox_1.port_Dis, res1.port_a)
  connect(VAVBox_1.port_aHeaWat, bouHeaWat.ports[1])
  connect(VAVBox_1.port_bHeaWat, bouHeaWat.ports[2])
  connect(sigZon.bus, VAVBox_1.bus)
  connect(sigAirHan.busTer[1], VAVBox_1.bus)
  connect(sigPla.busTer[1], VAVBox_1.bus)
  connect(sigBAS.busTer[1], VAVBox_1.bus)
end VAVBoxCoolingOnly;


Validation model for VAV terminal unit with reheat. This is a validation model for the template

Buildings.Templates.ZoneEquipment.VAVBoxReheat.

within Buildings.Templates.ZoneEquipment.Validation;
model VAVBoxReheat
  "Validation model for VAV terminal unit with reheat"
  extends VAVBoxCoolingOnly(
    redeclare Buildings.Templates.ZoneEquipment.VAVBoxReheat VAVBox_1);
end VAVBoxReheat;


Emulation of control points from the BAS. This class generates signals typically provided by the BAS.
It is aimed for validation purposes only.

within Buildings.Templates.ZoneEquipment.Validation.UserProject;
block BASControlPoints "Emulation of control points from the BAS"
  extends Modelica.Blocks.Icons.Block;

  parameter Integer nZon = 2
    "Number of served zones";

  Interfaces.Bus busTer[nZon]
    "Terminal unit control bus"
  Controls.OBC.CDL.Logical.Sources.Constant y1OccSch[nZon](
    each k=true)
    "Scheduled occupancy"
  Controls.OBC.CDL.Integers.Sources.Constant yOveFloSet[nZon](each k=0)
    "Override flow setpoint, 1: set to zero; 2: set to cooling maximum; 3: set to minimum; 4: set to heating maximum"
  Controls.OBC.CDL.Logical.Sources.Constant y1OveHeaOff[nZon](
    each k=false)
    "Override heating coil valve position, true: close valve"
  Controls.OBC.CDL.Integers.Sources.Constant yOveDamPos[nZon](each k=0)
    "Override damper position, 1: set to close; 2: set to open"
  Controls.OBC.CDL.Reals.Sources.Constant TZonHeaOccSet[nZon](
    each k=293.15)
    "Occupied heating setpoint"
  Controls.OBC.CDL.Reals.Sources.Constant TZonCooOccSet[nZon](
    each k=297.15)
    "Occupied cooling setpoint"
  Controls.OBC.CDL.Reals.Sources.Constant TZonHeaUnoSet[nZon](
    each k=285.15)
    "Unoccupied heating setpoint"
  Controls.OBC.CDL.Reals.Sources.Constant TZonCooUnoSet[nZon](
    each k=303.15)
    "Unoccupied cooling setpoint"
  Controls.OBC.CDL.Reals.Sources.Constant ppmCO2Set[nZon](
    each k=1000)
    "Zone CO2 concentration setpoint"
equation
  connect(y1OccSch.y, busTer.y1OccSch);
  connect(yOveFloSet.y, busTer.yOveFloSet);
  connect(yOveDamPos.y, busTer.yOveDamPos);
  connect(y1OveHeaOff.y, busTer.y1OveHeaOff);

  connect(TZonHeaOccSet.y, busTer.TZonHeaOccSet);
  connect(TZonCooOccSet.y, busTer.TZonCooOccSet);
  connect(TZonHeaUnoSet.y, busTer.TZonHeaUnoSet);
  connect(TZonCooUnoSet.y, busTer.TZonCooUnoSet);
  connect(ppmCO2Set.y, busTer.ppmCO2Set);
end BASControlPoints;


Package with configured models

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


Emulation of control points from plant. This class generates signals typically provided by the HHW and CHW plant
controller.
It is aimed for validation purposes only.

within Buildings.Templates.ZoneEquipment.Validation.UserProject;
block PlantControlPoints
  "Emulation of control points from plant"
  extends Modelica.Blocks.Icons.Block;

  parameter Integer nZon = 2
    "Number of served zones";

  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1PlaHeaWat[nZon](
    each k=true) "Heating hot water plant status"
  Interfaces.Bus busTer[nZon]
    "Terminal unit control bus"
equation

  connect(y1PlaHeaWat.y, busTer.y1PlaHeaWat)
end PlantControlPoints;


Emulation of multiple-zone VAV control points. This class generates signals typically provided by the AHU controller.
It is aimed for validation purposes only.

within Buildings.Templates.ZoneEquipment.Validation.UserProject;
block VAVMZControlPoints "Emulation of multiple-zone VAV control points"
  extends Modelica.Blocks.Icons.Block;

  parameter Integer nZon = 2
    "Number of served zones";

  Buildings.Templates.ZoneEquipment.Interfaces.Bus busTer[nZon]
    "Terminal unit control bus"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant TAirSupSet[nZon](
    each k=15 + 273.15) "AHU supply air temperature setpoint"
  Buildings.Controls.OBC.CDL.Integers.Sources.Constant yOpeMod[nZon](each k=1)
    "Group operating mode"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant VDesUncOutAir_flow[nZon](each k=1)
    "VDesUncOutAir_flow from AHU controller"
  Buildings.Controls.OBC.CDL.Logical.Sources.Constant yReqOutAir[nZon](each k=true)
    "yReqOutAir from AHU controller"
  Controls.OBC.CDL.Logical.Sources.Constant y1FanSup_actual[nZon](each k=true)
    "y1FanSup_actual from AHU controller"
  Controls.OBC.CDL.Reals.Sources.Constant TAirSup[nZon](each k=15 + 273.15)
    "AHU supply air temperature"
equation

  connect(TAirSupSet.y, busTer.TAirSupSet);
  connect(TAirSup.y, busTer.TAirSup);
  connect(yOpeMod.y, busTer.yOpeMod);

  connect(yReqOutAir.y, busTer.yReqOutAir);
  connect(VDesUncOutAir_flow.y, busTer.VDesUncOutAir_flow);
  connect(y1FanSup_actual.y, busTer.y1FanSup_actual);
end VAVMZControlPoints;


Emulation of control points from zone sensors and thermostats. This class generates signals typically provided by the zone equipment.
It is aimed for validation purposes only.

within Buildings.Templates.ZoneEquipment.Validation.UserProject;
block ZoneControlPoints "Emulation of control points from zone sensors and thermostats"
  extends Modelica.Blocks.Icons.Block;

  Interfaces.Bus bus
    "Terminal unit control bus"

  Buildings.Controls.OBC.CDL.Logical.Sources.Constant y1Occ(k=true)
    "Occupancy sensor status"
  Controls.OBC.CDL.Logical.Sources.Constant y1Win(k=true)
    "Window switch status"
  Controls.OBC.CDL.Reals.Sources.Constant TZon(k=303.15)
    "Zone temperature"
  Controls.OBC.CDL.Logical.Sources.Constant y1OveOccZon(
    k=false)
    "Zone occupancy override"
  Controls.OBC.CDL.Reals.Sources.Constant ppmCO2(k=1000)
    "Zone CO2 concentration"

equation
  connect(y1Occ.y, bus.y1Occ);
  connect(y1Win.y, bus.y1Win);
  connect(TZon.y, bus.TZon);
  connect(ppmCO2.y, bus.ppmCO2);
  connect(y1OveOccZon.y, bus.y1OveOccZon);
end ZoneControlPoints;


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


Models for BuildingPhysics

within Buildings;
package ThermalZones "Models for BuildingPhysics"
    extends Modelica.Icons.Package;
end ThermalZones;


Model of a room in which the air is computed using Computational Fluid Dynamics (CFD). Room model that computes the room air flow using computational fluid dynamics (CFD). The CFD simulation is coupled to the thermal simulation of the room
and, through the fluid port, to the air conditioning system.

within Buildings.ThermalZones.Detailed;
model CFD
  "Model of a room in which the air is computed using Computational Fluid Dynamics (CFD)"
  extends Buildings.ThermalZones.Detailed.BaseClasses.RoomHeatMassBalance(
  redeclare BaseClasses.CFDAirHeatMassBalance air(
    final massDynamics = massDynamics,
    final cfdFilNam = absCfdFilNam,
    final useCFD=useCFD,
    final samplePeriod=samplePeriod,
    final haveSensor=haveSensor,
    final nSen=nSen,
    final sensorName=sensorName,
    final portName=portName,
    final uSha_fixed=uSha_fixed,
    final p_start=p_start));

  // Assumptions
  parameter Modelica.Fluid.Types.Dynamics massDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial
    "Formulation of mass balance"
  // Initialization
  parameter Medium.AbsolutePressure p_start = Medium.p_default
    "Start value of pressure"

  parameter Boolean useCFD = true
    "Set to false to deactivate the CFD computation and use instead yFixed as output"
  parameter Modelica.Units.SI.Time samplePeriod(min=100*Modelica.Constants.eps)
    "Sample period of component"
  parameter Real uSha_fixed[nConExtWin] = zeros(nConExtWin)
    "Constant control signal for the shading device (0: unshaded; 1: fully shaded)";
  parameter String sensorName[:]
    "Names of sensors as declared in the CFD input file"
  parameter String portName[nPorts] = {"port_" + String(i) for i in 1:nPorts}
    "Names of fluid ports as declared in the CFD input file"
  parameter String cfdFilNam "CFD input file name"
  Modelica.Blocks.Interfaces.RealOutput yCFD[nSen]
    if haveSensor "Sensor for output from CFD"
protected
  final parameter String absCfdFilNam = Buildings.BoundaryConditions.WeatherData.BaseClasses.getAbsolutePath(cfdFilNam)
    "Absolute path to the CFD file";

  final parameter Boolean haveSensor = Modelica.Utilities.Strings.length(sensorName[1]) > 0
    "Flag, true if the model has at least one sensor";
  final parameter Integer nSen(min=0) = size(sensorName, 1)
    "Number of sensors that are connected to CFD output";
  Modelica.Blocks.Sources.Constant conSha[nConExtWin](final k=uSha_fixed)
    if haveShade "Constant signal for shade"

equation
  connect(air.yCFD, yCFD)
  connect(conSha.y, conExtWin.uSha)
  connect(conSha.y, bouConExtWin.uSha)
  connect(conSha.y, conExtWinRad.uSha)
  connect(irRadGai.uSha,conSha.y)
  connect(conSha.y, radTem.uSha)
  connect(conSha.y, shaSig.u)
  connect(air.uSha,conSha.y)
end CFD;


within Buildings.ThermalZones.Detailed;
model MixedAir "Model of a room in which the air is completely mixed"
  extends Buildings.ThermalZones.Detailed.BaseClasses.RoomHeatMassBalance(
  redeclare Buildings.ThermalZones.Detailed.BaseClasses.MixedAirHeatMassBalance air(
    final energyDynamics=energyDynamics,
    final massDynamics = energyDynamics,
    final p_start=p_start,
    final T_start=T_start,
    final X_start=X_start,
    final C_start=C_start,
    final C_nominal=C_nominal,
    final mSenFac=mSenFac,
    final m_flow_nominal=m_flow_nominal,
    final homotopyInitialization=homotopyInitialization,
    final conMod=intConMod,
    final hFixed=hIntFixed,
    final use_C_flow = use_C_flow),
    datConExt(
      each T_a_start = T_start,
      each T_b_start = T_start),
    datConExtWin(
      each T_a_start = T_start,
      each T_b_start = T_start),
    datConBou(
      each T_a_start = T_start,
      each T_b_start = T_start),
    datConPar(
      each T_a_start = T_start,
      each T_b_start = T_start));

  ////////////////////////////////////////////////////////////////////////////
  // Media declaration. This is identical to
  // Buildings.Fluid.Interfaces.LumpedVolumeDeclarations, except
  // that the comments have been changed to avoid a confusion about
  // what energyDynamics refers to.
  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"

  // Ports
  parameter Boolean use_C_flow=false
    "Set to true to enable input connector for trace substance that is connected to room air"

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

  parameter Real mSenFac(min=1)=1
    "Factor for scaling the sensible thermal mass of the zone air volume"

  // Initialization
  parameter Medium.AbsolutePressure p_start = Medium.p_default
    "Start value of zone air pressure"
  parameter Medium.Temperature T_start=Medium.T_default
    "Start value of zone air temperature"
  parameter Medium.MassFraction X_start[Medium.nX](
       quantity=Medium.substanceNames) = Medium.X_default
    "Start value of zone air mass fractions m_i/m"
  parameter Medium.ExtraProperty C_start[Medium.nC](
       quantity=Medium.extraPropertiesNames)=fill(0, Medium.nC)
    "Start value of zone air trace substances"
  parameter Medium.ExtraProperty C_nominal[Medium.nC](
       quantity=Medium.extraPropertiesNames) = fill(1E-2, Medium.nC)
    "Nominal value of zone air trace substances. (Set to typical order of magnitude.)"

  ////////////////////////////////////////////////////////////////////////////
  // Input connectors
  Modelica.Blocks.Interfaces.RealInput uSha[nConExtWin](each min=0, each max=1)
    if haveShade
    "Control signal for the shading device (removed if no shade is present)"

  Modelica.Blocks.Interfaces.RealInput C_flow[Medium.nC] if use_C_flow
    "Trace substance mass flow rate added to the room air. Enable if use_C_flow = true"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput HGlo[NConExtWin](
    final unit=fill("W/m2",NConExtWin))
    "Global solar irradiance"

  Buildings.Controls.OBC.CDL.Interfaces.RealOutput QTraGlo[NConExtWin](
    final unit=fill("W",NConExtWin)) "Transmitted global solar radiation"

  Buildings.Controls.OBC.CDL.Reals.Add gloSol[NConExtWin] if haveConExtWin
    "Global solar irradiance"

  Buildings.Controls.OBC.CDL.Reals.Add traSol[NConExtWin] if haveConExtWin
    "Transmitted solar radiation"

  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con[NConExtWin](
    final k=fill(0,NConExtWin),
    y(unit=fill("W",NConExtWin))) if not haveConExtWin "Constant zero"
  Buildings.Controls.OBC.CDL.Reals.Sources.Constant con1[NConExtWin](
    final k=fill(0, NConExtWin),
    y(unit=fill("W/m2", NConExtWin))) if not haveConExtWin
    "Constant zero"

equation
  connect(uSha, conExtWin.uSha)
  connect(uSha, bouConExtWin.uSha)
  connect(uSha, conExtWinRad.uSha)
  connect(irRadGai.uSha,uSha)
  connect(uSha, radTem.uSha)
  connect(uSha, shaSig.u)
  connect(air.uSha,uSha)
  connect(C_flow, air.C_flow)
  connect(conExtWinRad.HDir, gloSol.u2)
  connect(conExtWinRad.HDif, gloSol.u1)
  connect(gloSol.y, HGlo)
  connect(conExtWinRad.QTraDif_flow, traSol.u2)
  connect(conExtWinRad.QTraDir_flow, traSol.u1)
  connect(traSol.y, QTraGlo)
  connect(con.y, QTraGlo)
  connect(con1.y, HGlo)
end MixedAir;


Package with models for rooms

within Buildings.ThermalZones;
package Detailed "Package with models for rooms"
  extends Modelica.Icons.Package;
end Detailed;


Package with type definitions

within Buildings.ThermalZones.Detailed;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;

  type CFDBoundaryConditions = enumeration(
      Temperature "Temperature specified",
      HeatFlowRate "Heat flow rate specified")
    "Enumeration to define boundary conditions for the CFD simulation";
end Types;


User's Guide

within Buildings.ThermalZones.Detailed;
package UsersGuide "User's Guide"
  extends Modelica.Icons.Information;

   class MixedAir "Room model with instantaneously mixed air"
    extends Modelica.Icons.Information;
  Buildings.HeatTransfer.Data.OpaqueConstructions.Brick120 matLayPar
    \"Construction material for partition walls\"
    annotation (Placement(transformation(extent={{-20,140},{0,160}})));
  Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matLayRoo(
        material={
          HeatTransfer.Data.Solids.InsulationBoard(x=0.2),
          HeatTransfer.Data.Solids.Concrete(x=0.2)},
        final nLay=2) \"Construction material for roof\"
    annotation (Placement(transformation(extent={{20,140},{40,160}})));
  Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matLayFlo(
        material={
          HeatTransfer.Data.Solids.Concrete(x=0.2),
          HeatTransfer.Data.Solids.InsulationBoard(x=0.1),
          HeatTransfer.Data.Solids.Concrete(x=0.05)},
        final nLay=3) \"Construction material for floor\"
    annotation (Placement(transformation(extent={{60,140},{80,160}})));
  Buildings.HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveExteriorShade=false,
    haveInteriorShade=true) \"Data record for the glazing system\"
annotation (Placement(transformation(extent={{100,140},{120,160}})));

Note that construction layers are assembled from the outside to the room-side. Thus, the construction
matLayRoo has an exterior insulation. This constructions can then be used in the room model.

Before we explain how to declare and parametrize a room model,
we explain the different models that can be used to compute heat transfer through the room enclosing surfaces
and constructions. The room model
Buildings.ThermalZones.Detailed.MixedAir contains the constructions shown
in the table below.
The first row of the table lists the name of the data record that is used by the user
to assign the model parameters.
The second row lists the name of the instance of the model that simulates the equations.
The third column provides a reference to the class definition that implements the equations.
The forth column describes the main applicability of the model.

Record name
Model instance name
Class name
Description of the model

datConExt

modConExt

Buildings.ThermalZones.Detailed.Constructions.Construction

Exterior constructions that have no window.

datConExtWin

modConExtWin

Buildings.ThermalZones.Detailed.Constructions.ConstructionWithWindow

Exterior constructions that have a window. Each construction of this type must have one window.

Within the same room, all windows can either have an interior shade, an exterior shade or no shade.
Each window has its own control signal for the shade. This signal is exposed by the port uSha, which
has the same dimension as the number of windows. The values for uSha must be between
0 and 1. Set uSha=0 to open the shade, and uSha=1
to close the shade.

Windows can also have an overhang, side fins, both (overhang and sidefins) or no external shading device.

datConPar

modConPar

Buildings.ThermalZones.Detailed.Constructions.Construction

Interior constructions such as partitions within a room. Both surfaces of this construction are inside the room model
and participate in the infrared and solar radiation balance.
Since the view factor between these surfaces is zero, there is no infrared radiation from one surface to the other
of the same construction.

datConBou

modConBou

Buildings.ThermalZones.Detailed.Constructions.Construction

Constructions that expose the other boundary conditions of the other surface to the outside of this room model.
The heat conduction through these constructions is modeled in this room model.
The surface at the port opa_b is connected to the models for convection, infrared and solar radiation exchange
with this room model and with the other surfaces of this room model.
The surface at the port opa_a is connected to the port surf_conBou of this room model. This could be used, for example,
to model a floor inside this room and connect to other side of this floor model to a model that computes heat transfer in the soil.

surBou

N/A

Buildings.HeatTransfer.Data.OpaqueSurfaces.Generic

Opaque surfaces of this room model whose heat transfer through the construction is modeled outside of this room model.
This object is modeled using a data record that contains the area, solar and infrared emissivities and surface tilt.
The surface then participates in the convection and radiation heat balance of the room model. The heat flow rate and temperature
of this surface are exposed at the heat port surf_surBou.
An application of this object may be to connect the port surf_surBou of this room model with the port
surf_conBou of another room model in order to couple two room models.
Another application would be to model a radiant ceiling outside of this room model, and connect its surface to the port
surf_conBou in order for the radiant ceiling model to participate in the heat balance of this room.

With these constructions, we may define a room as follows:

  Buildings.ThermalZones.Detailed.MixedAir roo(
    redeclare package Medium = MediumA,
    AFlo=6*4,
    hRoo=2.7,
    nConExt=2,
    datConExt(layers={matLayRoo, matLayExt},
           A={6*4, 6*3},
           til={Buildings.Types.Tilt.Ceiling, Buildings.Types.Tilt.Wall},
           azi={Buildings.Types.Azimuth.S, Buildings.Types.Azimuth.W}),
    nConExtWin=nConExtWin,
    datConExtWin(layers={matLayExt}, A={4*3},
              glaSys={glaSys},
              hWin={2},
              wWin={2},
              fFra={0.1},
              til={Buildings.Types.Tilt.Wall},
              azi={Buildings.Types.Azimuth.S}),
    nConPar=1,
    datConPar(layers={matLayPar}, each A=10,
           each til=Buildings.Types.Tilt.Wall),
    nConBou=1,
    datConBou(layers={matLayFlo}, each A=6*4,
           each til=Buildings.Types.Tilt.Floor),
    nSurBou=1,
    surBou(each A=6*3, each absIR=0.9, each absSol=0.9, each til=Buildings.Types.Tilt.Wall),
    linearizeRadiation = true ,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) \"Room model\"
    annotation (Placement(transformation(extent={{46,20},{86,60}})));

The following paragraphs explain the " + "different declarations.

The statement

    redeclare package Medium = MediumA,
    AFlo=20,
    V=20*2.5,

declares that the medium of the room air is set to MediumA,
that the floor area is 20 m2 and that
the room air volume is 20*2.5 m3.
The floor area is used to scale the internal heat
gains, which are declared with units of W/m2
using the input signal qGai_flow.

The next entries specify constructions and surfaces
that participate in the heat exchange.

The entry

    nConExt=2,

declares that there are two exterior constructions.

The lines

    datConExt(layers={matLayRoo, matLayExt},
           A={6*4, 6*3},
           til={Buildings.Types.Tilt.Ceiling, Buildings.Types.Tilt.Wall},
           azi={Buildings.Types.Azimuth.S, Buildings.Types.Azimuth.W}),

declare that the material layers in these constructions are
set the records matLayRoo and matLayExt.
What follows are the declarations for the surface area,
the tilt of the surface and the azimuth of the surfaces. Thus, the
surface with construction matLayExt is 6*3 m2 large
and it is a west-facing wall.

Next, the declaration

    nConExtWin=nConExtWin,
    datConExtWin(layers={matLayExt}, A={4*3},
              glaSys={glaSys},
              hWin={2},
              wWin={2},
              fFra={0.1},
              til={Buildings.Types.Tilt.Wall},
              azi={Buildings.Types.Azimuth.S}),

declares the construction that contains a window. This construction is built
using the materials defined in the record matLayExt. Its total area,
including the window, is 4*3 m2.
The glazing system is built using the construction defined in the record
glaSys. The window area is hwin=2 m high
and
wwin=2 m wide.
The ratio of frame
to total glazing system area is 10%.

Optionally, each window can have an overhang, side fins or both.
If the above window were to have an overhang of
2.5 m width that is centered above the window,
and hence extends each side of the window by 0.25 m, and has a depth of
1 m and a gap between window and overhang of
0.1 m, then
its declaration would be

              ove(wL={0.25}, wR={0.25}, gap={0.1}, dep={1}),

This line can be placed below the declaration of wWin.
This would instanciate the model

Buildings.HeatTransfer.Windows.Overhang to model the overhang. See this class for a picture of the above dimensions.

If the window were to have side fins that are
2.5 m high, measured from the bottom of the windows,
and hence extends 0.5 m above the window, are
1 m depth and are placed
0.1 m to the left and right of the window,
then its declaration would be

              sidFin(h={0.5}, gap={0.1}, dep={1}),

This would instanciate the model

Buildings.HeatTransfer.Windows.SideFins to model the side fins. See this class for a picture of the above dimensions.

The lines

              til={Buildings.Types.Tilt.Wall},
              azi={Buildings.Types.Azimuth.S}),

declare that the construction is a wall that is south exposed.

Note that if the room were to have two windows, and one window has side fins and the other window has an overhang, the
following declaration could be used, which sets the value of dep to 0 for the non-present side fins or overhang, respectively:

              sidFin(h  = {0.5, 0}, gap = {0.1, 0.0}, dep = {1, 0}),
              ove(wL = {0.0, 0.25}, wR = {0.0, 0.25}, gap = {0.0, 0.1}, dep = {0, 1}),

What follows is the declaration of the partition constructions, as declared by

    nConPar=1,
    datConPar(layers={matLayPar}, each A=10,
           each til=Buildings.Types.Tilt.Wall),

Thus, there is one partition construction. Its area is 10 m2 for each
surface, to form a total surface area inside this thermal zone of 20 m2.

Next, the declaration

    nConBou=1,
    datConBou(layers={matLayFlo}, each A=6*4,
           each til=Buildings.Types.Tilt.Floor),

declares one construction whose other surface boundary condition is exposed by this
room model (through the heat port surf_conBou).

Note that by default, there is a temperature state at the surface of this wall.
Therefore, connecting to the heat port  surf_conBou a prescribed
temperature boundary condition such as

Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature would lead to an error
and the model won't translate.
The reason is that both, the state defines the temperature at the surface, and

Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature prescribes
the value of this temperature, leading
to an overspecification. To avoid this, add between surf_conBou
and the prescribed boundary condition a thermal conductance such as

Modelica.Thermal.HeatTransfer.Components.ThermalConductor
or a thermal convection model such as

Buildings.HeatTransfer.Convection.Exterior.
Alternatively, you could remove the state from the surface by declaring

    nConBou=1,
    datConBou(layers={matLayFlo}, each A=6*4,
           each til=Buildings.Types.Tilt.Floor,
           each stateAtSurface_a = false),

The declaration

    nSurBou=1,
    surBou(each A=6*3, each absIR=0.9, each absSol=0.9, each til=Buildings.Types.Tilt.Wall),

is used to instantiate a model for a surface that is in this room.
The surface has an area of 6*3 m2, absorptivity in the infrared and the solar
spectrum of 0.9 and it is a wall.
The room model will compute infrared radiative heat exchange, solar radiative heat gains
and infrared radiative heat gains of this surface. The surface temperature and
heat flow rate are exposed by this room model at the heat port
surf_surBou.
A model builder may use this construct
to couple this room model to another room model that may model the construction.

The declaration

    linearizeRadiation = true,

causes the equations for radiative heat transfer to be linearized. This can
reduce computing time at the expense of accuracy.

The declaration

    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial)

is used to initialize the air volume inside the thermal zone.

Modeling of contaminants

The model has a parameter use_C_flow. If set to true,
then an input connector C_flow is enabled, which allows adding trace substances
to the room air. Note that this requires a medium model that has trace substances enabled.
See the example

Buildings.ThermalZones.Detailed.Examples.MixedAirCO2.

Notes

To connect two rooms, the model

Buildings.HeatTransfer.Conduction.MultiLayer can be connected to
the ports surf_surBou of the two rooms.
However, make sure to set stateAtSurface_a = true
and stateAtSurface_b = true in the instance of the heat conduction
model, as this allows to avoid
a nonlinear system of equation to compute the radiative heat transfer,
thereby leading to faster simulation.
See

Buildings.ThermalZones.Detailed.Validation.BESTEST.Cases9xx.Case960
for an example.

By setting linearizeRadiation = false, nonlinear equations will
be used to compute the infrared radiation exchange among surfaces. This
can lead to slower computation.

References

Michael Wetter, Wangda Zuo and Thierry Stephane Nouidui.

Modeling of Heat Transfer in Rooms in the Modelica \"Buildings\" Library.

Proc. of the 12th IBPSA Conference, p. 1096-1103. Sydney, Australia, November 2011.

"));
   end MixedAir;

  class CFD
    "Room model with air heat and mass balance computed using Computational Fluid Dynamics"
    extends Modelica.Icons.Information;
  end CFD;
end UsersGuide;