Radiative temperature of the room. This model computes the radiative temperature in the room.
For a room with windows but no shade, the radiative temperature is
computed as

within Buildings.ThermalZones.Detailed.BaseClasses;
model RadiationTemperature "Radiative temperature of the room"
  extends Buildings.ThermalZones.Detailed.BaseClasses.PartialSurfaceInterfaceRadiative;

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaUns[NConExtWin]
  if haveConExtWin
    "Heat port that connects to room-side surface of unshaded glass"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaSha[NConExtWin]
 if haveShade "Heat port that connects to room-side surface of shaded glass"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a sha[NConExtWin]
 if haveShade "Heat port that connects to shade"
  parameter Boolean haveShade "Set to true if the windows have a shade"

  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.RealOutput TRad(min=0, unit="K", displayUnit="degC")
    "Radiative temperature"

protected
  final parameter Integer NOpa = NConExt+2*NConExtWin+2*NConPar+NConBou+NSurBou
    "Number of opaque surfaces, including the window frame";
  final parameter Integer NWin = NConExtWin "Number of window surfaces";
  final parameter Integer NTot = NOpa + NWin "Total number of surfaces";

  final parameter Modelica.Units.SI.Area AGla[NWin]=datConExtWin.AGla
    "Surface area of opaque surfaces";
  final parameter Real epsGla[NWin](each min=0, each max=1)=
    {datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].absIR_b for i in 1:NWin}
    "Absorptivity of glass";
  final parameter Real epsSha[NWin](each min=0, each max=1)=
    {datConExtWin[i].glaSys.shade.absIR_a for i in 1:NWin}
    "Absorptivity of shade";
  final parameter Real tauSha[NWin](each min=0, each max=1)=
    {(if datConExtWin[i].glaSys.haveInteriorShade then
      datConExtWin[i].glaSys.shade.tauIR_a else 1) for i in 1:NWin}
    "Transmissivity of shade";
  final parameter Modelica.Units.SI.Area epsAOpa[NOpa](each fixed=false)
    "Product of area times absorptivity of opaque surfaces";
  final parameter Modelica.Units.SI.Area epsAGla[NWin](each fixed=false)
    "Product of area times absorptivity of window surfaces";
  final parameter Modelica.Units.SI.Area epsASha[NWin](each fixed=false)
    "Product of area times absorptivity of window shade";
  final parameter Modelica.Units.SI.Area epsTauASha[NWin](each fixed=false)
    "Product of area times glass absorptivity times shade transmittance";
  Modelica.Units.SI.Temperature TOpa[NOpa](each start=293.15, each nominal=
        293.15) "Temperature of opaque surfaces";
  Modelica.Units.SI.Temperature TGlaUns[NWin](each start=293.15, each nominal=
        293.15) "Temperature of unshaded part of glass";
  Modelica.Units.SI.Temperature TGlaSha[NWin](each start=293.15, each nominal=
        293.15) "Temperature of shaded part of glass";
  Modelica.Units.SI.Temperature TSha[NWin](each start=293.15, each nominal=
        293.15) "Temperature of shade";
  // Internal connectors, used because of the conditionally removed connectors
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaUns_internal[NConExtWin]
    "Heat port that connects to room-side surface of unshaded glass";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaSha_internal[NConExtWin]
    "Heat port that connects to room-side surface of shaded glass";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a sha_internal[NConExtWin]
    "Heat port that connects to shade";
  Modelica.Blocks.Interfaces.RealInput uSha_internal[NConExtWin](each min=0, each max=1)
    "Control signal for the shading device";

initial equation
  // The next loops build the array epsAOpa that simplifies
  // the model equations.
  // The arrays stores the values of the constructios in the following order
  // [x[1:NConExt] x[1:NConPar] x[1: NConPar] x[1: NConBou] x[1: NSurBou] x[1: NConExtWin] x[1: NConExtWin]]
  // where x is epsOpa, AOpa or kOpa.
  // The last two entries are for the opaque wall that contains a window, and for the window frame.
  for i in 1:NConExt loop
    epsAOpa[i] = epsConExt[i] * AConExt[i];
  end for;
  for i in 1:NConPar loop
    epsAOpa[i+NConExt]         = epsConPar_a[i] * AConPar[i];
    epsAOpa[i+NConExt+NConPar] = epsConPar_b[i] * AConPar[i];
  end for;
  for i in 1:NConBou loop
    epsAOpa[i+NConExt+2*NConPar] = epsConBou[i] * AConBou[i];
  end for;
  for i in 1:NSurBou loop
    epsAOpa[i+NConExt+2*NConPar+NConBou] = epsSurBou[i] * ASurBou[i];
  end for;
  for i in 1:NConExtWin loop
    // Opaque part of construction that has a window embedded
    epsAOpa[i+NConExt+2*NConPar+NConBou+NSurBou] = epsConExtWinOpa[i] * AConExtWinOpa[i];
    // Window frame
    epsAOpa[i+NConExt+2*NConPar+NConBou+NSurBou+NConExtWin] = epsConExtWinFra[i] * AConExtWinFra[i];
  end for;
  // Window glass
  for i in 1:NConExtWin loop
    // Window glass
    epsAGla[i] = AGla[i] * epsGla[i];
    // Window shade
    epsASha[i]    = AGla[i] * epsSha[i];
    // Emitted from glas and transmitted through window shade
    epsTauASha[i] = AGla[i] * epsGla[i] * tauSha[i];
  end for;
////////////////////////////////////////////////////////////////////
equation
  // Conditional connnector
  connect(glaUns, glaUns_internal);
  connect(glaSha, glaSha_internal);
  connect(sha, sha_internal);
  connect(uSha, uSha_internal);
  if not haveConExtWin then
    glaUns_internal.T = fill(293.15, NConExtWin);
  end if;
  if not haveShade then
    glaSha_internal.T = fill(293.15, NConExtWin);
    sha_internal.T = fill(293.15, NConExtWin);
    uSha_internal = fill(0, NConExtWin);
  end if;

  // Assign temperature of opaque surfaces
  for i in 1:NConExt loop
    TOpa[i] = conExt[i].T;
  end for;
  for i in 1:NConPar loop
    TOpa[i+NConExt]         = conPar_a[i].T;
    TOpa[i+NConExt+NConPar] = conPar_b[i].T;
  end for;
  for i in 1:NConBou loop
    TOpa[i+NConExt+2*NConPar] = conBou[i].T;
  end for;
  for i in 1:NSurBou loop
    TOpa[i+NConExt+2*NConPar+NConBou] = conSurBou[i].T;
  end for;
  for i in 1:NConExtWin loop
    TOpa[i+NConExt+2*NConPar+NConBou+NSurBou]            = conExtWin[i].T;
    TOpa[i+NConExt+2*NConPar+NConBou+NConExtWin+NSurBou] = conExtWinFra[i].T;
  end for;
  // Assign temperature of glass and shade
  for i in 1:NConExtWin loop
    TGlaUns[i] = glaUns_internal[i].T;
    TGlaSha[i] = glaSha_internal[i].T;
    TSha[i]    = sha_internal[i].T;
  end for;
  // Compute radiative temperature
  if haveShade then
    TRad = (sum(epsAOpa[i] * TOpa[i] for i in 1:NOpa)
        + sum(
      ( uSha_internal[i] * (epsASha[i] * TSha[i] + epsTauASha[i] * TGlaSha[i]) +
      (1-uSha_internal[i]) * epsAGla[i] * TGlaUns[i])
        for i in 1:NConExtWin))  /
        (sum(epsAOpa) + sum(
      ( uSha_internal[i] * (epsASha[i] + epsTauASha[i]) + (1-uSha_internal[i]) * epsAGla[i])
        for i in 1:NConExtWin));
      else
    TRad = (sum(epsAOpa[i] * TOpa[i] for i in 1:NOpa) + sum(epsAGla .* TGlaUns)) / (sum(epsAOpa) + sum(epsAGla));
  end if;

  // Assign heat exchange to connectors
  if haveConExt then
    for i in 1:NConExt loop
      0 = conExt[i].Q_flow;
    end for;
  else
      conExt[1].T = 293.15;
  end if;

  if haveConPar then
    for i in 1:NConPar loop
      0 = conPar_a[i].Q_flow;
      0 = conPar_b[i].Q_flow;
    end for;
  else
      conPar_a[1].T = 293.15;
      conPar_b[1].T = 293.15;
  end if;

  if haveConBou then
    for i in 1:NConBou loop
      0 = conBou[i].Q_flow;
    end for;
  else
     conBou[1].T = 293.15;
  end if;

  if haveSurBou then
    for i in 1:NSurBou loop
      0 = conSurBou[i].Q_flow;
    end for;
  else
      conSurBou[1].T = 293.15;
  end if;

  if haveConExtWin then
    for i in 1:NConExtWin loop
      0 = conExtWin[i].Q_flow;
      0 = conExtWinFra[i].Q_flow;
    end for;
  else
      conExtWin[1].T    = 293.15;
      conExtWinFra[1].T = 293.15;
  end if;
end RadiationTemperature;


Base model for a room

within Buildings.ThermalZones.Detailed.BaseClasses;
partial model RoomHeatMassBalance "Base model for a room"
  extends Buildings.ThermalZones.Detailed.BaseClasses.ConstructionRecords;

  replaceable package Medium =
    Modelica.Media.Interfaces.PartialMedium "Medium in the component"

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

  parameter Integer nPorts=0 "Number of ports"
  Modelica.Fluid.Vessels.BaseClasses.VesselFluidPorts_b ports[nPorts](
      redeclare each package Medium = Medium) "Fluid inlets and outlets"
  final parameter Modelica.Units.SI.Volume V=AFlo*hRoo "Volume";
  parameter Modelica.Units.SI.Area AFlo "Floor area";
  parameter Modelica.Units.SI.Length hRoo "Average room height";

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heaPorAir
    "Heat port to air volume"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a heaPorRad
    "Heat port for radiative heat gain and radiative temperature"
  ////////////////////////////////////////////////////////////////////////
  // Constructions
  Constructions.Construction conExt[NConExt](
    final A=datConExt.A,
    final til=datConExt.til,
    final layers=datConExt.layers,
    final steadyStateInitial=datConExt.steadyStateInitial,
    final T_a_start=datConExt.T_a_start,
    final T_b_start=datConExt.T_b_start,
    final stateAtSurface_a = datConExt.stateAtSurface_a,
    final stateAtSurface_b = datConExt.stateAtSurface_b) if haveConExt
    "Heat conduction through exterior construction that have no window"
  Constructions.ConstructionWithWindow conExtWin[NConExtWin](
    final A=datConExtWin.A,
    final til=datConExtWin.til,
    final layers=datConExtWin.layers,
    final steadyStateInitial=datConExtWin.steadyStateInitial,
    final T_a_start=datConExtWin.T_a_start,
    final T_b_start=datConExtWin.T_b_start,
    final AWin=datConExtWin.AWin,
    final fFra=datConExtWin.fFra,
    final glaSys=datConExtWin.glaSys,
    each final homotopyInitialization=homotopyInitialization,
    each final linearizeRadiation=linearizeRadiation,
    each final steadyStateWindow=steadyStateWindow,
    final stateAtSurface_a = datConExtWin.stateAtSurface_a,
    final stateAtSurface_b = datConExtWin.stateAtSurface_b) if haveConExtWin
    "Heat conduction through exterior construction that have a window"

  Constructions.Construction conPar[NConPar](
    A=datConPar.A,
    til=datConPar.til,
    final layers=datConPar.layers,
    steadyStateInitial=datConPar.steadyStateInitial,
    T_a_start=datConPar.T_a_start,
    T_b_start=datConPar.T_b_start,
    final stateAtSurface_a = datConPar.stateAtSurface_a,
    final stateAtSurface_b = datConPar.stateAtSurface_b) if haveConPar
    "Heat conduction through partitions that have both sides inside the thermal zone"

  Constructions.Construction conBou[NConBou](
    A=datConBou.A,
    til=datConBou.til,
    final layers=datConBou.layers,
    steadyStateInitial=datConBou.steadyStateInitial,
    T_a_start=datConBou.T_a_start,
    T_b_start=datConBou.T_b_start,
    final stateAtSurface_a = datConBou.stateAtSurface_a,
    final stateAtSurface_b = datConBou.stateAtSurface_b) if haveConBou
    "Heat conduction through opaque constructions that have the boundary conditions of the other side exposed"
  parameter Boolean linearizeRadiation=true
    "Set to true to linearize emissive power";

  parameter Boolean steadyStateWindow = false
    "Set to false to add thermal capacity at window, which generally leads to faster simulation"
  ////////////////////////////////////////////////////////////////////////
  // Convection
  parameter Buildings.HeatTransfer.Types.InteriorConvection intConMod=Buildings.HeatTransfer.Types.InteriorConvection.Temperature
    "Convective heat transfer model for room-facing surfaces of opaque constructions"
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hIntFixed=3.0
    "Constant convection coefficient for room-facing surfaces of opaque constructions"
  parameter Buildings.HeatTransfer.Types.ExteriorConvection extConMod=Buildings.HeatTransfer.Types.ExteriorConvection.TemperatureWind
    "Convective heat transfer model for exterior facing surfaces of opaque constructions"
  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hExtFixed=10.0
    "Constant convection coefficient for exterior facing surfaces of opaque constructions"
  parameter Modelica.Units.SI.MassFlowRate m_flow_nominal(min=0) = V*1.2/3600
    "Nominal mass flow rate"
  parameter Boolean sampleModel = false
    "Set to true to time-sample the model, which can give shorter simulation time if there is already time sampling in the system model"
  ////////////////////////////////////////////////////////////////////////
  // Control signals
  Modelica.Blocks.Interfaces.RealInput uWin[nConExtWin](
    each min=0, each max=1, each unit="1") if haveControllableWindow
    "Control signal for window state (used for electrochromic windows, removed otherwise)"

  ////////////////////////////////////////////////////////////////////////
  // Models for boundary conditions
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a surf_conBou[nConBou]
 if haveConBou "Heat port at surface b of construction conBou"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a surf_surBou[nSurBou]
 if haveSurBou "Heat port of surface that is connected to the room air"
  Modelica.Blocks.Interfaces.RealInput qGai_flow[3](each unit="W/m2")
    "Radiant, convective and latent heat input into room (positive if heat gain)"
  // Reassign the tilt since a construction that is declared as a ceiling of the
  // room model has an exterior-facing surface that is a floor
  BaseClasses.ExteriorBoundaryConditions bouConExt(
    final nCon=nConExt,
    linearizeRadiation=linearizeRadiation,
    final conMod=extConMod,
    final conPar=datConExt,
    final hFixed=hExtFixed) if haveConExt
    "Exterior boundary conditions for constructions without a window"
  // Reassign the tilt since a construction that is declared as a ceiling of the
  // room model has an exterior-facing surface that is a floor
  BaseClasses.ExteriorBoundaryConditionsWithWindow bouConExtWin(
    final nCon=nConExtWin,
    final conPar=datConExtWin,
    linearizeRadiation=linearizeRadiation,
    final conMod=extConMod,
    final hFixed=hExtFixed) if haveConExtWin
    "Exterior boundary conditions for constructions with a window"

  HeatTransfer.Windows.BaseClasses.WindowRadiation conExtWinRad[NConExtWin](
    final AWin=(1 .- datConExtWin.fFra) .* datConExtWin.AWin,
    final N={size(datConExtWin[i].glaSys.glass, 1) for i in 1:NConExtWin},
    final tauGlaSol=datConExtWin.glaSys.glass.tauSol,
    final rhoGlaSol_a=datConExtWin.glaSys.glass.rhoSol_a,
    final rhoGlaSol_b=datConExtWin.glaSys.glass.rhoSol_b,
    final xGla=datConExtWin.glaSys.glass.x,
    final tauShaSol_a=datConExtWin.glaSys.shade.tauSol_a,
    final tauShaSol_b=datConExtWin.glaSys.shade.tauSol_b,
    final rhoShaSol_a=datConExtWin.glaSys.shade.rhoSol_a,
    final rhoShaSol_b=datConExtWin.glaSys.shade.rhoSol_b,
    final haveExteriorShade=datConExtWin.glaSys.haveExteriorShade,
    final haveInteriorShade=datConExtWin.glaSys.haveInteriorShade)
 if haveConExtWin "Model for solar radiation through shades and window"

  BoundaryConditions.WeatherData.Bus weaBus "Weather data"

  replaceable BaseClasses.PartialAirHeatMassBalance air
   constrainedby BaseClasses.PartialAirHeatMassBalance(
        redeclare final package Medium = Medium,
        nPorts=nPorts,
        final nConExt=nConExt,
        final nConExtWin=nConExtWin,
        final nConPar=nConPar,
        final nConBou=nConBou,
        final nSurBou=nSurBou,
        final datConExt=datConExt,
        final datConExtWin=datConExtWin,
        final datConPar=datConPar,
        final datConBou=datConBou,
        final surBou=surBou,
        final haveShade=haveShade,
        final V=V) "Convective heat and mass balance of air"

  Buildings.ThermalZones.Detailed.BaseClasses.SolarRadiationExchange solRadExc(
    final nConExt=nConExt,
    final nConExtWin=nConExtWin,
    final nConPar=nConPar,
    final nConBou=nConBou,
    final nSurBou=nSurBou,
    final datConExt = datConExt,
    final datConExtWin = datConExtWin,
    final datConPar = datConPar,
    final datConBou = datConBou,
    final surBou = surBou,
    final is_floorConExt=is_floorConExt,
    final is_floorConExtWin=is_floorConExtWin,
    final is_floorConPar_a=is_floorConPar_a,
    final is_floorConPar_b=is_floorConPar_b,
    final is_floorConBou=is_floorConBou,
    final is_floorSurBou=is_floorSurBou,
    final tauGla={datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].tauSol[1] for i in 1:NConExtWin})
    if haveConExtWin "Solar radiative heat exchange"

  Buildings.ThermalZones.Detailed.BaseClasses.InfraredRadiationGainDistribution irRadGai(
    final nConExt=nConExt,
    final nConExtWin=nConExtWin,
    final nConPar=nConPar,
    final nConBou=nConBou,
    final nSurBou=nSurBou,
    final datConExt = datConExt,
    final datConExtWin = datConExtWin,
    final datConPar = datConPar,
    final datConBou = datConBou,
    final surBou = surBou,
    final haveShade=haveShade)
    "Distribution for infrared radiative heat gains (e.g., due to equipment and people)"

  Buildings.ThermalZones.Detailed.BaseClasses.InfraredRadiationExchange irRadExc(
    final nConExt=nConExt,
    final nConExtWin=nConExtWin,
    final nConPar=nConPar,
    final nConBou=nConBou,
    final nSurBou=nSurBou,
    final datConExt = datConExt,
    final datConExtWin = datConExtWin,
    final datConPar = datConPar,
    final datConBou = datConBou,
    final surBou = surBou,
    final linearizeRadiation = linearizeRadiation,
    final homotopyInitialization = homotopyInitialization,
    final sampleModel = sampleModel)
    "Infrared radiative heat exchange"

  Buildings.ThermalZones.Detailed.BaseClasses.RadiationTemperature radTem(
    final nConExt=nConExt,
    final nConExtWin=nConExtWin,
    final nConPar=nConPar,
    final nConBou=nConBou,
    final nSurBou=nSurBou,
    final datConExt=datConExt,
    final datConExtWin=datConExtWin,
    final datConPar=datConPar,
    final datConBou=datConBou,
    final surBou=surBou,
    final haveShade=haveShade) "Radiative temperature of the room"

  HeatTransfer.Windows.BaseClasses.ShadeRadiation shaRad[NConExtWin](
    final A=(1 .- datConExtWin.fFra) .* datConExtWin.AWin,
    final thisSideHasShade=haveInteriorShade,
    final absIR_air=datConExtWin.glaSys.shade.absIR_a,
    final absIR_glass={(datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].absIR_b)
                         for i in 1:NConExtWin},
    final tauIR_air=tauIRSha_air,
    final tauIR_glass=tauIRSha_glass,
    each final linearize = linearizeRadiation,
    each final homotopyInitialization=homotopyInitialization)
    if haveShade "Radiation model for room-side window shade"

protected
  final parameter Modelica.Units.SI.TransmissionCoefficient tauIRSha_air[
    NConExtWin]=datConExtWin.glaSys.shade.tauIR_a
    "Infrared transmissivity of shade for radiation coming from the exterior or the room"
  final parameter Modelica.Units.SI.TransmissionCoefficient tauIRSha_glass[
    NConExtWin]=datConExtWin.glaSys.shade.tauIR_b
    "Infrared transmissivity of shade for radiation coming from the glass"

  // If at least one glass layer in the room has mutiple states, then
  // set haveControllableWindow=true. In this case, the input connector for
  // the control signal will be enabled. Otherwise, it is removed.
  final parameter Boolean haveControllableWindow=
  Modelica.Math.BooleanVectors.anyTrue(
    {datConExtWin[i].glaSys.haveControllableWindow for i in 1:NConExtWin})
    "Flag, true if the windows allow multiple states, such as for electrochromic windows"

  final parameter Boolean haveExteriorShade[NConExtWin]=
    {datConExtWin[i].glaSys.haveExteriorShade for i in 1:NConExtWin}
    "Set to true if window has exterior shade (at surface a)"
  final parameter Boolean haveInteriorShade[NConExtWin]=
    {datConExtWin[i].glaSys.haveInteriorShade for i in 1:NConExtWin}
    "Set to true if window has interior shade (at surface b)"

  final parameter Boolean haveShade=
    Modelica.Math.BooleanVectors.anyTrue(haveExteriorShade[:]) or
    Modelica.Math.BooleanVectors.anyTrue(haveInteriorShade[:])
    "Set to true if the windows have a shade";

  final parameter Boolean is_floorConExt[NConExt]=
    datConExt.is_floor "Flag to indicate if floor for exterior constructions";
  final parameter Boolean is_floorConExtWin[NConExtWin]=
    datConExtWin.is_floor "Flag to indicate if floor for constructions";
  final parameter Boolean is_floorConPar_a[NConPar]=
    datConPar.is_floor "Flag to indicate if floor for constructions";
  final parameter Boolean is_floorConPar_b[NConPar]=
    datConPar.is_ceiling "Flag to indicate if floor for constructions";
  final parameter Boolean is_floorConBou[NConBou]=
    datConBou.is_floor
    "Flag to indicate if floor for constructions with exterior boundary conditions exposed to outside of room model";
  parameter Boolean is_floorSurBou[NSurBou]=
    surBou.is_floor
    "Flag to indicate if floor for constructions that are modeled outside of this room";

  HeatTransfer.Windows.BaseClasses.ShadingSignal shaSig[NConExtWin](
    each final haveShade=haveShade)
    if haveConExtWin "Shading signal"

  Buildings.ThermalZones.Detailed.BaseClasses.HeatGain heaGai(final AFlo=AFlo)
    "Model to convert internal heat gains"

  Buildings.ThermalZones.Detailed.BaseClasses.RadiationAdapter radiationAdapter
  Modelica.Blocks.Math.Add add

  Modelica.Blocks.Math.Add sumJToWin[NConExtWin](
    each final k1=1,
    each final k2=1)
    if haveConExtWin
    "Sum of radiosity flows from room surfaces toward the window"

  HeatTransfer.Radiosity.RadiositySplitter radShaOut[NConExtWin]
  if haveConExtWin
    "Splitter for radiosity that strikes shading device or unshaded part of window"

  Modelica.Blocks.Math.Sum sumJFroWin[NConExtWin](each nin=if haveShade then 2
         else 1)
    if haveConExtWin "Sum of radiosity fom window to room surfaces"

  Modelica.Thermal.HeatTransfer.Sources.PrescribedTemperature TSha[NConExtWin]
    if haveShade "Temperature of shading device"

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

equation
  connect(conBou.opa_a, surf_conBou)
  connect(bouConExtWin.opa_a, conExtWin.opa_a)
  connect(conExtWin.JInUns_a, bouConExtWin.JOutUns)
  connect(bouConExtWin.JInUns, conExtWin.JOutUns_a)
  connect(conExtWin.glaUns_a, bouConExtWin.glaUns)
  connect(bouConExtWin.glaSha, conExtWin.glaSha_a)
  connect(conExtWin.JInSha_a, bouConExtWin.JOutSha)
  connect(bouConExtWin.JInSha, conExtWin.JOutSha_a)
  connect(conExtWin.fra_a, bouConExtWin.fra)
  connect(conExt.opa_a, bouConExt.opa_a)
  connect(weaBus, bouConExtWin.weaBus)
  connect(weaBus, bouConExt.weaBus)
  connect(bouConExtWin.QAbsSolSha_flow, conExtWinRad.QAbsExtSha_flow)
  connect(bouConExtWin.inc, conExtWinRad.incAng)
  connect(bouConExtWin.HDir, conExtWinRad.HDir)
  connect(bouConExtWin.HDif, conExtWinRad.HDif)
  connect(conExtWin.QAbsSha_flow, conExtWinRad.QAbsGlaSha_flow)
  connect(conExtWinRad.QAbsGlaUns_flow, conExtWin.QAbsUns_flow)
 // Connect statements from the model BaseClasses.MixedAir
  connect(conExt.opa_b, irRadExc.conExt)
  connect(conExtWin.fra_b, irRadExc.conExtWinFra)
  connect(conPar.opa_a, irRadExc.conPar_a)
  connect(conPar.opa_b, irRadExc.conPar_b)

  connect(conBou.opa_b, irRadExc.conBou)

  connect(surf_surBou, irRadExc.conSurBou)
  connect(irRadGai.conExt, conExt.opa_b)
  connect(irRadGai.conExtWinFra, conExtWin.fra_b)
  connect(irRadGai.conPar_a, conPar.opa_a)
  connect(irRadGai.conPar_b, conPar.opa_b)
  connect(irRadGai.conBou, conBou.opa_b)
  connect(irRadGai.conSurBou, surf_surBou)

  connect(conExtWin.opa_b, irRadExc.conExtWin)
  connect(conExtWin.opa_b, irRadGai.conExtWin)

  connect(conExt.opa_b, solRadExc.conExt)
  connect(conExtWin.fra_b, solRadExc.conExtWinFra)
  connect(conPar.opa_a, solRadExc.conPar_a)
  connect(conPar.opa_b, solRadExc.conPar_b)
  connect(conBou.opa_b, solRadExc.conBou)
  connect(surf_surBou, solRadExc.conSurBou)
  connect(conExtWin.opa_b, solRadExc.conExtWin)
  connect(solRadExc.JInDifConExtWin, conExtWinRad.QTraDif_flow)
  connect(solRadExc.HOutConExtWin,conExtWinRad.HRoo)
  connect(conExt.opa_b, radTem.conExt)
  connect(conExtWin.opa_b, radTem.conExtWin)
  connect(conExtWin.fra_b, radTem.conExtWinFra)
  connect(conPar.opa_a, radTem.conPar_a)
  connect(conPar.opa_b, radTem.conPar_b)

  connect(conBou.opa_b, radTem.conBou)

  connect(surf_surBou, radTem.conSurBou)

  connect(radTem.glaUns, conExtWin.glaUns_b)
  connect(radTem.glaSha, conExtWin.glaSha_b)

  connect(radTem.TRad, radiationAdapter.TRad)
  connect(radiationAdapter.rad, heaPorRad)

  connect(radiationAdapter.QRad_flow, add.u1)
  connect(add.y, irRadGai.Q_flow)
  connect(irRadExc.JOutConExtWin, sumJToWin.u1)
  connect(irRadGai.JOutConExtWin, sumJToWin.u2)
  connect(shaSig.y, radShaOut.u)
  connect(shaSig.y, shaRad.u)

  connect(sumJToWin.y, radShaOut.JIn)
  connect(radShaOut.JOut_1, shaRad.JIn_air)
  connect(radShaOut.JOut_2, conExtWin.JInUns_b)
  connect(shaRad.JOut_glass, conExtWin.JInSha_b)
  connect(conExtWin.JOutSha_b, shaRad.JIn_glass)

  connect(irRadExc.JInConExtWin, sumJFroWin.y)

  connect(shaRad.QSolAbs_flow, conExtWinRad.QAbsIntSha_flow)
  connect(sumJFroWin.u[1], conExtWin.JOutUns_b)
  connect(sumJFroWin.u[2], shaRad.JOut_air)
  connect(radTem.sha, TSha.port)

  for i in 1:nPorts loop
    connect(ports[i],air. ports[i])
  end for;

  connect(air.conExt, conExt.opa_b)
  connect(air.conExtWin, conExtWin.opa_b)
  connect(air.glaUns, conExtWin.glaUns_b)
  connect(air.glaSha, conExtWin.glaSha_b)
  connect(air.conExtWinFra, conExtWin.fra_b)
  connect(air.conPar_a, conPar.opa_a)
  connect(air.conPar_b, conPar.opa_b)
  connect(air.conBou, conBou.opa_b)
  connect(air.conSurBou, surf_surBou)
  connect(shaRad.QRadAbs_flow,air. QRadAbs_flow)

  connect(air.TSha, shaRad.TSha)

  connect(air.heaPorAir, heaPorAir)
  connect(air.TSha, TSha.T)

  connect(uWin, conExtWinRad.uSta)
  connect(qGai_flow,heaGai. qGai_flow)
  connect(air.QCon_flow,heaGai. QCon_flow)
  connect(air.QLat_flow,heaGai. QLat_flow)
  connect(heaGai.QRad_flow, add.u2)
  connect(conExtWinRad.QTraDir_flow, solRadExc.JInDirConExtWin)
end RoomHeatMassBalance;


Record for window side fins. This record declares parameters for window side fins.

within Buildings.ThermalZones.Detailed.BaseClasses;
record SideFins "Record for window side fins"
  extends Modelica.Icons.Record;
  parameter Modelica.Units.SI.Length h(min=0)
    "Height of side fin that extends above window, measured from top of window"
  parameter Modelica.Units.SI.Length dep(min=0)
    "Side fin depth (measured perpendicular to the wall plane)"
  parameter Modelica.Units.SI.Length gap(min=0)
    "Distance between side fin and window edge"

  final parameter Boolean haveSideFins= dep > Modelica.Constants.eps
    "Flag, true if the window has side fins"

end SideFins;


Radiative heat exchange with the sky and the ambient.

within Buildings.ThermalZones.Detailed.BaseClasses;
model SkyRadiationExchange
  "Radiative heat exchange with the sky and the ambient"
  extends Buildings.BaseClasses.BaseIcon;
  parameter Integer n(min=1) "Number of constructions";
  parameter Modelica.Units.SI.Area A[n] "Area of exterior constructions";
  parameter Real vieFacSky[n](
    each min=0,
    each max=1) "View factor to sky (=1 for roofs)";
  parameter Modelica.Units.SI.Emissivity absIR[n]
    "Infrared absorptivity of building surface";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port[n] "Heat port"
  Modelica.Blocks.Interfaces.RealInput TOut(final quantity="ThermodynamicTemperature",
                                            final unit = "K", min=0)
    "Outside air temperature"
  Modelica.Blocks.Interfaces.RealInput TBlaSky(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    min=0) "Black body sky temperature"
protected
  parameter Real k[n](
    each unit="W/K4") = {4*A[i]*Modelica.Constants.sigma*absIR[i] for i in 1:n}
    "Constant for radiative heat exchange";
  Modelica.Units.SI.Temperature TEnv[n] "Environment temperature";
  Real TBlaSky4(unit="K4") "Auxiliary variable for radiative heat exchange";
  Real TOut4(unit="K4") "Auxiliary variable for radiative heat exchange";
  Modelica.Units.SI.CoefficientOfHeatTransfer h[n]
    "Radiative heat transfer coefficient";

equation
  TBlaSky4 = TBlaSky^4;
  TOut4 = TOut^4;
  for i in 1:n loop
    TEnv[i] = (vieFacSky[i] * TBlaSky4 + (1-vieFacSky[i]) * TOut4)^(0.25);
    // h[i] uses TEnv[i] instead of (port[i].T+TEnv[i])/2 to avoid
    // a nonlinear equation system
    h[i]  = k[i] * TEnv[i]^3;
    port[i].Q_flow = h[i] * (port[i].T-TEnv[i]);
  end for;
end SkyRadiationExchange;


Solar radiation heat exchange between the room facing surfaces. This model computes the distribution of the solar radiation gain
to the room surfaces.
Let
Nw
denote the number of windows,
Nf
the number of floor elements and
Nn
the number of non-floor elements such as ceiling, wall and window elements.
Input to the model are the diffuse and direct solar radiosities
Jidif, i ∈ {1, … , Nw}
and
Jidir, i ∈ {1, … , Nw}
that were transmitted through the window.
The total incoming solar radiation is therefore for the diffuse irradiation

within Buildings.ThermalZones.Detailed.BaseClasses;
model SolarRadiationExchange
  "Solar radiation heat exchange between the room facing surfaces"
  extends Buildings.ThermalZones.Detailed.BaseClasses.PartialSurfaceInterfaceRadiative(
  final epsConExt = datConExt.layers.absSol_b,
  final epsConExtWinOpa = datConExtWin.layers.absSol_b,
  final epsConExtWinUns={(1-datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].tauSol[1]
                     -datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].rhoSol_b[1]) for i in 1:NConExtWin},
  final epsConExtWinSha = {(1-datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].tauSol[1]
                       -datConExtWin[i].glaSys.glass[size(datConExtWin[i].glaSys.glass, 1)].rhoSol_b[1]) for i in 1:NConExtWin},
  final epsConExtWinFra = datConExtWin.glaSys.absSolFra,
  final epsConPar_a = datConPar.layers.absSol_a,
  final epsConPar_b = datConPar.layers.absSol_b,
  final epsConBou = datConBou.layers.absSol_b,
  final epsSurBou = surBou.absSol);
  // In the above declaration, we simplified the assignment of epsConExtWinSha.
  // An exact formulation would need to take into account the transmission and reflection
  // of the shade for the solar radiation that strikes the window from the room-side.
  // The simplification leads to too low a value of epsConExtWinSha. Since epsConExtWinSha
  // is used as a weight for how much solar radiation hits the window from the room-side,
  // underestimating epsConExtWinSha does not seem to cause concerns. The reason is that
  // the model assumes diffuse reflection, whereas in reality, reflection of the solar
  // radiation at the floor is likely specular, and therefore less radiation would hit
  // the window from the room-side.
  parameter Boolean is_floorConExt[NConExt]
    "Flag to indicate if floor for exterior constructions";
  parameter Boolean is_floorConExtWin[NConExtWin]
    "Flag to indicate if floor for constructions";
  parameter Boolean is_floorConPar_a[NConPar]
    "Flag to indicate if floor for constructions";
  parameter Boolean is_floorConPar_b[NConPar]
    "Flag to indicate if floor for constructions";
  parameter Boolean is_floorConBou[NConBou]
    "Flag to indicate if floor for constructions with exterior boundary conditions exposed to outside of room model";
  parameter Boolean is_floorSurBou[NSurBou]
    "Flag to indicate if floor for constructions that are modeled outside of this room";

  parameter Modelica.Units.SI.Emissivity tauGla[NConExtWin]
    "Transmissivity of window";

  Modelica.Blocks.Interfaces.RealInput JInDifConExtWin[NConExtWin](each unit="W")
    "Diffuse solar radiation transmitted by window per unit area"
  Modelica.Blocks.Interfaces.RealInput JInDirConExtWin[NConExtWin](each unit="W")
    "Direct solar radiation transmitted by window per unit area"

  Modelica.Blocks.Interfaces.RealOutput HOutConExtWin[NConExtWin](each unit="W/m2")
    "Outgoing solar radiation that strikes window per unit area"

  Modelica.Units.SI.HeatFlowRate JOutConExtWin[NConExtWin]
    "Outgoing solar radiation that strikes the window";

protected
  final parameter Real kDir1(unit="1", fixed=false)
    "Intermediate variable for gain for direct solar radiation distribution";
  final parameter Real kDir2(fixed=false)
    "Intermediate variable for gain for solar radiation distribution";
  Modelica.Units.SI.HeatFlowRate Q_flow[NTot]
    "Total solar radiation that is absorbed by the surfaces (or transmitted back through the glass)";
  final parameter Integer NOpa = NConExt+2*NConExtWin+2*NConPar+NConBou+NSurBou
    "Number of opaque surfaces, including the window frame";
  final parameter Integer NWin = NConExtWin "Number of window surfaces";
  final parameter Integer NTot = NOpa + NWin "Total number of surfaces";
  final parameter Boolean is_flo[NTot](each fixed=false)
    "Flag, true if a surface is a floor";
  final parameter Real eps[NTot](each min=0, each max=1, each fixed=false)
    "Solar absorptivity";
  final parameter Real tau[NTot](each min=0, each max=1, each fixed=false)
    "Solar transmissivity";
  final parameter Modelica.Units.SI.Area AFlo(fixed=false) "Total floor area";
  final parameter Modelica.Units.SI.Area A[NTot](each fixed=false)
    "Surface areas";
  final parameter Real kDif[NTot](
    each unit="1",
    each fixed=false)
    "Gain for diffuse solar radiation distribution";
  final parameter Real kDir[NTot](
    each unit="1",
    each fixed=false)
    "Gain for direct solar radiation distribution";
  final parameter Real epsTauA[NTot](
    each unit="m2",
    each fixed=false) "Product (eps[i]+tau[i])*A[i] for all surfaces";
  final parameter Real sumEpsTauA(unit="m2", fixed=false)
    "Sum(epsTauA)";
initial equation
  // The next loops builds arrays that simplify
  // the model equations.
  // These arrays store the values of the constructios in the following order
  // [x[1:NConExt] x[1:NConPar] x[1: NConPar] x[1: NConBou] x[1: NSurBou] x[1: NConExtWin] x[1: NConExtWin]]
  // where x is epsOpa, AOpa or kOpa.
  // The last two entries are for the opaque wall that contains a window, and for the window frame.
  for i in 1:NConExt loop
    eps[i] = epsConExt[i];
    A[i]      = AConExt[i];
    is_flo[i]  = is_floorConExt[i];
  end for;
  for i in 1:NConPar loop
    eps[i+NConExt]           = epsConPar_a[i];
    A[i+NConExt]             = AConPar[i];
    is_flo[i+NConExt]         = is_floorConPar_a[i];
    eps[i+NConExt+NConPar]   = epsConPar_b[i];
    A[i+NConExt+NConPar]     = AConPar[i];
    is_flo[i+NConExt+NConPar] = is_floorConPar_b[i];
  end for;
  for i in 1:NConBou loop
    eps[i+NConExt+2*NConPar]   = epsConBou[i];
    A[i+NConExt+2*NConPar]     = AConBou[i];
    is_flo[i+NConExt+2*NConPar] = is_floorConBou[i];
  end for;
  for i in 1:NSurBou loop
    eps[i+NConExt+2*NConPar+NConBou]   = epsSurBou[i];
    A[i+NConExt+2*NConPar+NConBou]     = ASurBou[i];
    is_flo[i+NConExt+2*NConPar+NConBou] = is_floorSurBou[i];
  end for;

  for i in 1:NConExtWin loop
    // Opaque part of construction that has a window embedded
    eps[i+NConExt+2*NConPar+NConBou+NSurBou]   = epsConExtWinOpa[i];
    A[i+NConExt+2*NConPar+NConBou+NSurBou]     = AConExtWinOpa[i];
    is_flo[i+NConExt+2*NConPar+NConBou+NSurBou] = is_floorConExtWin[i];
    // Window frame
    eps[i+NConExt+2*NConPar+NConBou+NSurBou+NConExtWin]   = epsConExtWinFra[i];
    A[i+NConExt+2*NConPar+NConBou+NSurBou+NConExtWin]     = AConExtWinFra[i];
    is_flo[i+NConExt+2*NConPar+NConBou+NSurBou+NConExtWin] = is_floorConExtWin[i];
  end for;
  // Window glass
  for i in 1:NConExtWin loop
    // We simplify and assume that the shaded and unshaded part of the window
    // have the same solar absorbtance.
    // A further simplification is that the window is assumed to have the
    // optical properties of state 1, which for electrochromic windows is
    // the uncontrolled state. The error should be small as in the controlled state,
    // there is little solar radiation entering the room, and with this simplification,
    // the main error is that the radiation that is reflected in the room and hits the
    // window is larger than it otherwise would be.
    // This simplification allows lumping the solar distribution into
    // a parameter.
    eps[i+NConExt+2*NConPar+NConBou+NSurBou+2*NConExtWin] = epsConExtWinUns[i];
    is_flo[i+NConExt+2*NConPar+NConBou+NSurBou+2*NConExtWin] = is_floorConExtWin[i];
    A[i+NConExt+2*NConPar+NConBou+NSurBou+2*NConExtWin] = AConExtWinGla[i];
  end for;
  // Vector with all surface areas.
  // The next loops build the array A that simplifies
  // the model equations.
  // These array stores the values of the constructios in the following order
  // [AOpa[1:NConExt] AOpa[1:NConPar] AOpa[1: NConPar] AOpa[1: NConBou] AOpa[1: NSurBou]
  //  AOpa[1: NConExtWin] AOpa[1: NConExtWin] AGla[1: NConExtWin]]
  // since NWin=NConExtWin.

  // Solar transmissivity
  for i in 1:NOpa loop
    tau[i] = 0;
  end for;
  for i in 1:NWin loop
    tau[NOpa+i] = tauGla[i];
  end for;

  // Sum of surface areas and products of emmissivity, transmissivity and area
  AFlo = sum( (if is_flo[i] then A[i] else 0) for i in 1:NTot);
  epsTauA = (eps .+ tau).*A;
  sumEpsTauA = sum(epsTauA[i] for i in 1:NTot);

  // Coefficients for distribution of diffuse solar irradiation inside the room.
  for i in 1:NTot loop
    kDif[i] = (eps[i] + tau[i])*A[i]/sumEpsTauA;
  end for;

  // Coefficients for distribution of direct solar radiation inside the room.
  // Coefficient that is used for non-floor areas.
  // The expression  max(1E-20, AFlo) is used to prevent a division by zero in case AFlo=0.
  // The situation for AFlo=0 is caught by the assert statement.
  kDir1 = sum((if is_flo[i] then (A[i]*(1 - eps[i] - tau[i])) else 0) for i in 1:
    NTot)/max(1E-20, AFlo);

  kDir2 = sum((if is_flo[i] then 0 else epsTauA[i]) for i in 1:NTot);

  if (kDir2 > 1E-10) then
    for i in 1:NTot loop
      if is_flo[i] then
        kDir[i] = epsTauA[i]/AFlo;
      else
        kDir[i] =kDir1/kDir2*epsTauA[i];
      end if;
     end for;
  else
        // This branch only happens if k2=0, i.e., there is no surface other than floors
    for i in 1:NTot loop
      if is_flo[i] then
        kDir[i] = A[i]/AFlo;
      else
        kDir[i] = 0;
      end if;
    end for;
  end if;

  // Test whether there is a floor inside this room
  assert( AFlo > 1E-10,
     "Error in parameters of the room model: The geometry is incorrect:\n" +
     "    The room model must have a construction that is a floor,\n" +
     "    and this construction must not have a window.\n" +
     "    The parameters for the room model are such that there is no such construction.\n" +
     "    Revise the model parameters.");
  // Test whether the distribution factors add up to one
  assert(abs(1 - sum(kDif)) < 1E-5, "Program error: Sum of diffuse solar distribution factors in room is not equal to one. kDif="
     + String(sum(kDif)));
  assert(abs(1 - sum(kDir)) < 1E-5, "Program error: Sum of direct solar distribution factors in room is not equal to one. kDir="
     + String(sum(kDir)));
////////////////////////////////////////////////////////////////////
equation
  // Radiation that is absorbed by the surfaces
  Q_flow =-kDif .* sum(JInDifConExtWin) - kDir .* sum(JInDirConExtWin);
  // Assign heat exchange to connectors
  if haveConExt then
    for i in 1:NConExt loop
      Q_flow[i] = conExt[i].Q_flow;
    end for;
  else
    conExt[1].T = 293.15;
  end if;

  if haveConPar then
    for i in 1:NConPar loop
      Q_flow[i+NConExt]         = conPar_a[i].Q_flow;
      Q_flow[i+NConExt+NConPar] = conPar_b[i].Q_flow;
    end for;
  else
      conPar_a[1].T = 293.15;
      conPar_b[1].T = 293.15;
  end if;

  if haveConBou then
    for i in 1:NConBou loop
      Q_flow[i+NConExt+2*NConPar] = conBou[i].Q_flow;
    end for;
  else
    conBou[1].T = 293.15;
  end if;

  if haveSurBou then
    for i in 1:NSurBou loop
      Q_flow[i+NConExt+2*NConPar+NConBou] = conSurBou[i].Q_flow;
     end for;
  else
      conSurBou[1].T = 293.15;
  end if;

  if haveConExtWin then
    for i in 1:NConExtWin loop
      Q_flow[i+NConExt+2*NConPar+NConBou+NSurBou]            = conExtWin[i].Q_flow;
      Q_flow[i+NConExt+2*NConPar+NConBou+NSurBou+NConExtWin] = conExtWinFra[i].Q_flow;
    end for;
  else
    conExtWin[1].T    = 293.15;
    conExtWinFra[1].T = 293.15;
  end if;
  // Windows
  for j in 1:NWin loop
    Q_flow[j+NOpa] = JOutConExtWin[j];
    HOutConExtWin[j] = if (AConExtWinGla[j] > 1E-10) then JOutConExtWin[j] / AConExtWinGla[j] else 0;
  end for;
end SolarRadiationExchange;


Add unit [W] to data.

within Buildings.ThermalZones.Detailed.BaseClasses;
block to_W "Add unit [W] to data"
  extends Modelica.Blocks.Icons.Block;

  Modelica.Blocks.Interfaces.RealInput u
  Modelica.Blocks.Interfaces.RealOutput y(final quantity="Power", final unit=
        "W") "Power"
equation
  y = u;
end to_W;


Test model for the HeatGain model

within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
model HeatGain "Test model for the HeatGain model"
  extends Modelica.Icons.Example;

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

  parameter Modelica.Units.SI.Area AFlo=50 "Floor area";

  Buildings.ThermalZones.Detailed.BaseClasses.HeatGain heatGain(
    AFlo=AFlo)
  Modelica.Blocks.Sources.Constant qConGai_flow(k=10) "Convective heat gain"
  Modelica.Blocks.Sources.Constant qRadGai_flow1(k=5) "Radiative heat gain"
  Modelica.Blocks.Routing.Multiplex3 multiplex3_1
  Modelica.Blocks.Sources.Constant qLatGai_flow(k=12) "Latent heat gain"
equation
  connect(qRadGai_flow1.y,multiplex3_1. u1[1])
  connect(qConGai_flow.y,multiplex3_1. u2[1])
  connect(qLatGai_flow.y, multiplex3_1.u3[1])
  connect(multiplex3_1.y, heatGain.qGai_flow)
end HeatGain;


Test model for infrared radiation exchange. Test model for the infrared radiation exchange.

within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
model InfraredRadiationExchange "Test model for infrared radiation exchange"
  extends Modelica.Icons.Example;
  extends
    Buildings.ThermalZones.Detailed.BaseClasses.Examples.BaseClasses.PartialInfraredRadiation;
  Buildings.ThermalZones.Detailed.BaseClasses.InfraredRadiationExchange irRadExc(
    nConExt=nConExt,
    nConExtWin=nConExtWin,
    nConPar=nConPar,
    nConBou=nConBou,
    nSurBou=nSurBou,
    final datConExt=datConExt,
    final datConExtWin=datConExtWin,
    final datConPar=datConPar,
    final datConBou=datConBou,
    final surBou=surBou,
    linearizeRadiation=true)
    "Distribution for infrared radiative heat transfer"
  Buildings.HeatTransfer.Radiosity.Constant radSou[NConExtWin](each k=187)
    "Radiosity source for window"
equation
  connect(conConExt.port_a, irRadExc.conExt)
  connect(conConExtWin.port_a, irRadExc.conExtWin)
  connect(conConExtWinFra.port_a, irRadExc.conExtWinFra)
  connect(conConPar_a.port_a, irRadExc.conPar_a)
  connect(conConPar_b.port_a, irRadExc.conPar_b)
  connect(conConBou.port_a, irRadExc.conBou)
  connect(conSurBou.port_a, irRadExc.conSurBou)
  connect(radSou.JOut, irRadExc.JInConExtWin)
end InfraredRadiationExchange;


Test model for infrared radiation gain. Test model for the distribution of the infrared radiation heat gain.

within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
model InfraredRadiationGainDistribution
  "Test model for infrared radiation gain"
  extends Modelica.Icons.Example;
  extends
    Buildings.ThermalZones.Detailed.BaseClasses.Examples.BaseClasses.PartialInfraredRadiation;
  Buildings.ThermalZones.Detailed.BaseClasses.InfraredRadiationGainDistribution irRadGai(
    nConExt=nConExt,
    nConExtWin=nConExtWin,
    nConPar=nConPar,
    nConBou=nConBou,
    nSurBou=nSurBou,
    final datConExt=datConExt,
    final datConExtWin=datConExtWin,
    final datConPar=datConPar,
    final datConBou=datConBou,
    final surBou=surBou,
    haveShade=true)
    "Distribution for infrared radiative heat gains (e.g., due to equipment and people)"
protected
  Modelica.Blocks.Sources.Constant QRad_flow(k=1) "Radiative heat gain"
  Modelica.Blocks.Sources.Constant zer[NConExtWin](each k=0)
    "Outputs zero. This block is needed to send a signal to the shading connector if no window is used in the room model"
equation
  connect(conConExt.port_a, irRadGai.conExt)
  connect(conConExtWin.port_a, irRadGai.conExtWin)
  connect(conConExtWinFra.port_a, irRadGai.conExtWinFra)
  connect(conConPar_a.port_a, irRadGai.conPar_a)
  connect(conConPar_b.port_a, irRadGai.conPar_b)
  connect(conConBou.port_a, irRadGai.conBou)
  connect(conSurBou.port_a, irRadGai.conSurBou)
  connect(QRad_flow.y, irRadGai.Q_flow)
  connect(zer.y, irRadGai.uSha)
end InfraredRadiationGainDistribution;


within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
model MixedAirHeatMassBalance "Test model for air heat and mass balance"
  extends Modelica.Icons.Example;
  extends
    Buildings.ThermalZones.Detailed.BaseClasses.Examples.BaseClasses.PartialInfraredRadiation(
    nConExt=1, nConExtWin=0, nConBou=0, nSurBou=0, nConPar=0);
  package Medium = Buildings.Media.Air "Medium model";

  Buildings.ThermalZones.Detailed.BaseClasses.MixedAirHeatMassBalance air(
    nConExt=nConExt,
    nConExtWin=nConExtWin,
    nConPar=nConPar,
    nConBou=nConBou,
    nSurBou=nSurBou,
    final datConExt=datConExt,
    final datConExtWin=datConExtWin,
    final datConPar=datConPar,
    final datConBou=datConBou,
    final surBou=surBou,
    m_flow_nominal=0.1,
    V=10,
    conMod=Buildings.HeatTransfer.Types.InteriorConvection.Fixed,
    hFixed=3,
    haveShade=datConExtWin[1].glaSys.haveShade,
    redeclare package Medium = Medium,
    nPorts=1,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    use_C_flow=false)
    "Convective heat balance of air"
protected
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conGlaSha[
    NConExtWin](each G=100) "Heat conductor"
  Buildings.HeatTransfer.Sources.FixedTemperature bouConGlaSha[NConExtWin](
      each T=293.15) "Boundary condition"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conGlaUns[
    NConExtWin](each G=100) "Heat conductor"
  Buildings.HeatTransfer.Sources.FixedTemperature bouConGlaUns[NConExtWin](
      each T=293.15) "Boundary condition"
public
  Modelica.Blocks.Sources.Constant uSha[NConExtWin](each k=0)
    "Shade control signal"
protected
  Buildings.ThermalZones.Detailed.BaseClasses.HeatGain heaGai(
    final AFlo=5) "Model to convert internal heat gains"
public
  Modelica.Blocks.Sources.Constant qRadGai_flow(k=0) "Radiative heat gain"
  Modelica.Blocks.Sources.Constant qConGai_flow(k=0) "Convective heat gain"
  Modelica.Blocks.Sources.Constant qLatGai_flow(k=0) "Latent heat gain"
  Modelica.Blocks.Routing.Multiplex3 multiplex3_1
  Modelica.Blocks.Sources.Constant QRadAbs_flow[NConExtWin](each k=0)
    "Radiation absorbed by shade"
  Buildings.Fluid.Sources.Boundary_pT
                              boundary(
    nPorts=1,
    redeclare package Medium = Medium,
    T=293.15) "Boundary condition"
equation
  connect(conConExt.port_a, air.conExt)
  connect(conConExtWin.port_a, air.conExtWin)
  connect(conConExtWinFra.port_a, air.conExtWinFra)
  connect(conConPar_a.port_a, air.conPar_a)
  connect(conConPar_b.port_a, air.conPar_b)
  connect(conConBou.port_a, air.conBou)
  connect(conSurBou.port_a, air.conSurBou)
  connect(bouConGlaUns.port, conGlaUns.port_b)
  connect(conGlaUns.port_a, air.glaUns)
  connect(bouConGlaSha.port, conGlaSha.port_b)
  connect(conGlaSha.port_a, air.glaSha)
  connect(uSha.y, air.uSha)
  connect(multiplex3_1.y, heaGai.qGai_flow)
  connect(QRadAbs_flow.y, air.QRadAbs_flow)

  connect(qRadGai_flow.y, multiplex3_1.u1[1])
  connect(qConGai_flow.y, multiplex3_1.u2[1])
  connect(qLatGai_flow.y, multiplex3_1.u3[1])
  connect(boundary.ports[1], air.ports[1])
  connect(heaGai.QCon_flow, air.QCon_flow)
  connect(air.QLat_flow, heaGai.QLat_flow)
end MixedAirHeatMassBalance;


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


Test model for the radiation temperature. Test model for the radiative temperature of the room.

within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
model RadiationTemperature "Test model for the radiation temperature"
  extends Modelica.Icons.Example;
  extends
    Buildings.ThermalZones.Detailed.BaseClasses.Examples.BaseClasses.PartialInfraredRadiation(
    bouConExt(each T=289.15),
    bouConExtWin(each T=290.15),
    bouConExtWinFra(each T=285.15),
    bouConPar_b(each T=291.15),
    bouConBou(each T=295.15),
    bouSurBou(each T=296.15));

  Buildings.ThermalZones.Detailed.BaseClasses.RadiationTemperature radTem(
    nConExt=nConExt,
    nConExtWin=nConExtWin,
    nConPar=nConPar,
    nConBou=nConBou,
    nSurBou=nSurBou,
    final datConExt=datConExt,
    final datConExtWin=datConExtWin,
    final datConPar=datConPar,
    final datConBou=datConBou,
    final surBou=surBou,
    haveShade=true) "Radiative temperature"

  Modelica.Blocks.Sources.Constant uSha[NConExtWin](each k=0.5)
    "Shade control signal"
protected
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conGlaUns[
    NConExtWin](each G=100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conGlaSha[
    NConExtWin](each G=100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conSha[NConExtWin](
      each G=100) "Heat conductor"
  Buildings.HeatTransfer.Sources.FixedTemperature bouGlaUns[NConExtWin](each T=
        288.15) "Boundary condition"
  Buildings.HeatTransfer.Sources.FixedTemperature bouGlaSha[NConExtWin](each T=
        284.15) "Boundary condition"
  Buildings.HeatTransfer.Sources.FixedTemperature bouSha[NConExtWin](
      each T=293.15) "Boundary condition"
equation
  connect(conConExt.port_a, radTem.conExt)
  connect(conConExtWin.port_a, radTem.conExtWin)
  connect(conConExtWinFra.port_a, radTem.conExtWinFra)
  connect(conConPar_a.port_a, radTem.conPar_a)
  connect(conConPar_b.port_a, radTem.conPar_b)
  connect(conConBou.port_a, radTem.conBou)
  connect(conSurBou.port_a, radTem.conSurBou)

  connect(uSha.y, radTem.uSha)
  connect(bouGlaUns.port, conGlaUns.port_b)
  connect(bouGlaSha.port, conGlaSha.port_b)
  connect(bouSha.port, conSha.port_b)
  connect(radTem.glaUns, conGlaUns.port_a)
  connect(radTem.glaSha, conGlaSha.port_a)
  connect(radTem.sha, conSha.port_a)
end RadiationTemperature;


within Buildings.ThermalZones.Detailed.BaseClasses.Examples;
package BaseClasses "Package with base classes for Buildings.ThermalZones.Detailed.BaseClasses.Examples"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model to test infrared radiation inside the room.

within Buildings.ThermalZones.Detailed.BaseClasses.Examples.BaseClasses;
model PartialInfraredRadiation
  "Partial model to test infrared radiation inside the room"
  extends Buildings.ThermalZones.Detailed.BaseClasses.ConstructionRecords(
  nConExt=1,
  nConExtWin=1,
  nConPar=1,
  nConBou=1,
  nSurBou=1,
  datConExt(each A=1),
  datConBou(each A=1),
  datConExtWin(each A=1, each hWin=1, each wWin=0.5),
  surBou(each A=1),
  datConPar(each A=1));

protected
  Buildings.HeatTransfer.Sources.FixedTemperature bouConExt[NConExt](each T=293.15)
    "Boundary condition"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConExt[NConExt](each G=
        100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConExtWin[
    NConExtWin](each G=100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConExtWinFra[
    NConExtWin](each G=100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConPar_a[NConPar](each G=
        100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConPar_b[NConPar](each G=
        100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conConBou[NConBou](each G=
        100) "Heat conductor"
  Modelica.Thermal.HeatTransfer.Components.ThermalConductor conSurBou[NSurBou](each G=
        100) "Heat conductor"
protected
  Buildings.HeatTransfer.Sources.FixedTemperature bouConExtWin[
    NConExtWin](each T=293.15) "Boundary condition"

  Buildings.HeatTransfer.Sources.FixedTemperature bouConExtWinFra[
    NConExtWin](each T=293.15) "Boundary condition"

  Buildings.HeatTransfer.Sources.FixedTemperature bouConPar_a[NConPar](each T=
       293.15) "Boundary condition"

  Buildings.HeatTransfer.Sources.FixedTemperature bouConPar_b[NConPar](each T=
       293.15) "Boundary condition"

  Buildings.HeatTransfer.Sources.FixedTemperature bouConBou[NConBou](each T=293.15)
    "Boundary condition"

  Buildings.HeatTransfer.Sources.FixedTemperature bouSurBou[NSurBou](each T=293.15)
    "Boundary condition"
equation
  connect(bouConExt.port, conConExt.port_b)
  connect(bouConExtWin.port, conConExtWin.port_b)
  connect(bouConExtWinFra.port, conConExtWinFra.port_b)
  connect(bouConPar_a.port, conConPar_a.port_b)

  connect(bouConPar_b.port, conConPar_b.port_b)
  connect(bouConBou.port, conConBou.port_b)
  connect(bouSurBou.port, conSurBou.port_b)
end PartialInfraredRadiation;


Model for an opaque construction that has no window.

within Buildings.ThermalZones.Detailed.Constructions;
model Construction "Model for an opaque construction that has no window"
  extends Buildings.ThermalZones.Detailed.Constructions.BaseClasses.PartialConstruction(
    final AOpa=A);
end Construction;


Model for an opaque construction that has one window embedded in the construction. This model is used to compute heat transfer through constructions with windows inside the
room model.

within Buildings.ThermalZones.Detailed.Constructions;
model ConstructionWithWindow
  "Model for an opaque construction that has one window embedded in the construction"
  extends Buildings.ThermalZones.Detailed.Constructions.BaseClasses.PartialConstruction(
    final AOpa=A-AWin);

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

  parameter Modelica.Units.SI.Area AWin "Heat transfer area of window"
  parameter Real fFra(
    min=0,
    max=1) = 0.1 "Fraction of window frame divided by total window area"
  final parameter Modelica.Units.SI.Area AFra=fFra*AWin "Frame area"
  final parameter Modelica.Units.SI.Area AGla=AWin - AFra "Glass area"
  parameter Boolean linearizeRadiation = true
    "Set to true to linearize emissive power"

  parameter Boolean steadyStateWindow = false
    "Set to false to add thermal capacity at window, which generally leads to faster simulation"

 replaceable parameter HeatTransfer.Data.GlazingSystems.Generic glaSys
    "Material properties of glazing system"

  HeatTransfer.Windows.Window win(
    final glaSys=glaSys,
    final A=AWin,
    final fFra=fFra,
    final linearize = linearizeRadiation,
    final steadyState = steadyStateWindow,
    final til=til,
    final homotopyInitialization=homotopyInitialization) "Window model"

  HeatTransfer.Interfaces.RadiosityOutflow JOutUns_a
    "Outgoing radiosity that connects to unshaded part of glass at exterior side"
  HeatTransfer.Interfaces.RadiosityInflow JInUns_a
    "Incoming radiosity that connects to unshaded part of glass at exterior side"
  HeatTransfer.Interfaces.RadiosityOutflow JOutSha_a if haveShade
    "Outgoing radiosity that connects to shaded part of glass at exterior side"
  HeatTransfer.Interfaces.RadiosityInflow JInSha_a if haveShade
    "Incoming radiosity that connects to shaded part of glass at exterior side"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaUns_a
    "Heat port at unshaded glass of exterior-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaSha_a if haveShade
    "Heat port at shaded glass of exterior-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a fra_a
    "Heat port at frame of exterior-facing surface"
  Modelica.Blocks.Interfaces.RealInput uSha(min=0, max=1)
    if haveShade
    "Control signal for the shading device, 0: unshaded; 1: fully shaded (removed if no shade is present)"
  HeatTransfer.Interfaces.RadiosityOutflow JOutUns_b
    "Outgoing radiosity that connects to unshaded part of glass at room-side"
  HeatTransfer.Interfaces.RadiosityInflow JInUns_b
    "Incoming radiosity that connects to unshaded part of glass at room-side"
  HeatTransfer.Interfaces.RadiosityOutflow JOutSha_b if haveShade
    "Outgoing radiosity that connects to shaded part of glass at room-side"
  HeatTransfer.Interfaces.RadiosityInflow JInSha_b if haveShade
    "Incoming radiosity that connects to shaded part of glass at room-side"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glaUns_b
    "Heat port at unshaded glass of room-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glaSha_b if haveShade
    "Heat port at shaded glass of room-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b fra_b
    "Heat port at frame of room-facing surface"

  Modelica.Blocks.Interfaces.RealInput QAbsUns_flow[size(glaSys.glass, 1)](
    each unit="W",
    each quantity="Power") "Solar radiation absorbed by unshaded part of glass"
  Modelica.Blocks.Interfaces.RealInput QAbsSha_flow[size(glaSys.glass, 1)](
    each unit="W",
    each quantity="Power") if haveShade
    "Solar radiation absorbed by shaded part of glass"

protected
  final parameter Boolean haveShade = glaSys.haveExteriorShade or glaSys.haveInteriorShade
    "Parameter, equal to true if the window has a shade"

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

equation
  connect(win.uSha, uSha)
  connect(JInUns_a, win.JInUns_a)
  connect(JOutUns_a, win.JOutUns_a)
  connect(win.glaUns_a, glaUns_a)
  connect(win.glaSha_a, glaSha_a)
  connect(win.JInSha_a, JInSha_a)
  connect(win.JOutSha_a, JOutSha_a)
  connect(win.fra_a, fra_a)
  connect(win.JOutUns_b, JOutUns_b)
  connect(win.JInUns_b, JInUns_b)
  connect(win.glaUns_b, glaUns_b)
  connect(win.glaSha_b, glaSha_b)
  connect(win.JOutSha_b, JOutSha_b)
  connect(win.JInSha_b, JInSha_b)
  connect(win.fra_b, fra_b)
  connect(opa.port_a, opa_a)
  connect(opa.port_b, opa_b)
  connect(win.QAbsUns_flow, QAbsUns_flow)
  connect(win.QAbsSha_flow, QAbsSha_flow)
end ConstructionWithWindow;


within Buildings.ThermalZones.Detailed;
package Constructions "Package with models for constructions that are used in the room model"
  extends Modelica.Icons.VariantsPackage;
end Constructions;


within Buildings.ThermalZones.Detailed.Constructions;
package BaseClasses "Package with base classes for Buildings.ThermalZones.Detailed.Constructions"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model for exterior construction that has no window. This is the base class that is used to model opaque constructions in the room model.

within Buildings.ThermalZones.Detailed.Constructions.BaseClasses;
partial model PartialConstruction
  "Partial model for exterior construction that has no window"

  parameter Modelica.Units.SI.Area A "Heat transfer area";
  parameter Modelica.Units.SI.Area AOpa
    "Heat transfer area of opaque construction"

  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic
    layers "Material properties of opaque construction"

  parameter Modelica.Units.SI.Angle til "Surface tilt";

  final parameter Boolean is_floor=til > 2.74889125 and til < 3.53428875
    "Flag, true if construction is a floor"
  final parameter Boolean is_ceiling=til > -0.392699 and til < 0.392699
    "Flag, true if construction is a floor"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a opa_a
    "Heat port at surface a of opaque construction"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b opa_b
    "Heat port at surface b of opaque construction"

  final parameter Integer nLay(min=1, fixed=true) = size(layers.material, 1)
    "Number of layers";
  final parameter Integer nSta[nLay](each min=1)=
    {layers.material[i].nSta for i in 1:nLay} "Number of states"
  parameter Boolean steadyStateInitial=false
    "=true initializes dT(0)/dt=0, false initializes T(0) at fixed temperature using T_a_start and T_b_start"
  parameter Modelica.Units.SI.Temperature T_a_start=293.15
    "Initial temperature at port_a, used if steadyStateInitial = false"
  parameter Modelica.Units.SI.Temperature T_b_start=293.15
    "Initial temperature at port_b, used if steadyStateInitial = false"

  parameter Boolean stateAtSurface_a=true
    "=true, a state will be at the surface a"
  parameter Boolean stateAtSurface_b=true
    "=true, a state will be at the surface b"

  HeatTransfer.Conduction.MultiLayer opa(
    final A=AOpa,
    final layers=layers,
    final steadyStateInitial=steadyStateInitial,
    final stateAtSurface_a = stateAtSurface_a,
    final stateAtSurface_b = stateAtSurface_b,
    final T_a_start=T_a_start,
    final T_b_start=T_b_start)
    "Model for heat transfer through opaque construction"

equation
  connect(opa.port_a, opa_a)
  connect(opa.port_b, opa_b)
end PartialConstruction;


Test model for an exterior wall without a window. This model tests the exterior construction without windows.

within Buildings.ThermalZones.Detailed.Constructions.Examples;
model ExteriorWall "Test model for an exterior wall without a window"
  extends Modelica.Icons.Example;

  parameter HeatTransfer.Data.OpaqueConstructions.Insulation100Concrete200 extConMat
    "Record for material layers"

  parameter Buildings.ThermalZones.Detailed.BaseClasses.ParameterConstruction conPar[1](
    each til=Buildings.Types.Tilt.Wall,
    each azi=0,
    each A=3*10,
    layers={extConMat}) "Data for construction"

  Buildings.ThermalZones.Detailed.Constructions.Construction conExt[1](
    each stateAtSurface_a=false,
    each stateAtSurface_b=false,
    A=conPar[:].A,
    layers=conPar.layers,
    til={Buildings.Types.Tilt.Wall})
    "Construction of an exterior wall without a window"
  Buildings.ThermalZones.Detailed.BaseClasses.ExteriorBoundaryConditions bouConExt(
    nCon=1,
    linearizeRadiation = false,
    conMod=Buildings.HeatTransfer.Types.ExteriorConvection.TemperatureWind,
    conPar=conPar)
    "Exterior boundary conditions for constructions without a window"
  Buildings.HeatTransfer.Sources.PrescribedTemperature prescribedTemperature
  Buildings.HeatTransfer.Convection.Interior con[1](
    A={3*10}, til={Buildings.Types.Tilt.Wall})
    "Model for heat convection"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol(m=1)
    "Thermal collector to link a vector of models to a single model"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))
  Modelica.Blocks.Sources.Constant TRoo(k=273.15 + 20) "Room air temperature"
equation
  connect(prescribedTemperature.port, theCol.port_b)
  connect(theCol.port_a, con.fluid)
  connect(weaDat.weaBus, bouConExt.weaBus)
  connect(TRoo.y, prescribedTemperature.T)
  connect(con.solid, conExt.opa_b)
  connect(bouConExt.opa_a, conExt.opa_a)
end ExteriorWall;


Test model for an exterior wall with two windows, one having a shade, the other not. This model tests the exterior construction with two windows.

within Buildings.ThermalZones.Detailed.Constructions.Examples;
model ExteriorWallTwoWindows
  "Test model for an exterior wall with two windows, one having a shade, the other not"
  extends Modelica.Icons.Example;
  parameter Integer nCon = 2 "Number of constructions";
  parameter Modelica.Units.SI.Area A[:]={3*10,3*10}
    "Heat transfer area of wall and window";
  parameter Modelica.Units.SI.Length hWin[:]={2,1} "Window height";
  parameter Modelica.Units.SI.Length wWin[:]={3,3} "Window width";
  parameter Modelica.Units.SI.Area AWin[:]=hWin .* wWin
    "Heat transfer area of frame and window";
  parameter Real fFra[:]={0.1, 0.1}
    "Fraction of window frame divided by total window area";
  final parameter Modelica.Units.SI.Area AFra[:]=fFra .* AWin "Frame area";
  final parameter Modelica.Units.SI.Area AGla[:]=AWin .- AFra "Glass area";

  parameter Boolean linearizeRadiation = false
    "Set to true to linearize emissive power";
  parameter HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys1(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false) "Record for glazing system"
  parameter HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys2(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false) "Record for glazing system"

  parameter Buildings.ThermalZones.Detailed.BaseClasses.ParameterConstructionWithWindow conPar[nCon](
    each layers = extConMat,
    each til=Buildings.Types.Tilt.Wall,
    each azi=0.017453292519943,
    A=A,
    hWin=hWin,
    wWin=wWin,
    glaSys = {glaSys1, glaSys2}) "Construction parameters"

  parameter HeatTransfer.Data.OpaqueConstructions.Insulation100Concrete200 extConMat
    "Record for material layers"

  ConstructionWithWindow conExt[nCon](
    layers=conPar.layers,
    glaSys=conPar[:].glaSys,
    linearizeRadiation = {linearizeRadiation, linearizeRadiation},
    A=conPar[:].A,
    AWin=conPar[:].hWin .* conPar[:].wWin,
    fFra=conPar[:].fFra,
    til=conPar[:].til) "Construction of an exterior wall with a window"

  Buildings.ThermalZones.Detailed.BaseClasses.ExteriorBoundaryConditionsWithWindow
    bouConExt(
    nCon=2,
    linearizeRadiation = false,
    conMod=Buildings.HeatTransfer.Types.ExteriorConvection.Fixed,
    conPar=conPar)
    "Exterior boundary conditions for constructions with a window"
  Buildings.HeatTransfer.Sources.FixedTemperature TRoo(T=293.15)
    "Room temperature"
  Buildings.HeatTransfer.Convection.Interior con[nCon](A=A - AWin,
    til={Buildings.Types.Tilt.Wall,
         Buildings.Types.Tilt.Wall}) "Model for heat convection"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol(m=2)
    "Thermal collector to link a vector of models to a single model"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))

  Modelica.Blocks.Sources.Constant uSha(k=0) "Shading control signal"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol1(m=2)
    "Thermal collector to link a vector of models to a single model"
  HeatTransfer.Radiosity.IndoorRadiosity indRad[nCon](
    each linearize = linearizeRadiation,
    A=AWin) "Model for indoor radiosity"
  Modelica.Blocks.Routing.Replicator replicator(nout=nCon)
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol3(m=2)
    "Thermal collector to link a vector of models to a single model"
  Modelica.Blocks.Sources.Constant QAbsSha[nCon](each k=0)
    "Solar radiation absorbed by interior shade"
  Modelica.Blocks.Sources.Constant QAbs[nCon, size(glaSys1.glass, 1)](each k=0)
    "Solar radiation absorbed by glass"
  Modelica.Blocks.Sources.Constant QTra[nCon](each k=0)
    "Solar radiation absorbed by exterior shade"

  Buildings.HeatTransfer.Windows.BaseClasses.ShadeRadiation intShaRad[nCon](
    thisSideHasShade={glaSys1.haveInteriorShade, glaSys2.haveInteriorShade},
    each linearize=linearizeRadiation,
    absIR_air={glaSys1.shade.absIR_a, glaSys2.shade.absIR_a},
    absIR_glass={glaSys1.shade.absIR_b, glaSys2.shade.absIR_b},
    tauIR_air={glaSys1.shade.tauIR_a, glaSys2.shade.tauIR_a},
    tauIR_glass={glaSys1.shade.tauIR_b, glaSys2.shade.tauIR_b},
    A=AGla)
  if glaSys1.haveShade or glaSys2.haveShade "Interior shade radiation model"
  Buildings.HeatTransfer.Windows.InteriorHeatTransferConvective intShaCon[nCon](
    A=A,
    fFra=fFra,
    til=conPar[:].til,
    haveExteriorShade={glaSys1.haveExteriorShade, glaSys2.haveExteriorShade},
    haveInteriorShade={glaSys1.haveInteriorShade, glaSys2.haveInteriorShade})
    "Model for interior shade heat transfer"
protected
  Modelica.Blocks.Math.Sum sumJ[nCon](each nin=if glaSys1.haveShade or glaSys2.haveShade
         then 2 else 1) "Sum of radiosity fom glass to outside"
  Buildings.HeatTransfer.Radiosity.RadiositySplitter radShaOut[nCon]
    "Radiosity that strikes shading device"
equation
  connect(TRoo.port, theCol.port_b)
  connect(theCol.port_a, con.fluid)
  connect(weaDat.weaBus, bouConExt.weaBus)
  connect(theCol1.port_b, TRoo.port)

  connect(uSha.y, replicator.u)
  connect(theCol3.port_b, TRoo.port)
  connect(bouConExt.uSha, replicator.y)
  connect(QAbs.y, conExt.QAbsUns_flow)
  connect(QAbs.y, conExt.QAbsSha_flow)
  connect(QTra.y, bouConExt.QAbsSolSha_flow)
  connect(con.solid, conExt.opa_b)
  connect(replicator.y, conExt.uSha)
  connect(conExt.opa_a, bouConExt.opa_a)

  connect(bouConExt.JOutUns, conExt.JInUns_a)
  connect(conExt.JOutUns_a, bouConExt.JInUns)
  connect(bouConExt.glaUns, conExt.glaUns_a)
  connect(bouConExt.glaSha, conExt.glaSha_a)
  connect(bouConExt.JOutSha, conExt.JInSha_a)
  connect(conExt.JOutSha_a, bouConExt.JInSha)
  connect(bouConExt.fra, conExt.fra_a)
  connect(intShaCon.TSha,intShaRad. TSha)
  connect(QAbsSha.y,intShaRad [1].QSolAbs_flow)
  connect(intShaCon.QRadAbs_flow,intShaRad. QRadAbs_flow)
  connect(theCol1.port_a,intShaCon. air)
  connect(intShaRad.JOut_air,sumJ. u[2])
  connect(radShaOut.JOut_1,intShaRad. JIn_air)
  connect(radShaOut.JOut_2, conExt.JInUns_b)
  connect(conExt.JOutUns_b,sumJ. u[1])
  connect(intShaRad.JOut_glass, conExt.JInSha_b)
  connect(intShaRad.JIn_glass, conExt.JOutSha_b)
  connect(conExt.glaUns_b, intShaCon.glaUns)
  connect(intShaCon.glaSha, conExt.glaSha_b)
  connect(conExt.fra_b, intShaCon.frame)
  connect(sumJ.y, indRad.JIn)
  connect(theCol3.port_a, indRad.heatPort)
  connect(replicator.y, radShaOut.u)
  connect(indRad.JOut, radShaOut.JIn)
end ExteriorWallTwoWindows;


Test model for an exterior wall with a window. This model tests the exterior constructions with windows.

within Buildings.ThermalZones.Detailed.Constructions.Examples;
model ExteriorWallWithWindow "Test model for an exterior wall with a window"
  extends Modelica.Icons.Example;
  parameter Modelica.Units.SI.Area A=3*10
    "Heat transfer area of wall and window";
  parameter Modelica.Units.SI.Length hWin=2 "Window height";
  parameter Modelica.Units.SI.Length wWin=3 "Window width";
  parameter Modelica.Units.SI.Area AWin=hWin*wWin
    "Heat transfer area of frame and window";
  parameter Real fFra=0.1
    "Fraction of window frame divided by total window area";
  final parameter Modelica.Units.SI.Area AFra=fFra*AWin "Frame area";
  final parameter Modelica.Units.SI.Area AGla=AWin - AFra "Glass area";
  parameter Boolean linearizeRadiation = false
    "Set to true to linearize emissive power";
  parameter HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveExteriorShade=false,
    haveInteriorShade=false) "Record for glazing system"

  parameter HeatTransfer.Data.OpaqueConstructions.Insulation100Concrete200 extConMat
    "Record for material layers"

  parameter Buildings.ThermalZones.Detailed.BaseClasses.ParameterConstructionWithWindow conPar(
    til=Buildings.Types.Tilt.Wall,
    azi=0,
    layers=extConMat,
    glaSys=glaSys,
    A=A,
    hWin=hWin,
    wWin=wWin) "Data for construction with window"

  ConstructionWithWindow conExt[1](
    layers={conPar.layers},
    glaSys={conPar.glaSys},
    linearizeRadiation = {linearizeRadiation},
    A={conPar.A},
    AWin={conPar.hWin * conPar.wWin},
    fFra={conPar.fFra},
    til={conPar.til}) "Construction of an exterior wall with a window"
  Buildings.ThermalZones.Detailed.BaseClasses.ExteriorBoundaryConditionsWithWindow
    bouConExt(
    nCon=1,
    linearizeRadiation = linearizeRadiation,
    conMod=Buildings.HeatTransfer.Types.ExteriorConvection.Fixed,
    conPar={conPar})
    "Exterior boundary conditions for constructions with a window"
  Buildings.HeatTransfer.Sources.FixedTemperature TRoo(T=293.15)
    "Room temperature"
  Buildings.HeatTransfer.Convection.Interior con[1](
      each A=A .- AWin,
      til={Buildings.Types.Tilt.Wall}) "Model for heat convection"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol(m=1)
    "Thermal collector to link a vector of models to a single model"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat(filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos"))

  Modelica.Blocks.Sources.Constant uSha(k=0) "Shading control signal"
  Modelica.Thermal.HeatTransfer.Components.ThermalCollector theCol1(m=1)
    "Thermal collector to link a vector of models to a single model"
  HeatTransfer.Radiosity.IndoorRadiosity indRad(
    A=AWin,
    linearize=linearizeRadiation) "Model for indoor radiosity"
  Modelica.Blocks.Sources.Constant QAbs[1,size(glaSys.glass, 1)](each k=0)
    "Solar radiation absorbed by glass"
  Modelica.Blocks.Sources.Constant QAbsSha(k=0)
    "Solar radiation absorbed by interior shade"
  Modelica.Blocks.Sources.Constant QTra(k=0)
    "Solar radiation absorbed by exterior shade"

  Buildings.HeatTransfer.Windows.InteriorHeatTransferConvective intShaCon[1](
    each A=A,
    each fFra=fFra,
    each til=conPar.til,
    each haveExteriorShade=glaSys.haveExteriorShade,
    each haveInteriorShade=glaSys.haveInteriorShade)
    "Model for interior shade heat transfer"

  Buildings.HeatTransfer.Windows.BaseClasses.ShadeRadiation intShaRad[1](
    each thisSideHasShade=glaSys.haveInteriorShade,
    each linearize=linearizeRadiation,
    each absIR_air=glaSys.shade.absIR_a,
    each absIR_glass=glaSys.shade.absIR_b,
    each tauIR_air=glaSys.shade.tauIR_a,
    each tauIR_glass=glaSys.shade.tauIR_b,
    each A=AGla)
  if glaSys.haveShade "Interior shade radiation model"
protected
  Modelica.Blocks.Math.Sum sumJ[1](each nin=if glaSys.haveShade then 2 else 1)
    "Sum of radiosity fom glass to outside"

  Buildings.HeatTransfer.Radiosity.RadiositySplitter radShaOut[1]
    "Radiosity that strikes shading device"
equation
  connect(TRoo.port, theCol.port_b)
  connect(theCol.port_a, con.fluid)
  connect(weaDat.weaBus, bouConExt.weaBus)
  connect(theCol1.port_b, TRoo.port)
  connect(indRad.heatPort, TRoo.port)
  connect(uSha.y, bouConExt.uSha[1])

  if glaSys.haveShade then
    connect(uSha.y, conExt[1].uSha)
    connect(QAbs.y, conExt.QAbsSha_flow)
  connect(intShaCon.glaSha, conExt.glaSha_b)
  connect(intShaCon[1].uSha, uSha.y)
  end if;

  connect(QAbs.y, conExt.QAbsUns_flow)

  connect(QTra.y, bouConExt.QAbsSolSha_flow[1])
  connect(conExt.opa_b, con.solid)
  connect(conExt.opa_a, bouConExt.opa_a)

  connect(conExt.JInUns_a, bouConExt.JOutUns)
  connect(conExt.JOutUns_a, bouConExt.JInUns)
  connect(conExt.glaUns_a, bouConExt.glaUns)
  connect(conExt.glaSha_a, bouConExt.glaSha)
  connect(conExt.JInSha_a, bouConExt.JOutSha)
  connect(conExt.JOutSha_a, bouConExt.JInSha)
  connect(conExt.fra_a, bouConExt.fra)
  connect(intShaCon.QRadAbs_flow,intShaRad. QRadAbs_flow)
  connect(intShaCon.TSha,intShaRad. TSha)
  connect(intShaRad.JOut_glass, conExt.JInSha_b)
  connect(intShaRad.JIn_glass, conExt.JOutSha_b)
  connect(conExt.glaUns_b, intShaCon.glaUns)
  connect(theCol1.port_a, intShaCon.air)
  connect(uSha.y, intShaRad[1].u)
  connect(conExt.JOutUns_b, sumJ.u[1])
  connect(intShaRad.JOut_air, sumJ.u[2])
  connect(radShaOut[1].u, uSha.y)
  connect(radShaOut.JOut_1, intShaRad.JIn_air)
  connect(radShaOut.JOut_2, conExt.JInUns_b)
  connect(QAbsSha.y, intShaRad[1].QSolAbs_flow)
  connect(indRad.JOut, radShaOut[1].JIn)
  connect(indRad.JIn, sumJ[1].y)
  connect(conExt.fra_b, intShaCon.frame)
end ExteriorWallWithWindow;


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


within Buildings.ThermalZones.Detailed.Examples;
model ElectroChromicWindow
  "Model that illustrates the use of electrochromic windows"
  extends Modelica.Icons.Example;
  replaceable package MediumA = Buildings.Media.Air(T_default=T_start) "Medium model";

  constant Modelica.Units.SI.Temperature T_start=273.15 + 20 "Initial value";

  parameter Modelica.Units.SI.Area AFlo=13.94 "Floor area";

  parameter Integer nConExtWin=1 "Number of constructions with a window";
  parameter Integer nConExt=0 "Number of constructions without a window";
  parameter Integer nConBou=5
    "Number of surface that are connected to constructions that are modeled inside the room";
  parameter Integer nSurBou=0
    "Number of surface that are connected to the room air volume";
  parameter Integer nConPar=0 "Number of surface that are partitions";

  MixedAir roo(
    redeclare package Medium = MediumA,
    nConExt=nConExt,
    nConExtWin=nConExtWin,
    nConPar=nConPar,
    nConBou=nConBou,
    nSurBou=nSurBou,
    linearizeRadiation=false,
    T_start=T_start,
    datConExtWin(
      layers={matExtWal},
      each A=10.22,
      glaSys={glaSys},
      each hWin=3.13,
      each wWin=2.782751,
      each fFra=0.000001,
      each til=Buildings.Types.Tilt.Wall,
      azi={Buildings.Types.Azimuth.S}),
    datConBou(
      layers={matFlo,matCeil,matEWWal,matNWal,matEWWal},
      A={13.94,13.94,15.33,10.22,15.33},
      til={Buildings.Types.Tilt.Floor,Buildings.Types.Tilt.Ceiling,Buildings.Types.Tilt.Wall,
          Buildings.Types.Tilt.Wall,Buildings.Types.Tilt.Wall}),
    hRoo=3.37,
    intConMod=Buildings.HeatTransfer.Types.InteriorConvection.Temperature,
    extConMod=Buildings.HeatTransfer.Types.ExteriorConvection.TemperatureWind,
    conBou(opa(T(each start = T_start))),
    nPorts=2,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
    final AFlo=AFlo) "Room model"
  BoundaryConditions.WeatherData.ReaderTMY3 weaDat1(
    relHum=0,
    TDewPoi(displayUnit="K"),
    filNam=
        Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_CA_San.Francisco.Intl.AP.724940_TMY3.mos"),
    pAtmSou=Buildings.BoundaryConditions.Types.DataSource.File,
    calTSky=Buildings.BoundaryConditions.Types.SkyTemperatureCalculation.HorizontalRadiation)

  Modelica.Blocks.Sources.Constant uSha(k=0)
    "Control signal for the shading device"
  Modelica.Blocks.Routing.Replicator replicator(nout=max(1, nConExtWin))
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matExtWal(
    nLay=3,
    absIR_a=0.9,
    absIR_b=0.9,
    absSol_a=0.6,
    absSol_b=0.6,
    material={Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.000701,
        k=45.345,
        c=502.416,
        d=7833.028),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.0127,
        k=0.12,
        c=1210,
        d=540),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.133,
        k=0.047,
        c=1006,
        d=93.84)}) "71T: South Wall"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matCeil(
    nLay=3,
    absIR_a=0.9,
    absIR_b=0.9,
    absSol_a=0.6,
    absSol_b=0.6,
    material={Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.009525,
        k=0.12,
        c=1210,
        d=540),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.133,
        k=0.047,
        c=1006,
        d=93.84),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.015875,
        k=0.17,
        c=1090,
        d=800)}) "71T: Ceiling"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matFlo(
    final nLay=4,
    absIR_a=0.9,
    absIR_b=0.9,
    absSol_a=0.6,
    absSol_b=0.6,
    material={Buildings.HeatTransfer.Data.Solids.Generic(
        x=5.28,
        k=1,
        c=0,
        d=0),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.01905,
        k=0.15,
        c=1630,
        d=608),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.01905,
        k=0.12,
        c=1210,
        d=540),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.22,
        k=1,
        c=0,
        d=0)}) "71T: Floor"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matEWWal(
    final nLay=2,
    absIR_a=0.9,
    absIR_b=0.9,
    absSol_a=0.6,
    absSol_b=0.6,
    material={Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.133,
        k=0.047,
        c=1006,
        d=93.84),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.015875,
        k=0.17,
        c=1090,
        d=800)}) "71T: East West Wall"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic matNWal(
    final nLay=4,
    absIR_a=0.9,
    absIR_b=0.9,
    absSol_a=0.6,
    absSol_b=0.6,
    material={Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.015875,
        k=0.17,
        c=1090,
        d=800),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.009525,
        k=0.12,
        c=1210,
        d=540),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.133,
        k=0.047,
        c=1006,
        d=93.84),Buildings.HeatTransfer.Data.Solids.Generic(
        x=0.015875,
        k=0.17,
        c=1090,
        d=800)}) "71T: North Wall"

  parameter HeatTransfer.Data.GlazingSystems.DoubleElectrochromicAir13Clear glaSys(
    UFra=2,
    haveInteriorShade=false,
    haveExteriorShade=false) "Data record for the glazing system"
  BoundaryConditions.WeatherData.Bus weaBus

  Controls.ElectrochromicWindow conWin "Controller for windows"
  Modelica.Thermal.HeatTransfer.Sensors.TemperatureSensor TRooAir
    "Room air temperature"
  Fluid.Sources.MassFlowSource_T bou(
    redeclare package Medium = MediumA,
    m_flow=-47*6/3600*1.2,
    nPorts=1,
    T=293.15) "Boundary condition"
  Fluid.Sources.Outside freshAir(redeclare package Medium = MediumA, nPorts=1)
    "Boundary condition"
  Fluid.FixedResistances.PressureDrop duc(
    redeclare package Medium = MediumA,
    allowFlowReversal=false,
    linearized=true,
    from_dp=true,
    dp_nominal=100,
    m_flow_nominal=47*6/3600*1.2)
    "Duct resistance (to decouple room and outside pressure)"
  Modelica.Blocks.Math.MatrixGain gai(K=120/AFlo*[0.4; 0.4; 0.2])
    "Matrix gain to split up heat gain in radiant, convective and latent gain"
  Modelica.Blocks.Sources.Pulse nPer(
    period(displayUnit="d") = 86400,
    startTime(displayUnit="h") = 25200,
    amplitude=2) "Number of persons"

equation

  connect(uSha.y, replicator.u)
  connect(roo.uSha, replicator.y)

  connect(weaBus, roo.weaBus)
  connect(weaBus, weaDat1.weaBus)
  connect(roo.heaPorAir, TRooAir.port)
  connect(TRooAir.T, conWin.T)
  connect(conWin.H, weaBus.HGloHor)
  connect(conWin.y, roo.uWin[1])
  connect(freshAir.weaBus, weaBus)

  connect(freshAir.ports[1], duc.port_a)
  connect(bou.ports[1], roo.ports[1])
  connect(duc.port_b, roo.ports[2])
  connect(gai.u[1],nPer. y)
  connect(gai.y, roo.qGai_flow)
end ElectroChromicWindow;


within Buildings.ThermalZones.Detailed.Examples;
model MixedAirCO2
  "Mixed air room model with CO2 concentration simulated"
  extends Buildings.ThermalZones.Detailed.Examples.ElectroChromicWindow(
    bou(use_m_flow_in=true),
    redeclare package MediumA = Buildings.Media.Air(extraPropertiesNames={"CO2"}),
    roo(
      use_C_flow=true,
      nPorts=3),
    nPer(
      width=100*2/24,
      amplitude=5,
      startTime=43200));

  parameter Modelica.Units.SI.MassFlowRate mOut_flow=47*2/3600*1.2
    "Typical outside air mass flow rate, unless increased by controller";

  Modelica.Blocks.Math.Gain gaiCO2(k=8.18E-6) "CO2 emission per person"
  Buildings.Fluid.Sensors.PPM senCO2(
    redeclare package Medium = MediumA,
    warnAboutOnePortConnection=false,
    MM=Modelica.Media.IdealGases.Common.SingleGasesData.CO2.MM)
    "CO2 sensor that measures concentration in the room"
  Modelica.Blocks.Sources.Constant CO2Set(k=700)
    "CO2 set point in PPM above the initial value"
  Modelica.Blocks.Math.Gain norCO2Set(k=1/700)
    "Normalization for CO2 set point"
  Modelica.Blocks.Math.Gain norCO2Mea(k=1/700)
    "Normalization for CO2 measurement"
  Buildings.Controls.Continuous.LimPID conPI(
    k=5,
    Ti=120,
    yMax=10,
    yMin=0,
    reverseActing=false)
    "PI controller for fresh air supply, with negative minimum because of reverse action"
  Buildings.Controls.OBC.CDL.Reals.AddParameter addFlo(
    p = 1)
    "Gain that increases the mass flow rate above its typical value"
  Buildings.Controls.OBC.CDL.Reals.MultiplyByParameter gaiFac(
    k=-mOut_flow)
    "Gain that increases the mass flow rate above its typical value"

equation
  connect(roo.C_flow[1], gaiCO2.y)
  connect(nPer.y, gaiCO2.u)
  connect(senCO2.port, roo.ports[3])
  connect(CO2Set.y, norCO2Set.u)
  connect(senCO2.ppm, norCO2Mea.u)
  connect(norCO2Set.y, conPI.u_s)
  connect(norCO2Mea.y, conPI.u_m)
  connect(conPI.y,addFlo. u)
  connect(addFlo.y, gaiFac.u)
  connect(gaiFac.y, bou.m_flow_in)
end MixedAirCO2;


Free response of room model

within Buildings.ThermalZones.Detailed.Examples;
model MixedAirFreeResponse "Free response of room model"
  extends Modelica.Icons.Example;
  package Medium = Buildings.Media.Air "Medium model";

  parameter Buildings.HeatTransfer.Data.Solids.Plywood matWoo(
    x=0.01,
    k=0.11,
    d=544,
    nStaRef=1) "Wood for exterior construction"
  parameter Buildings.HeatTransfer.Data.Solids.Concrete matCon(
    x=0.1,
    k=1.311,
    c=836,
    nStaRef=5) "Concrete"
  parameter Buildings.HeatTransfer.Data.Solids.Generic matIns(
    x=0.087,
    k=0.049,
    c=836.8,
    d=265,
    nStaRef=5) "Steelframe construction with insulation"
  parameter Buildings.HeatTransfer.Data.Solids.GypsumBoard matGyp(
    x=0.0127,
    k=0.16,
    c=830,
    d=784,
    nStaRef=2) "Gypsum board"
  parameter Buildings.HeatTransfer.Data.Solids.GypsumBoard matGyp2(
    x=0.025,
    k=0.16,
    c=830,
    d=784,
    nStaRef=2) "Gypsum board"
  parameter Buildings.HeatTransfer.Data.Solids.Plywood matFur(x=0.15, nStaRef=5)
    "Material for furniture"
  parameter Buildings.HeatTransfer.Data.Solids.Plywood matCarTra(
    x=0.215/0.11,
    k=0.11,
    d=544,
    nStaRef=1) "Wood for floor"
  parameter Buildings.HeatTransfer.Data.Resistances.Carpet matCar "Carpet"
  parameter Buildings.HeatTransfer.Data.GlazingSystems.DoubleClearAir13Clear glaSys(
    UFra=2,
    shade=Buildings.HeatTransfer.Data.Shades.Gray(),
    haveInteriorShade=false,
    haveExteriorShade=false) "Data record for the glazing system"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic conExtWal(
    final nLay=3,
    material={matWoo,matIns,matGyp}) "Exterior construction"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic conIntWal(
    final nLay=1,
    material={matGyp2}) "Interior wall construction"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic conFlo(
    final nLay=1,
    material={matCon}) "Floor construction (opa_a is carpet)"
  parameter Buildings.HeatTransfer.Data.OpaqueConstructions.Generic conFur(
    final nLay=1,
    material={matFur}) "Construction for internal mass of furniture"

  parameter String weaFil = Modelica.Utilities.Files.loadResource("modelica://Buildings/Resources/weatherdata/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.mos")
   "Weather data file";
  parameter Modelica.Units.SI.Volume VRoo=4555.7 "Room volum";
  parameter Modelica.Units.SI.Height hRoo=2.74 "Room height";
  parameter Modelica.Units.SI.Length hWin=1.5 "Height of windows";
  parameter Real winWalRat(min=0.01,max=0.99) = 0.33
    "Window to wall ratio for exterior walls";
  parameter Modelica.Units.SI.Area AFlo=VRoo/hRoo "Floor area";

  Buildings.ThermalZones.Detailed.MixedAir roo(
    redeclare package Medium = Medium,
    AFlo=AFlo,
    hRoo=hRoo,
    nConExt=0,
    nConExtWin=4,
    datConExtWin(
      layers={conExtWal,conExtWal,conExtWal,conExtWal},
      A={
        49.91*hRoo,
        49.91*hRoo,
        33.27*hRoo,
        33.27*hRoo},
      glaSys={glaSys,glaSys,glaSys,glaSys},
      wWin={
        winWalRat/hWin*49.91*hRoo,
        winWalRat/hWin*49.91*hRoo,
        winWalRat/hWin*33.27*hRoo,
        winWalRat/hWin*33.27*hRoo},
      each hWin=hWin,
      fFra={0.1, 0.1, 0.1, 0.1},
      til={Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall},
      azi={Buildings.Types.Azimuth.N, Buildings.Types.Azimuth.S, Buildings.Types.Azimuth.W, Buildings.Types.Azimuth.E}),
    nConPar=3,
    datConPar(
      layers={conFlo, conFur, conIntWal},
      A={AFlo, AFlo*2, (6.47*2 + 40.76 + 24.13)*2*hRoo},
      til={Buildings.Types.Tilt.Floor, Buildings.Types.Tilt.Wall, Buildings.Types.Tilt.Wall}),
    nConBou=0,
    nSurBou=0,
    energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial) "Floor"

  Modelica.Blocks.Sources.Constant qConGai_flow(k=0) "Convective heat gain"
  Modelica.Blocks.Sources.Constant qRadGai_flow(k=0) "Radiative heat gain"
  Modelica.Blocks.Routing.Multiplex3 multiplex3_1 "Multiplex"
  Modelica.Blocks.Sources.Constant qLatGai_flow(k=0) "Latent heat gain"
  Buildings.BoundaryConditions.WeatherData.ReaderTMY3 weaDat(
    filNam=weaFil,
      computeWetBulbTemperature=false)
  Modelica.Blocks.Sources.Constant uSha(k=0)
    "Control signal for the shading device"
  Modelica.Blocks.Routing.Replicator replicator(nout=4)

equation
  connect(qRadGai_flow.y, multiplex3_1.u1[1])
  connect(qConGai_flow.y, multiplex3_1.u2[1])

  connect(qLatGai_flow.y, multiplex3_1.u3[1])
  connect(multiplex3_1.y, roo.qGai_flow)

  connect(weaDat.weaBus, roo.weaBus)
  connect(uSha.y, replicator.u)
  connect(roo.uSha, replicator.y)
end MixedAirFreeResponse;


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


Controller for electrochromic windows. Controller for electrochromic windows.
If the temperature or the irradiation is below TClear or HClear, then
the window is in the clear state, allowing for passive heating and for view if the room is cool enough.
If the temperature and the irradition is above TDark and HDark, then
the window is in the dark state, thereby protecting the room from too much solar gain.
For each of these measured quantity, the respective control signal is a linear function, with
output limitation between 0 and 1.
The control output of this block is the product of these two control signals. Hence, there is
a continuous transition for intermediate values.

within Buildings.ThermalZones.Detailed.Examples.Controls;
block ElectrochromicWindow "Controller for electrochromic windows"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Irradiance HClear=250
    "Solar irradiation below which the window will be in clear state regardless of temperature";
  parameter Modelica.Units.SI.Irradiance HDark=HClear + 100
    "Solar irradiation at which the window will be in dark state if T > TDark";
  parameter Modelica.Units.SI.Temperature TClear=273.15 + 22
    "Measured temperature below which the window will be in clear state for any irradiation";
  parameter Modelica.Units.SI.Temperature TDark=TClear + 2
    "Measured temperature above which the window will be transitioned to completely dark state if H > HDark";

  Modelica.Blocks.Interfaces.RealInput T(
    quantity="ThermodynamicTemperature",
    unit="K")
    "Temperature used for control"

  Modelica.Blocks.Interfaces.RealInput H(
    quantity="RadiantEnergyFluenceRate",
    unit="W/m2")
    "Direct solar radiation onto window"

  Modelica.Blocks.Interfaces.RealOutput y "Control signal for window"

protected
  Modelica.Blocks.Sources.Constant TLow(final k=TClear) "Lower temperature"

  Modelica.Blocks.Nonlinear.Limiter limT(
    final uMax=1,
    final uMin=0,
    final strict=true) "Limiter for temperature"
  Modelica.Blocks.Math.Feedback feeT "Feedback for temperature"
  Modelica.Blocks.Math.Gain gaiT(final k=1/(TDark - TClear))
    "Gain for temperature"

  Modelica.Blocks.Sources.Constant HLow(final k=HClear) "Lower irradiation"

  Modelica.Blocks.Nonlinear.Limiter limH(
    final uMax=1,
    final uMin=0,
    final strict=true) "Limiter for irradiation"
  Modelica.Blocks.Math.Feedback feeH "Feedback for irradiation"
  Modelica.Blocks.Math.Gain gaiH(final k=1/(HDark - HClear))
    "Gain for irradiation"

  Modelica.Blocks.Math.Product product

equation
  connect(TLow.y, feeT.u2)
  connect(feeT.u1, T)
  connect(feeT.y, gaiT.u)
  connect(gaiT.y, limT.u)
  connect(H, feeH.u1)
  connect(HLow.y, feeH.u2)
  connect(feeH.y, gaiH.u)
  connect(gaiH.y, limH.u)
  connect(limT.y, product.u1)
  connect(limH.y, product.u2)
  connect(product.y, y)
end ElectrochromicWindow;


Package with control models

within Buildings.ThermalZones.Detailed.Examples;
package Controls "Package with control models"
  extends Modelica.Icons.Package;

end Controls;


Validation model for the electrochromic window model. This example checks the correct operation of the window controller.
Two days are emulated. During the days, the room temperature measurement signal
increases. The first day has solar radiation, but not the second.
Therefore, the window control signal switches to the dark state
only during the first day when the room is warm and
the solar irradiation is sufficiently large.

within Buildings.ThermalZones.Detailed.Examples.Controls.Validation;
model ElectrochromicWindow
  "Validation model for the electrochromic window model"
  extends Modelica.Icons.Example;

  Modelica.Blocks.Sources.Trapezoid TMea(
    amplitude=5,
    rising=3600,
    falling=3600,
    period=24*3600,
    width=12*3600,
    startTime=5*3600,
    offset=293.15) "Measured temperature"
  Modelica.Blocks.Sources.Trapezoid HMea(
    period=24*3600,
    nperiod=1,
    rising=2*3600,
    width=4*3600,
    falling=2*3600,
    startTime=7*3600,
    amplitude=500) "Measured irradiation"
  Buildings.ThermalZones.Detailed.Examples.Controls.ElectrochromicWindow conWin
equation
  connect(TMea.y, conWin.T)
  connect(HMea.y, conWin.H)
end ElectrochromicWindow;


Package with validation models

within Buildings.ThermalZones.Detailed.Examples.Controls;
package Validation "Package with validation models"
  extends Modelica.Icons.ExamplesPackage;

end Validation;


within Buildings.ThermalZones.Detailed.Examples.FFD;
model ForcedConvection "Ventilation with forced convection in an empty room"
  extends Modelica.Icons.Example;
  extends Buildings.ThermalZones.Detailed.Examples.FFD.BaseClasses.PartialRoom(
    roo(
      surBou(
        name={"East Wall","West Wall","North Wall","South Wall","Ceiling","Floor"},
        A={0.9,0.9,1,1,1,1},
        til={Buildings.Types.Tilt.Wall,
            Buildings.Types.Tilt.Wall,
            Buildings.Types.Tilt.Wall,
            Buildings.Types.Tilt.Wall,
            Buildings.Types.Tilt.Ceiling,
            Buildings.Types.Tilt.Floor},
        each absIR=1e-5,
        each absSol=1e-5,
        each boundaryCondition= Buildings.ThermalZones.Detailed.Types.CFDBoundaryConditions.Temperature),
      nPorts=2,
      portName={"Inlet","Outlet"},
      cfdFilNam="modelica://Buildings/Resources/Data/ThermalZones/Detailed/Examples/FFD/ForcedConvection.ffd",
      samplePeriod=6,
      linearizeRadiation=true,
      massDynamics=Modelica.Fluid.Types.Dynamics.DynamicFreeInitial),
      nSurBou=6);
  HeatTransfer.Sources.FixedTemperature TWal[nSurBou](each T=283.15)
    "Temperature of other walls"
  Buildings.Fluid.Sources.Boundary_pT bouOut(
    nPorts=1,
    redeclare package Medium = MediumA)
  Fluid.Sources.MassFlowSource_T bounIn(
    nPorts=1,
    redeclare package Medium = MediumA,
    m_flow=0.01,
    T=283.15)
equation
  for i in 1:nSurBou loop
    connect(TWal[i].port, roo.surf_surBou[i])
  end for;
    connect(bounIn.ports[1], roo.ports[1])
  connect(bouOut.ports[1], roo.ports[2])
end ForcedConvection;


A case of natural convection with feedback loop control. This model tests the coupled simulation of

Buildings.ThermalZones.Detailed.CFD
with the FFD program by simulating natural convection in an empty room with a PI controller and
a heater to maintain the temperature at room center to be 2°C.

within Buildings.ThermalZones.Detailed.Examples.FFD;
model NaturalConvectionWithControl
  "A case of natural convection with feedback loop control"
  extends Buildings.ThermalZones.Detailed.Examples.FFD.Tutorial.NaturalConvection(
      roo(
        nPorts=0,
        useCFD=true,
        samplePeriod=30,
        cfdFilNam = "modelica://Buildings/Resources/Data/ThermalZones/Detailed/Examples/FFD/NaturalConvectionWithControl.ffd",
        massDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial));

  HeatTransfer.Sources.PrescribedHeatFlow preHeatFlo
  Buildings.Controls.Continuous.LimPID conPID(
    yMin=0,
    Ti=120,
    k=1,
    yMax=2,
    u_m(final unit="K", displayUnit="degC"),
    u_s(final unit="K", displayUnit="degC"))
  Modelica.Blocks.Sources.Constant TSet(k(final unit="K", displayUnit="degC")=275.15) "Temperature set point"
equation
  connect(roo.yCFD[1], conPID.u_m)
  connect(TSet.y, conPID.u_s)
  connect(preHeatFlo.port, roo.heaPorAir)
  connect(conPID.y, preHeatFlo.Q_flow)
end NaturalConvectionWithControl;


within Buildings.ThermalZones.Detailed.Examples;
package FFD "Package that tests the models for coupled simulation between Modelica and Fast Fluid Dynamics"
  extends Modelica.Icons.ExamplesPackage;
end FFD;