Parameters that are used to model two surfaces with the same area. Parameters that are used for classes with two surfaces.

within Buildings.HeatTransfer.Radiosity.BaseClasses;
model ParametersTwoSurfaces
  "Parameters that are used to model two surfaces with the same area"
  parameter Modelica.Units.SI.Emissivity absIR_a
    "Infrared absorptivity of surface a";
  parameter Modelica.Units.SI.Emissivity absIR_b
    "Infrared absorptivity of surface b";
  parameter Modelica.Units.SI.ReflectionCoefficient rhoIR_a
    "Infrared reflectivity of surface a";
  parameter Modelica.Units.SI.ReflectionCoefficient rhoIR_b
    "Infrared reflectivity of surface b";
  parameter Modelica.Units.SI.TransmissionCoefficient tauIR
    "Infrared transmissivity of glass pane";
  parameter Boolean linearize = false "Set to true to linearize emissive power"
  parameter Modelica.Units.SI.Temperature T0=293.15
    "Temperature used to linearize radiative heat transfer"
protected
 final parameter Real T03(min=0, final unit="K3")=T0^3
    "3rd power of temperature T0";
 final parameter Real T04(min=0, final unit="K4")=T0^4
    "4th power of temperature T0";
initial equation
  assert(abs(1-absIR_a-rhoIR_a-tauIR) < 1E-8,
    "Absorptivity, reflectivity and transmissivity of surface a do not add up to one. Check parameters.");
    assert(abs(1-absIR_b-rhoIR_b-tauIR) < 1E-8,
    "Absorptivity, reflectivity and transmissivity of surface b do not add up to one. Check parameters.");
end ParametersTwoSurfaces;


Model for the radiosity balance of a device with one surface.

within Buildings.HeatTransfer.Radiosity.BaseClasses;
partial model RadiosityOneSurface
  "Model for the radiosity balance of a device with one surface"
  extends Buildings.BaseClasses.BaseIcon;
  parameter Modelica.Units.SI.Area A "Surface area";

  Buildings.HeatTransfer.Interfaces.RadiosityInflow JIn(start=A*0.8*Modelica.Constants.sigma*293.15^4)
    "Incoming radiosity"
  Buildings.HeatTransfer.Interfaces.RadiosityOutflow JOut(start=A*0.8*Modelica.Constants.sigma*293.15^4) "Outgoing radiosity"
end RadiosityOneSurface;


Model for the radiosity balance of a device with two surfaces.

within Buildings.HeatTransfer.Radiosity.BaseClasses;
partial block RadiosityTwoSurfaces
  "Model for the radiosity balance of a device with two surfaces"
  extends Buildings.BaseClasses.BaseIcon;

  parameter Modelica.Units.SI.Area A "Heat transfer area";

  Buildings.HeatTransfer.Interfaces.RadiosityInflow JIn_a(start=A*0.8*Modelica.Constants.sigma*293.15^4)
    "Incoming radiosity at surface a"
  Buildings.HeatTransfer.Interfaces.RadiosityInflow JIn_b(start=A*0.8*Modelica.Constants.sigma*293.15^4)
    "Incoming radiosity at surface b"
  Buildings.HeatTransfer.Interfaces.RadiosityOutflow JOut_a
    "Outgoing radiosity at surface a"
  Buildings.HeatTransfer.Interfaces.RadiosityOutflow JOut_b
    "Outgoing radiosity at surface b"
end RadiosityTwoSurfaces;


Test model for indoor source as an opaque surface. This examples demonstrates two opaque surfaces that radiate toward each other.
The model assumes that the view factor between the surfaces is equal to one.

within Buildings.HeatTransfer.Radiosity.Examples;
model OpaqueSurface "Test model for indoor source as an opaque surface"
  extends Modelica.Icons.Example;

  Buildings.HeatTransfer.Sources.FixedTemperature T2(T=303.15)
    "Boundary condition for surface 2"

  Buildings.HeatTransfer.Radiosity.OpaqueSurface bod1( absIR=0.3, A=1)
    "Surface 1"
  Buildings.HeatTransfer.Sources.FixedTemperature T1(T=293.15)
    "Boundary condition for surface 1"
  Buildings.HeatTransfer.Radiosity.OpaqueSurface bod2( absIR=0.3, A=1)
    "Surface 2"
equation
  connect(T1.port, bod1.heatPort)
  connect(T2.port, bod2.heatPort)
  connect(bod1.JOut, bod2.JIn)
  connect(bod2.JOut, bod1.JIn)
end OpaqueSurface;


Test model for outdoor radiosity.

within Buildings.HeatTransfer.Radiosity.Examples;
model OutdoorRadiosity "Test model for outdoor radiosity"
  extends Modelica.Icons.Example;
  Buildings.HeatTransfer.Radiosity.OpaqueSurface sur(A=A, absIR=1)
    "Receiving surface"
  Buildings.HeatTransfer.Radiosity.OutdoorRadiosity outRad(A=A, vieFacSky=0.5)
    "Outdoor radiosity model"
  parameter Modelica.Units.SI.Area A=1 "Area of receiving surface";
  Modelica.Blocks.Sources.Ramp TSky(
    duration=1,
    height=30,
    offset=273.15) "Sky blackbody temperature"
  Modelica.Blocks.Sources.Constant TAir(k=273.15 + 20)
    "Outside air temperature"
equation
  connect(outRad.JOut, sur.JIn)
  connect(TAir.y, outRad.TBlaSky)
  connect(TSky.y, outRad.TOut)
end OutdoorRadiosity;


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


Fixed heat flow boundary condition. This model allows a specified amount of heat flow rate to be \"injected\"
into a thermal system at a given port.  The constant amount of heat
flow rate Q_flow is given as a parameter. The heat flows into the
component to which the component FixedHeatFlow is connected,
if parameter Q_flow is positive.

within Buildings.HeatTransfer.Sources;
model FixedHeatFlow "Fixed heat flow boundary condition"
  parameter Modelica.Units.SI.HeatFlowRate Q_flow
    "Fixed heat flow rate at port";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port
equation
  port.Q_flow = -Q_flow;
end FixedHeatFlow;


Fixed temperature boundary condition in Kelvin. This model defines a fixed temperature T at its port in Kelvin,
i.e., it defines a fixed temperature as a boundary condition.

within Buildings.HeatTransfer.Sources;
model FixedTemperature "Fixed temperature boundary condition in Kelvin"

  parameter Modelica.Units.SI.Temperature T "Fixed temperature at port";
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port
equation
  port.T = T;
end FixedTemperature;


Thermal sources

within Buildings.HeatTransfer;
package Sources "Thermal sources"
extends Modelica.Icons.SourcesPackage;
end Sources;


Prescribed heat flow boundary condition. This model allows a specified amount of heat flow rate to be \"injected\"
into a thermal system at a given port.  The amount of heat
is given by the input signal Q_flow into the model. The heat flows into the
component to which the component PrescribedHeatFlow is connected,
if the input signal is positive.

within Buildings.HeatTransfer.Sources;
model PrescribedHeatFlow "Prescribed heat flow boundary condition"
  Modelica.Blocks.Interfaces.RealInput Q_flow
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port
equation
  port.Q_flow = -Q_flow;
end PrescribedHeatFlow;


Variable temperature boundary condition in Kelvin. This model represents a variable temperature boundary condition.
The temperature in [K] is given as input signal <b>T</b>
to the model. The effect is that an instance of this model acts as
an infinite reservoir able to absorb or generate as much energy
as required to keep the temperature at the specified value.

within Buildings.HeatTransfer.Sources;
model PrescribedTemperature "Variable temperature boundary condition in Kelvin"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port
  Modelica.Blocks.Interfaces.RealInput T
equation
  port.T = T;
end PrescribedTemperature;


Fixed coefficient (a user-specified parameter is used). This enumeration is used to set the function
that is used to compute the convective
heat transfer coefficient for exterior (outside-side facing) surfaces.

within Buildings.HeatTransfer.Types;
type ExteriorConvection = enumeration(
    Fixed "Fixed coefficient (a user-specified parameter is used)",
    TemperatureWind "Wind speed and temperature dependent")
  "Enumeration defining the convective heat transfer model for exterior surfaces"


Fixed coefficient (a user-specified parameter is used). This enumeration is used to set the function
that is used to compute the convective
heat transfer coefficient for interior (room-side facing) surfaces.

within Buildings.HeatTransfer.Types;
type InteriorConvection = enumeration(
    Fixed "Fixed coefficient (a user-specified parameter is used)",
    Temperature "Temperature dependent")
  "Enumeration defining the convective heat transfer model for interior surfaces"


Package with type definitions

within Buildings.HeatTransfer;
package Types "Package with type definitions"
  extends Modelica.Icons.TypesPackage;
end Types;


Depth of solar beam in the room. This component computes the maximum distance at which a solar beam that enters the window
hits the workplane. The distance is measured perpendicular to the wall.

within Buildings.HeatTransfer.Windows;
block BeamDepthInRoom "Depth of solar beam in the room"
  extends Modelica.Blocks.Icons.Block;

  parameter String filNam=""
    "Name of weather data file (used to read longitude, latitude and time zone)"

  parameter Modelica.Units.SI.Angle lon(displayUnit="deg") =
    Buildings.BoundaryConditions.WeatherData.BaseClasses.getLongitudeTMY3(
    absFilNam) "Longitude"
  parameter Modelica.Units.SI.Angle lat(displayUnit="deg") =
    Buildings.BoundaryConditions.WeatherData.BaseClasses.getLatitudeTMY3(
    absFilNam) "Latitude"
  parameter Modelica.Units.SI.Time timZon(displayUnit="h") =
    Buildings.BoundaryConditions.WeatherData.BaseClasses.getTimeZoneTMY3(
    absFilNam) "Time zone"

  parameter Modelica.Units.SI.Angle azi "Surface azimuth";

  parameter Modelica.Units.SI.Length hWorPla=0.75
    "Height of workplane above ground";

  parameter Modelica.Units.SI.Length hApe
    "Upper height of aperature above ground"
  parameter Modelica.Units.SI.Length depApe=0.15
    "Depth of outer corner of aperture, measured from interior surface"

  parameter Modelica.Units.SI.Length depOve=0
    "Depth of overhang, meausured from other exterior surface of aperature (set to 0 if no overhang)"
  parameter Modelica.Units.SI.Length gapOve=0
    "Gap between upper height of aperature and lower height of overhang (set to 0 if no overhang)"

  Modelica.Blocks.Interfaces.RealOutput y(
    final quantity="Length",
    final unit="m")
    "Beam depth in room, measured perpendicular to window surface, at workplane height"

protected
  final parameter String absFilNam = Buildings.BoundaryConditions.WeatherData.BaseClasses.getAbsolutePath(filNam)
    "Absolute name of the file";

  parameter Modelica.Units.SI.Length dep=depApe + depOve
    "Depth of outer corner that throws the shade, measured from interior surface";
  parameter Modelica.Units.SI.Length h=hApe - hWorPla + gapOve
    "Height of outer corner that throws the shade measure from the workplane height";

  BoundaryConditions.SolarGeometry.ProjectedShadowLength proShaLen(
    final h=h,
    final lat=lat,
    final azi=azi,
    final filNam=filNam,
    final lon=lon,
    final timZon=timZon) "Projected length of shadow"

  Modelica.Blocks.Math.Add depInRoo(
    final k2=-1) "Depth of beam in room"
  Modelica.Blocks.Sources.Constant depth(final k=-dep)
    "Distance outer corner that throws shade minus room-side surface"

  Modelica.Blocks.Math.Max max "Limiter to avoid negative distance"
protected
  Modelica.Blocks.Sources.Constant zer(final k=0) "Outputs zero"
initial equation
  assert(h > 0, "The aperature is below the workplane, hence the solar beam never hits the workplane.",
    AssertionLevel.warning);

equation
  connect(proShaLen.y, depInRoo.u2)
  connect(depth.y, depInRoo.u1)
  connect(zer.y, max.u2)
  connect(max.u1, depInRoo.y)
  connect(max.y, y)
end BeamDepthInRoom;


Model for heat convection and radiation at the exterior surface of a window that may have a shading device. Model for the convective heat transfer between a window shade, a window surface
and the room air.
This model is applicable for the outside-facing surface of a window system and
can be used with the model

Buildings.HeatTransfer.Windows.Window.

within Buildings.HeatTransfer.Windows;
model ExteriorHeatTransfer
  "Model for heat convection and radiation at the exterior surface of a window that may have a shading device"
  extends BaseClasses.PartialWindowBoundaryCondition(final thisSideHasShade=haveExteriorShade);
  parameter Modelica.Units.SI.Emissivity absIRSha_air
    "Infrared absorptivity of shade surface that faces air"
  parameter Modelica.Units.SI.Emissivity absIRSha_glass
    "Infrared absorptivity of shade surface that faces glass"

  parameter Modelica.Units.SI.TransmissionCoefficient tauIRSha_air
    "Infrared transmissivity of shade for radiation coming from the exterior or the room"
  parameter Modelica.Units.SI.TransmissionCoefficient tauIRSha_glass
    "Infrared transmissivity of shade for radiation coming from the glass"

  parameter Boolean linearizeRadiation
    "Set to true to linearize emissive power";
  parameter Real vieFacSky(final min=0, final max=1, final unit="1")
    "View factor from receiving surface to sky";

  Modelica.Blocks.Interfaces.RealInput vWin(final unit="m/s") "Wind speed"
  Buildings.HeatTransfer.Windows.BaseClasses.ExteriorConvectionCoefficient
    conCoeGla(                                          final A=AGla)
    "Model for the outside convective heat transfer coefficient of the glass"
  Buildings.HeatTransfer.Windows.BaseClasses.ExteriorConvectionCoefficient
    conCoeFra(                                          final A=AFra)
    "Model for the outside convective heat transfer coefficient of the frame"
 Radiosity.OutdoorRadiosity radOut(
   final A=AGla, vieFacSky=vieFacSky,
    linearize=linearizeRadiation) "Outdoor radiosity"

  Modelica.Blocks.Interfaces.RealInput TBlaSky(
    final quantity="ThermodynamicTemperature",
    final unit="K",
    min=0) "Black body sky temperature"
  Modelica.Blocks.Interfaces.RealInput TOut(final quantity="ThermodynamicTemperature",
                                            final unit = "K", min=0)
    "Outside temperature"
  Interfaces.RadiosityOutflow JOutUns
    "Outgoing radiosity that connects to unshaded part of glass"
  Interfaces.RadiosityInflow JInUns
    "Incoming radiosity that connects to unshaded part of glass"
  Interfaces.RadiosityOutflow JOutSha if haveShade
    "Outgoing radiosity that connects to shaded part of glass"
  Interfaces.RadiosityInflow JInSha if haveShade
    "Incoming radiosity that connects to shaded part of glass"
  Modelica.Blocks.Interfaces.RealInput QSolAbs_flow(unit="W", quantity="Power")
    if haveShade "Solar radiation absorbed by shade"

  BaseClasses.ShadeRadiation shaRad(
    final thisSideHasShade=thisSideHasShade,
    final A=AGla,
    final linearize=linearizeRadiation,
    final absIR_air=if thisSideHasShade then absIRSha_air else 0,
    final absIR_glass=if thisSideHasShade then absIRSha_glass else 0,
    final tauIR_air=if thisSideHasShade then tauIRSha_air else 1,
    final tauIR_glass=if thisSideHasShade then tauIRSha_glass else 1)
    if haveShade "Radiative heat balance of shade"
protected
  Radiosity.RadiositySplitter radShaOut "Radiosity that strikes shading device"
  BaseClasses.ShadeConvection shaCon(final thisSideHasShade=thisSideHasShade,
      final A=AGla)
    if haveShade "Convective heat balance of shade"
public
  Modelica.Thermal.HeatTransfer.Components.Convection conFra
    "Convective heat transfer between air and frame"
  Modelica.Thermal.HeatTransfer.Components.Convection conWinUns(
    dT(start=0))
    "Convection from unshaded part of window to outside or room air"
protected
  Modelica.Blocks.Math.Product proUns "Product for unshaded part of window"
equation
  assert(-1E-10<vieFacSky and 1.00001 > vieFacSky,
         "View factor to sky is out of range. vieFacSky = " + String(vieFacSky)
         + "\n   Check parameters.");

  connect(vWin, conCoeGla.v)
  connect(vWin, conCoeFra.v)
  connect(conCoeFra.GCon, conFra.Gc)
  connect(conCoeGla.GCon, proSha.u1)
  connect(conCoeGla.GCon, proUns.u2)
  connect(radOut.JOut, radShaOut.JIn)
  connect(radOut.TBlaSky, TBlaSky)
  connect(radOut.TOut, TOut)
  connect(radShaOut.JOut_2,JOutUns)
  connect(shaRad.JOut_glass, JOutSha)
  connect(shaRad.JIn_glass, JInSha)
  connect(radShaOut.JOut_1, shaRad.JIn_air)
  connect(shaRad.u, shaSig.y)
  connect(glaSha, shaCon.glass)
  connect(shaCon.air, air)
  connect(shaCon.Gc, proSha.y)
  connect(shaCon.TSha, shaRad.TSha)
  connect(shaRad.QRadAbs_flow, shaCon.QRadAbs_flow)
  connect(radShaOut.u, shaSig.y)
  connect(shaRad.QSolAbs_flow, QSolAbs_flow)
  connect(conFra.fluid, air)
  connect(conWinUns.fluid, air)
  connect(glaUns,conWinUns. solid)
  connect(proUns.y,conWinUns. Gc)
  connect(conFra.solid, frame)
  connect(shaSig.yCom,proUns. u1)
end ExteriorHeatTransfer;


Model for exterior shade due to overhang and/or side fin. This model outputs the fraction of the window area that is sun exposed
for a window that may have an overhang and sidefins.
Depending on the record with construction data conPar,
an overhang, side fins or no external shade is modeled.
The model allows having an overhang and side fins at the same time.
In such a case, the overhang width should be
measured from the window edge to the sidefin,
because the overhang width beyond the sidefin will
cast a shadow on the side fin and not on the window.
Similarly, the side fin height should be measured
from the upper window edge to the overhang,
because the side fin height above the
overhang will not cast a shadow on the window.
The parameters for the dimensions of the overhang and side fins are as
described in the models

Buildings.HeatTransfer.Windows.Overhang
and

Buildings.HeatTransfer.Windows.SideFins.

within Buildings.HeatTransfer.Windows;
model FixedShade "Model for exterior shade due to overhang and/or side fin"
  extends HeatTransfer.Windows.BaseClasses.ShadeInterface_weatherBus;
  parameter Buildings.ThermalZones.Detailed.BaseClasses.ParameterConstructionWithWindow conPar
    "Construction parameters";

  parameter Modelica.Units.SI.Angle azi(displayUnit="deg")
    "Surface azimuth; azi= -90 degree East; azi= 0 South";

  Modelica.Blocks.Routing.Multiplex4 mulFraSun(
    n1=1,
    n2=1,
    n3=1,
    n4=1) "Multiplex for fraction of shaded area"

  Modelica.Blocks.Math.Add sumFraSun
    "Addition of sun exposed window area fractions"

  Modelica.Blocks.Math.Add resFraSun(k2=1.0, k1=-1.0)
    "Calculates resultant sun exposed window area fraction"
  Modelica.Blocks.Sources.Constant overlap(k=1.0)
    "Overlap of sun exposed window area fraction"
  Modelica.Blocks.Sources.Constant noSunCond(k=small)
    "Condition when the sun is not in front of window"

protected
  constant Real small = 0.001
    "Small number, used to avoid that sun-exposed fraction of window is negative";

  final parameter Boolean haveOverhang = conPar.ove.haveOverhang
    "Flag for overhang"

  final parameter Boolean haveSideFins = conPar.sidFin.haveSideFins
    "Flag for sidefins"
  final parameter Boolean haveOverhangAndSideFins= (haveOverhang
       and haveSideFins) "Flag for overhang and sidefins";

  final parameter Integer idx = if haveOverhangAndSideFins then 2 elseif haveOverhang then 1 elseif haveSideFins then 3 else 4
    "Integer used to pick the appropriate output signal";

  HeatTransfer.Windows.BaseClasses.Overhang ove(
    final azi=conPar.azi,
    final hWin=conPar.hWin,
    final wWin=conPar.wWin,
    final dep=conPar.ove.dep,
    final gap=conPar.ove.gap,
    final wR=conPar.ove.wR,
    final wL=conPar.ove.wL) "Model for overhang"

  HeatTransfer.Windows.BaseClasses.SideFins sidFin(
    final hWin=conPar.hWin,
    final wWin=conPar.wWin,
    final h=conPar.sidFin.h,
    final dep=conPar.sidFin.dep,
    final gap=conPar.sidFin.gap) "Model for side fins"

  BoundaryConditions.SolarGeometry.BaseClasses.WallSolarAzimuth walSolAzi
    "Angle measured in horizontal plane between projection of sun's rays and normal to vertical surface"
  Modelica.Blocks.Math.Product mulHDir
    "Multiplication to obtain direct solar irradiation on shaded window"

  Modelica.Blocks.Routing.Extractor extFraSun(final allowOutOfRange=false, final
      nin=4,
    index(start=idx, fixed=true))
    "Extractor to pick the appropriate output signal"
  Modelica.Blocks.Sources.IntegerConstant idxSou(final k=idx)
    "Source term to pick output signal"
  Modelica.Blocks.Sources.Constant const(k=1)

  Utilities.Math.SmoothMax smoMax(deltaX=small/2)
    "Limiter to avoid that the fraction of sun-exposed window is below zero"
equation
  connect(weaBus.solAlt, walSolAzi.alt)

  connect(incAng, walSolAzi.incAng)
  connect(walSolAzi.verAzi, ove.verAzi)
  connect(walSolAzi.verAzi, sidFin.verAzi)
  connect(weaBus.solAlt, sidFin.alt)
  connect(mulHDir.y, HDirTil)

  connect(mulHDir.u1, HDirTilUns)
  connect(weaBus, ove.weaBus)
  connect(extFraSun.y, fraSun)
  connect(extFraSun.y, mulHDir.u2)
  connect(mulFraSun.y, extFraSun.u)
  connect(ove.fraSun, mulFraSun.u1[1])
  connect(sidFin.fraSun, mulFraSun.u3[1])
  connect(const.y, mulFraSun.u4[1])
  connect(weaBus.solAlt, ove.alt)
  connect(ove.fraSun, sumFraSun.u1)
  connect(sumFraSun.y, resFraSun.u2)

  connect(overlap.y, resFraSun.u1)
  connect(sidFin.fraSun, sumFraSun.u2)

  connect(idxSou.y, extFraSun.index)
  connect(resFraSun.y, smoMax.u1)
  connect(noSunCond.y, smoMax.u2)
  connect(smoMax.y, mulFraSun.u2[1])
end FixedShade;


Model for heat convection at the interior surface of a window that may have a shading device. Model for the convective heat transfer between a window shade, a window surface
and the room air.
This model is applicable for the room-facing surface of a window system and
can be used with the model

Buildings.HeatTransfer.Windows.Window.

within Buildings.HeatTransfer.Windows;
model InteriorHeatTransferConvective
  "Model for heat convection at the interior surface of a window that may have a shading device"
  extends BaseClasses.PartialWindowBoundaryCondition(final thisSideHasShade=haveInteriorShade);

  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hFixed=4
    "Constant convection coefficient";
  parameter Types.InteriorConvection conMod=Buildings.HeatTransfer.Types.InteriorConvection.Fixed
    "Convective heat transfer model";
  parameter Modelica.Units.SI.Angle til "Surface tilt";

 Modelica.Blocks.Interfaces.RealInput QRadAbs_flow(final unit="W")
    if haveShade
    "Total net radiation that is absorbed by the shade (positive if absorbed)"
  Modelica.Blocks.Interfaces.RealOutput TSha(
   final unit="K",
   final quantity="ThermodynamicTemperature")
   if haveShade "Shade temperature"

  Buildings.HeatTransfer.Windows.BaseClasses.InteriorConvectionCoefficient
    conCoeGla(final A=AGla)
    "Model for the inside convective heat transfer coefficient of the glass"

  BaseClasses.ShadeConvection conSha(
    final A=AGla,
    final thisSideHasShade=thisSideHasShade)
    if haveShade "Convection model for shade"
  BaseClasses.InteriorConvection conFra(
    final A=AFra,
    final til=til,
    final conMod=conMod,
    hFixed=hFixed) "Convective heat transfer between air and frame"
  BaseClasses.InteriorConvection conWinUns(
    final A=AGla,
    final til=til,
    final conMod=conMod,
    hFixed=hFixed)
    "Convection from unshaded part of window to outside or room air"
equation
  connect(conCoeGla.GCon, proSha.u1)

  connect(conSha.glass, glaSha)
  connect(proSha.y, conSha.Gc)
  connect(conSha.TSha, TSha)
  connect(QRadAbs_flow, conSha.QRadAbs_flow)

  connect(conFra.fluid, air)

  connect(air, conSha.air)
  connect(conFra.fluid, air)
  connect(conWinUns.fluid, air)
  connect(glaUns,conWinUns. solid)
  connect(conFra.solid, frame)
  connect(shaSig.yCom, conWinUns.u)
  connect(shaSig.yCom, conFra.u)
end InteriorHeatTransferConvective;


For a window with an overhang, outputs the fraction of the window area exposed to the sun. For a window with an overhang, this model outputs the fraction of
the area that is exposed to the sun.
The models can also be used for doors with an overhang.

within Buildings.HeatTransfer.Windows;
model Overhang
  "For a window with an overhang, outputs the fraction of the window area exposed to the sun"
  extends Buildings.ThermalZones.Detailed.BaseClasses.Overhang;
  extends Buildings.HeatTransfer.Windows.BaseClasses.PartialShade_weatherBus;
  parameter Modelica.Units.SI.Angle azi(displayUnit="deg")
    "Surface azimuth; azi= -90 degree East; azi= 0 South";
  // Overhang dimensions
protected
  Buildings.HeatTransfer.Windows.BaseClasses.Overhang ove(
    final azi=azi,
    final wR=wR,
    final wL=wL,
    final dep=dep,
    final gap=gap,
    final hWin=hWin,
    final wWin=wWin) "Window overhang"
equation
  connect(ove.fraSun, fraSun)
  connect(walSolAzi.verAzi, ove.verAzi)
  connect(ove.fraSun, product.u2)
  connect(weaBus, ove.weaBus)
  connect(weaBus.solAlt, ove.alt)
end Overhang;


Package with models for windows

within Buildings.HeatTransfer;
package Windows "Package with models for windows"
  extends Modelica.Icons.VariantsPackage;
end Windows;


For a window with side fins, outputs the fraction of the window area exposed to the sun. For a window with side fins, this model outputs the fraction of
the area that is exposed to the sun.
The model calculates the fraction of the window area that is exposed to the sun.
The side fins are symmetrically placed above the vertical window centerline,
and its height must be equal or greater than the window height.
This models can also be used for doors with side fins.
The figure below shows the parameters. The parameter h is measured
from the top of the window to the top of the side fins.
Side fins are assumed to extend at least to the lower edge of the window.
(Any portion of the side fin below the window edge does not cast
as shadow on the window anyway.)

within Buildings.HeatTransfer.Windows;
model SideFins
  "For a window with side fins, outputs the fraction of the window area exposed to the sun"
  extends Buildings.ThermalZones.Detailed.BaseClasses.SideFins;
  extends Buildings.HeatTransfer.Windows.BaseClasses.PartialShade_weatherBus;
  Buildings.HeatTransfer.Windows.BaseClasses.SideFins fin(
    final dep=dep,
    final h=h,
    final gap=gap,
    final hWin=hWin,
    final wWin=wWin) "Window side fins"
equation
  connect(fin.fraSun, fraSun)
  connect(walSolAzi.verAzi, fin.verAzi)
  connect(weaBus.solAlt, fin.alt)
  connect(fin.fraSun, product.u2)
end SideFins;


Model for a window.

within Buildings.HeatTransfer.Windows;
model Window "Model for a window"

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

  parameter Buildings.HeatTransfer.Data.GlazingSystems.Generic glaSys
    "Glazing system"
  parameter Modelica.Units.SI.Area A "Heat transfer area";
  parameter Real fFra(min=0, max=1)=0.1 "Fraction of frame";
  final parameter Modelica.Units.SI.Area AFra=fFra*A "Frame area";
  final parameter Modelica.Units.SI.Area AGla=A - AFra "Glass area";
  parameter Boolean linearize=false "Set to true to linearize emissive power";
  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt";

  parameter Boolean steadyState = true
    "Flag, if true, then window is steady-state, else capacity is added at room-side"

  Interfaces.RadiosityOutflow JOutUns_a
    "Outgoing radiosity that connects to unshaded part of glass at exterior side"
  Interfaces.RadiosityInflow JInUns_a
    "Incoming radiosity that connects to unshaded part of glass at exterior side"
  Interfaces.RadiosityOutflow JOutSha_a if haveShade
    "Outgoing radiosity that connects to shaded part of glass at exterior side"
  Interfaces.RadiosityInflow JInSha_a if haveShade
    "Incoming radiosity that connects to shaded part of glass at exterior side"

  Interfaces.RadiosityOutflow JOutUns_b
    "Outgoing radiosity that connects to unshaded part of glass at room-side"
  Interfaces.RadiosityInflow JInUns_b
    "Incoming radiosity that connects to unshaded part of glass at room-side"
  Interfaces.RadiosityOutflow JOutSha_b if haveShade
    "Outgoing radiosity that connects to shaded part of glass at room-side"
  Interfaces.RadiosityInflow JInSha_b if haveShade
    "Incoming radiosity that connects to shaded part of glass at room-side"

  Buildings.HeatTransfer.Windows.BaseClasses.CenterOfGlass glaUns(
    final glaSys=glaSys,
    final A=AGla,
    final til=til,
    final linearize=linearize,
    final homotopyInitialization=homotopyInitialization)
    "Model for unshaded center of glass"

  Buildings.HeatTransfer.Windows.BaseClasses.CenterOfGlass glaSha(
    final glaSys=glaSys,
    final A=AGla,
    final til=til,
    final linearize=linearize,
    final homotopyInitialization=homotopyInitialization)
    if haveShade "Model for shaded center of glass"

  Modelica.Thermal.HeatTransfer.Components.ThermalConductor frame(
    G=AFra*glaSys.UFra,
    dT(start=0)) "Thermal conductance of frame"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glaUns_a
    "Heat port at unshaded glass of exterior-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glaUns_b
    "Heat port at unshaded glass of room-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_b glaSha_b if haveShade
    "Heat port at shaded glass of room-facing surface"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a fra_a
    "Heat port at frame of exterior-facing surface"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b fra_b
    "Heat port at frame of room-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)"

  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"

  Buildings.HeatTransfer.Windows.BaseClasses.HeatCapacity capGla(
    final haveShade=glaSys.haveExteriorShade or glaSys.haveInteriorShade,
    C=AGla*glaSys.glass[1].x*matGla.d*matGla.c,
    der_TUns(fixed=true),
    der_TSha(fixed=glaSys.haveExteriorShade or glaSys.haveInteriorShade))
      if not steadyState
    "Heat capacity of glass on room-side, used to reduce nonlinear system of equations"
  // We assume the frame is made of wood. Data are used for Plywood, as
  // this is an order of magnitude estimate for the heat capacity of the frame,
  // which is only used to avoid algebraic loops in the room model.
  Modelica.Thermal.HeatTransfer.Components.HeatCapacitor capFra(
    der_T(fixed=true),
    C=AFra*matFra.x*matFra.d*matFra.c)
      if not steadyState
    "Heat capacity of frame on room-side, used to reduce nonlinear system of equations"

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

  BaseClasses.ShadingSignal shaSig(final haveShade=glaSys.haveExteriorShade or glaSys.haveInteriorShade)
    "Block to constrain the shading control signal to be strictly within (0, 1) if a shade is present"

  parameter Data.Solids.Plywood matFra(x=0.03)
    "Thermal properties of frame (used to avoid algebraic loops in room model)"
  parameter Data.Solids.Glass matGla(
    x=glaSys.glass[end].x,
    nSta=1,
    nStaReal=1)
    "Material properties for thermal capacity of room-facing glass (used to avoid algebraic loops in room model)"

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(frame.port_a, fra_a)
  connect(frame.port_b, fra_b)

  connect(glaUns.glass_a, glaUns_a)
  connect(glaUns.glass_b, glaUns_b)
  connect(shaSig.yCom, glaUns.u)
  connect(shaSig.y, glaSha.u)
  connect(shaSig.u, uSha)
  connect(glaSha.glass_a, glaSha_a)
  connect(glaSha.glass_b, glaSha_b)
  connect(JInUns_a, glaUns.JIn_a)
  connect(glaUns.JOut_a, JOutUns_a)
  connect(glaUns.JOut_b, JOutUns_b)
  connect(JInUns_b, glaUns.JIn_b)
  connect(JInSha_a, glaSha.JIn_a)
  connect(glaSha.JOut_a, JOutSha_a)
  connect(glaSha.JOut_b, JOutSha_b)
  connect(JInSha_b, glaSha.JIn_b)
  connect(glaUns.QAbs_flow, QAbsUns_flow)

  connect(glaSha.QAbs_flow,QAbsSha_flow)

  connect(capFra.port, fra_b)
  connect(capGla.ySha, shaSig.y)
  connect(capGla.yCom, shaSig.yCom)
  connect(capGla.portSha, glaSha_b)
  connect(capGla.portUns, glaUns_b)
end Window;


Absorbed radiation by window. The model calculates absorbed solar radiation on the window.
The calculations follow the description in Wetter (2004), Appendix A.4.3.

within Buildings.HeatTransfer.Windows.BaseClasses;
block AbsorbedRadiation "Absorbed radiation by window"
  extends Buildings.HeatTransfer.Windows.BaseClasses.PartialRadiation;

  Modelica.Blocks.Interfaces.RealInput HRoo(
    quantity="RadiantEnergyFluenceRate",
    final unit="W/m2") "Diffussive radiation from room "

  Modelica.Blocks.Interfaces.RealOutput QAbsExtSha_flow[NSta](
    each final quantity="Power",
    each final unit="W")
    "Absorbed interior and exterior radiation by exterior shading device"
  Modelica.Blocks.Interfaces.RealOutput QAbsIntSha_flow[NSta](
    each final quantity="Power",
    each final unit="W")
    "Absorbed interior and exterior radiation by interior shading device"
  Modelica.Blocks.Interfaces.RealOutput QAbsGlaUns_flow[N, NSta](
    each quantity="Power",
    each final unit="W")
    "Absorbed interior and exterior radiation by unshaded part of glass"
  Modelica.Blocks.Interfaces.RealOutput QAbsGlaSha_flow[N, NSta](
    each quantity="Power",
    each final unit="W")
    "Absorbed interior and exterior radiation by shaded part of glass"

  output Modelica.Units.SI.Power absRad[2,N + 2,NSta] "Absorbed interior and exterior radiation.
      (absRad[2,1,iSta]: exterior shading device,
      absRad[1,2 to N+1,iSta]: glass (unshaded part),
      absRad[2,2 to N+1,iSta]: glass (shaded part),
      absRad[2,N+2,iSta]: interior shading device)
      with iSta being the state of the (electrochromic) window";

protected
  final parameter Integer NDIR=radDat.NDIR "Number of incident angles";
  final parameter Integer HEM=radDat.HEM "Index of hemispherical integration";
  constant Integer NoShade=1 "Index for data for no shade";
  constant Integer Shade=2 "Index for data with shade";
  final parameter Real coeAbsEx[2, radDat.N, radDat.HEM + 2, NSta](each fixed=false);
  final parameter Real coeRefExtPan1[radDat.HEM + 2, NSta](each fixed=false)
    "Reflectivity of pane 1";
  final parameter Real coeAbsIn[2, radDat.N, NSta](each fixed=false);
  final parameter Real coeAbsDevExtIrrIntSha[radDat.HEM + 2, NSta](each fixed=false)
    "Absorptivity of interior shading device for exterior radiation";
  final parameter Real coeAbsDevExtIrrExtSha=1 - radDat.traRefShaDev[1, 1] -
      radDat.traRefShaDev[2, 1]
    "Absorptivity of exterior shading device for exterior radiation";
  final parameter Real coeAbsDevIntIrrIntSha[NSta]=radDat.devAbsIntIrrIntSha
    "Absorptivity of interior shading device for interior radiation";
  final parameter Real coeAbsDevIntIrrExtSha[NSta]=
    {1 - radDat.winTraRefIntIrrExtSha[1, iSta]
       - radDat.winTraRefIntIrrExtSha[2, iSta] for iSta in 1:NSta}
    "Absorptivity of exterior shading device for interior radiation";

  Real x "Intermediate variable, x=(index-1)*incAng/(0.5pi)+2, 0<=x<=NDIR";

  Real incAng2;

initial equation
  //**************************************************************
  // Assign coefficients.
  // Data dimension changes from Original ([1 : HEM]) to New ([2 : HEM+1])
  // with 2 dummy variable for interpolation.
  //**************************************************************
  // Glass
  for i in 1:N loop
    coeAbsIn[NoShade, i, 1:NSta] =  radDat.absIntIrrNoSha[i, 1:NSta];
    // Properties for glass with shading
    if haveInteriorShade then
      coeAbsIn[Shade, i, 1:NSta] =  radDat.absIntIrrIntSha[i, 1:NSta];
    elseif haveExteriorShade then
      coeAbsIn[Shade, i, 1:NSta] =  radDat.absIntIrrExtSha[i, 1:NSta];
    else
      // No Shade
      coeAbsIn[Shade, i, 1:NSta] =  zeros(NSta);
    end if;

    for j in 1:HEM loop
      // Properties for glass without shading
      coeAbsEx[NoShade, i, j + 1, 1:NSta] =  radDat.absExtIrrNoSha[i, j, 1:NSta];
      // Properties for glass with shading
      if haveInteriorShade then
        coeAbsEx[Shade, i, j + 1, 1:NSta] =  radDat.absExtIrrIntSha[i, j, 1:NSta];
      elseif haveExteriorShade then
        coeAbsEx[Shade, i, j + 1, 1:NSta] =  radDat.absExtIrrExtSha[i, j, 1:NSta];
      else
        // No Shade
        coeAbsEx[Shade, i, j + 1, 1:NSta] =  zeros(NSta);
      end if;
    end for;
    // Dummy variables at 1 and HEM+2
    for k in NoShade:Shade loop
      coeAbsEx[k, i, 1, 1:NSta] =  coeAbsEx[k, i, 2, 1:NSta];
      coeAbsEx[k, i, HEM + 2, 1:NSta] =  coeAbsEx[k, i, HEM + 1, 1:NSta];
    end for;
  end for;

  // Glass Pane 1: Reflectivity
  for j in 1:HEM loop
    coeRefExtPan1[j + 1, 1:NSta] =  radDat.traRef[2, 1, N, j, 1:NSta];
  end for;

  // Interior shades
  for j in 1:HEM loop
    coeAbsDevExtIrrIntSha[j + 1, 1:NSta] =  radDat.devAbsExtIrrIntShaDev[j, 1:NSta];
  end for;

  // Dummy variables at 1 and HEM+2
  coeRefExtPan1[1, 1:NSta] =  coeRefExtPan1[2, 1:NSta];
  coeRefExtPan1[HEM + 2, 1:NSta] =  coeRefExtPan1[HEM + 1, 1:NSta];
  coeAbsDevExtIrrIntSha[1, 1:NSta] =  coeAbsDevExtIrrIntSha[2, 1:NSta];
  coeAbsDevExtIrrIntSha[HEM + 2, 1:NSta] =  coeAbsDevExtIrrIntSha[HEM + 1, 1:NSta];

algorithm
  absRad[NoShade, 1,     1:NSta] := zeros(NSta);
  absRad[NoShade, N + 2, 1:NSta] := zeros(NSta);
  absRad[Shade,   1,     1:NSta] := zeros(NSta);
  absRad[Shade,   N + 2, 1:NSta] := zeros(NSta);

  // **************************************************************
  // Glass: absorbed diffusive radiation from exterior and interior sources
  // **************************************************************
  for i in 1:N loop
    absRad[NoShade, i + 1, 1:NSta] := AWin*(1 - uSha_internal)*
       (HDif*coeAbsEx[NoShade, i, HEM + 1, 1:NSta] + HRoo*coeAbsIn[NoShade, i, 1:NSta]);
    absRad[Shade, i + 1, 1:NSta] := AWin*uSha_internal*(HDif*coeAbsEx[Shade, i, HEM + 1, 1:NSta]
       + HRoo*coeAbsIn[Shade, i, 1:NSta]);
  end for;

  // **************************************************************
  // Shading device: absorbed radiation from exterior source
  // **************************************************************
  // Exterior Shading Device:
  // direct radiation: 1. direct absorption;
  // diffusive radiation: 1. direct absorption 2. absorption from back reflection
  for iSta in 1:NSta loop
    if haveExteriorShade then
      absRad[Shade, 1, iSta] := AWin*uSha_internal*coeAbsDevExtIrrExtSha*
        (HDif + HDir + HDif*radDat.traRefShaDev[1, 1]*radDat.traRef[2, 1, N, HEM, iSta]);
    // Interior Shading Device: diffusive radiation from both interior and exterior
     elseif haveInteriorShade then
     absRad[Shade, N + 2, iSta] := AWin*uSha_internal*
        (HDif*radDat.devAbsExtIrrIntShaDev[HEM, iSta] + HRoo*coeAbsDevIntIrrIntSha[iSta]);
    end if;
  end for;

  // **************************************************************
  // Glass, Device: add absorbed direct radiation from exterior sources
  // **************************************************************
  // Use min() instead of if() to avoid event
  incAng2 := min(incAng, 0.5*Modelica.Constants.pi);

  x := 2*(NDIR - 1)*abs(incAng2)/Modelica.Constants.pi + 2
    "x=(index-1)*incAng/(0.5pi)+2, 0<=x<=NDIR";

  for i in 1:N loop
    // Glass without shading: Add absorbed direct radiation
    for iSta in 1:NSta loop
      absRad[NoShade, i + 1, iSta] := absRad[NoShade, i + 1, iSta] +
        AWin*HDir*(1 - uSha_internal)*
          Buildings.HeatTransfer.Windows.BaseClasses.smoothInterpolation(
          {coeAbsEx[NoShade, i, k, iSta] for k in 1:(HEM + 2)}, x);

      // Glass with shading: add absorbed direct radiation
      absRad[Shade, i + 1, iSta] := absRad[Shade, i + 1, iSta]
                                 + AWin*HDir*uSha_internal
        *Buildings.HeatTransfer.Windows.BaseClasses.smoothInterpolation(
           {coeAbsEx[Shade, i, k, iSta] for k in 1:(HEM + 2)}, x);
    end for;
  end for;

  // Interior shading device: add absorbed direct radiation
  if haveInteriorShade then
    for iSta in 1:NSta loop
      absRad[Shade, N + 2, iSta] := absRad[Shade, N + 2, iSta]
                                  + AWin*HDir*uSha_internal
          *Buildings.HeatTransfer.Windows.BaseClasses.smoothInterpolation(
              {coeAbsDevExtIrrIntSha[k, iSta] for k in 1:(HEM + 2)}, x);
    end for;
  end if;

  // Exterior shading device: add absorbed reflection of direct radiation from exterior source
  if haveExteriorShade then
    for iSta in 1:NSta loop
      absRad[Shade, 1, iSta] := absRad[Shade, 1, iSta]
                              + AWin*HDir*uSha_internal*coeAbsDevExtIrrExtSha
                              *Buildings.HeatTransfer.Windows.BaseClasses.smoothInterpolation(
          {coeRefExtPan1[k, iSta] for k in 1:(HEM + 2)}, x);
    end for;
  end if;

  // Assign quantities to output connectors
  QAbsExtSha_flow[1:NSta]    := absRad[2, 1,       1:NSta];
  QAbsIntSha_flow[1:NSta]    := absRad[2, N + 2,   1:NSta];
  QAbsGlaUns_flow[:, 1:NSta] := absRad[1, 2:N + 1, 1:NSta];
  QAbsGlaSha_flow[:, 1:NSta] := absRad[2, 2:N + 1, 1:NSta];
end AbsorbedRadiation;


Model for center of glass of a window construction.

within Buildings.HeatTransfer.Windows.BaseClasses;
model CenterOfGlass "Model for center of glass of a window construction"
  extends Buildings.HeatTransfer.Radiosity.BaseClasses.RadiosityTwoSurfaces;

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

  parameter Modelica.Units.SI.Angle til(displayUnit="deg")
    "Surface tilt (only 90 degrees=vertical is implemented)";

  parameter Buildings.HeatTransfer.Data.GlazingSystems.Generic glaSys
    "Glazing system"

  parameter Boolean linearize=false "Set to true to linearize emissive power"

  Modelica.Blocks.Interfaces.RealInput u
    "Input connector, used to scale the surface area to take into account an operable shading device"

  Buildings.HeatTransfer.Windows.BaseClasses.GlassLayer[nGlaLay] glass(
    each final A=A,
    final x=glaSys.glass.x,
    final k=glaSys.glass.k,
    final absIR_a=glaSys.glass.absIR_a,
    final absIR_b=glaSys.glass.absIR_b,
    final tauIR=glaSys.glass.tauIR,
    each final linearize=linearize,
    each final homotopyInitialization=homotopyInitialization)
    "Window glass layer"
  Buildings.HeatTransfer.Windows.BaseClasses.GasConvection gas[nGlaLay-1](
    each final A=A,
    final gas=glaSys.gas,
    each final til=til,
    each linearize=linearize,
    each final homotopyInitialization=homotopyInitialization) if have_GasLay
    "Window gas layer"

  // Note that the interior shade is flipped horizontally. Hence, surfaces a and b are exchanged,
  // i.e., surface a faces the room, while surface b faces the window

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a glass_a
    "Heat port connected to the outside facing surface of the glass"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glass_b
    "Heat port connected to the room-facing surface of the glass"

  Modelica.Blocks.Interfaces.RealInput QAbs_flow[nGlaLay](
    each unit="W",
    each quantity = "Power") "Solar radiation absorbed by glass"
protected
  final parameter Integer nGlaLay = size(glaSys.glass, 1)
    "Number of glass layers";
  final parameter Boolean have_GasLay = nGlaLay > 1
    "True if it has gas layer";

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

equation
  for i in 1:nGlaLay-1 loop
    connect(glass[i].port_b, gas[i].port_a)
    connect(gas[i].port_b, glass[i+1].port_a)

    connect(glass[i].JOut_b, glass[i+1].JIn_a)
    connect(glass[i].JIn_b, glass[i+1].JOut_a)

    connect(u, gas[i].u)

  end for;

  for i in 1:nGlaLay loop
    connect(u, glass[i].u)
  end for;

  connect(glass_b, glass[nGlaLay].port_b)

  connect(glass_a, glass[1].port_a)

  connect(JIn_a, glass[1].JIn_a)
  connect(glass[1].JOut_a, JOut_a)
  connect(glass[nGlaLay].JOut_b, JOut_b)
  connect(JIn_b, glass[nGlaLay].JIn_b)
  connect(glass.QAbs_flow, QAbs_flow)
end CenterOfGlass;


Model for the heat transfer coefficient at the outside of the window.

within Buildings.HeatTransfer.Windows.BaseClasses;
model ExteriorConvectionCoefficient
  "Model for the heat transfer coefficient at the outside of the window"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Area A "Heat transfer area";

  Modelica.Blocks.Interfaces.RealOutput GCon(unit="W/K")
    "Convective thermal conductance"
  Modelica.Blocks.Interfaces.RealInput v(unit="m/s") "Wind speed"

equation
  GCon = A*(4+4*Buildings.Utilities.Math.Functions.smoothMax(v, -v, 0.1));
end ExteriorConvectionCoefficient;


Model for heat convection through gas in a window assembly.

within Buildings.HeatTransfer.Windows.BaseClasses;
model GasConvection
  "Model for heat convection through gas in a window assembly"
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D(
     port_a(T(start=293.15)),
     port_b(T(start=293.15)),
     dT(start=0));
  extends Buildings.BaseClasses.BaseIcon;

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

  parameter Buildings.HeatTransfer.Data.Gases.Generic gas
    "Thermophysical properties of gas fill"
  parameter Modelica.Units.SI.Area A "Heat transfer area";
  parameter Modelica.Units.SI.Area h(min=0) = sqrt(A) "Height of window";

  parameter Modelica.Units.SI.Angle til(displayUnit="deg")
    "Surface tilt (only 0, 90 and 180 degrees are implemented)";
  parameter Boolean linearize=false "Set to true to linearize emissive power";

  parameter Modelica.Units.SI.Temperature T0=293.15
    "Temperature used to compute thermophysical properties";

  Modelica.Blocks.Interfaces.RealInput u
    "Input connector, used to scale the surface area to take into account an operable shading device"

  Modelica.Units.SI.CoefficientOfHeatTransfer hCon(min=0, start=3)
    "Convective heat transfer coefficient";
  Modelica.Units.SI.HeatFlux q_flow "Convective heat flux";
  Real Nu(min=0) "Nusselt number";
  Real Ra(min=0) "Rayleigh number";

protected
  Modelica.Units.SI.Temperature T_a
    "Temperature used for thermophysical properties at port_a";
  Modelica.Units.SI.Temperature T_b
    "Temperature used for thermophysical properties at port_b";
  Modelica.Units.SI.Temperature T_m
    "Temperature used for thermophysical properties";

  Real deltaNu(min=0.01) = 0.1
    "Small value for Nusselt number, used for smoothing";
  Real deltaRa(min=0.01) = 100
    "Small value for Rayleigh number, used for smoothing";
  final parameter Real cosTil=Modelica.Math.cos(til) "Cosine of window tilt";
  final parameter Real sinTil=Modelica.Math.sin(til) "Sine of window tilt";
  final parameter Boolean isVertical = abs(cosTil) < 10E-10
    "Flag, true if the window is in a wall";
  final parameter Boolean isHorizontal = abs(sinTil) < 10E-10
    "Flag, true if the window is horizontal";
  // Quantities that are only used in linearized model

  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hCon0(fixed=false)
    "Convective heat transfer coefficient";
  parameter Real Nu0(fixed=false, min=0) "Nusselt number";
  parameter Real Ra0(fixed=false, min=0) "Rayleigh number";

initial equation
  // This assertion is required to ensure that the default value of
  // in Buildings.HeatTransfer.Data.Gases.Generic is overwritten.
  assert(gas.x > 0, "The gas thickness must be non-negative. Obtained gas.x = " + String(gas.x) + ".
  Check the parameter for the gas thickness of the window model.");

  assert(isVertical or isHorizontal, "Only vertical and horizontal windows are implemented.");

  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);

  // Computations that are used in the linearized model only
  Ra0 = Buildings.HeatTransfer.Convection.Functions.HeatFlux.rayleigh(
    x=gas.x,
    rho=Buildings.HeatTransfer.Data.Gases.density(gas=gas, T=T0),
    c_p=Buildings.HeatTransfer.Data.Gases.specificHeatCapacity(gas=gas, T=T0),
    mu=Buildings.HeatTransfer.Data.Gases.dynamicViscosity(gas=gas, T=T0),
    k=Buildings.HeatTransfer.Data.Gases.thermalConductivity(gas=gas, T=T0),
    T_a=T0-5,
    T_b=T0+5,
    Ra_min=100);
  (Nu0, hCon0) = Buildings.HeatTransfer.Windows.BaseClasses.convectionVerticalCavity(
            gas=gas, Ra=Ra0, T_m=T0, dT=10, h=h, deltaNu=deltaNu, deltaRa=deltaRa);

equation
  T_a = port_a.T;
  T_b = port_b.T;
  T_m = (port_a.T+port_b.T)/2;
  if linearize then
    Ra=Ra0;
    Nu=Nu0;
    hCon=hCon0;
    q_flow = hCon0 * dT;
  else
    Ra = Buildings.HeatTransfer.Convection.Functions.HeatFlux.rayleigh(
      x=gas.x,
      rho=Buildings.HeatTransfer.Data.Gases.density(gas, T_m),
      c_p=Buildings.HeatTransfer.Data.Gases.specificHeatCapacity(gas, T_m),
      mu=Buildings.HeatTransfer.Data.Gases.dynamicViscosity(gas, T_m),
      k=Buildings.HeatTransfer.Data.Gases.thermalConductivity(gas, T_m),
      T_a=T_a,
      T_b=T_b,
      Ra_min=100);
    if isVertical then
       (Nu, hCon, q_flow) = Buildings.HeatTransfer.Windows.BaseClasses.convectionVerticalCavity(
              gas=gas, Ra=Ra, T_m=T_m, dT=dT, h=h, deltaNu=deltaNu, deltaRa=deltaRa);
    elseif isHorizontal then
       (Nu, hCon, q_flow) = Buildings.HeatTransfer.Windows.BaseClasses.convectionHorizontalCavity(
              gas=gas, Ra=Ra, T_m=T_m, dT=dT, til=til, sinTil=sinTil, cosTil=cosTil,
              h=h, deltaNu=deltaNu, deltaRa=deltaRa);

    else
       Nu = 0;
       hCon=0;
       q_flow=0;
    end if; // isVertical or isHorizontal
  end if; // linearize
  if homotopyInitialization then
    Q_flow = u*A*homotopy(actual=q_flow,
                          simplified=hCon0*dT);
  else
    Q_flow = u*A*q_flow;
  end if;
end GasConvection;


Model for a glass layer of a window assembly.

within Buildings.HeatTransfer.Windows.BaseClasses;
model GlassLayer "Model for a glass layer of a window assembly"
  extends Buildings.HeatTransfer.Radiosity.BaseClasses.RadiosityTwoSurfaces;
  extends Buildings.HeatTransfer.Radiosity.BaseClasses.ParametersTwoSurfaces(
    final rhoIR_a=1-absIR_a-tauIR,
    final rhoIR_b=1-absIR_b-tauIR);

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

  parameter Modelica.Units.SI.Length x "Material thickness";

  parameter Modelica.Units.SI.ThermalConductivity k "Thermal conductivity";

  Modelica.Blocks.Interfaces.RealInput u
    "Input connector, used to scale the surface area to take into account an operable shading device"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a(T(start=293.15))
    "Heat port at surface a"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b(T(start=293.15))
    "Heat port at surface b"
  Modelica.Blocks.Interfaces.RealInput QAbs_flow(unit="W", quantity="Power")
    "Solar radiation absorbed by glass"

protected
 Real T4_a(min=1E8, unit="K4", start=293.15^4, nominal=1E10)
    "4th power of temperature at surface a";
 Real T4_b(min=1E8, unit="K4", start=293.15^4, nominal=1E10)
    "4th power of temperature at surface b";
  Modelica.Units.SI.HeatFlowRate E_a(min=0, nominal=1E2)
    "Emissive power of surface a";
  Modelica.Units.SI.HeatFlowRate E_b(min=0, nominal=1E2)
    "Emissive power of surface b";
  final parameter Modelica.Units.SI.ThermalResistance R=x/2/k/A
    "Thermal resistance from surface of glass to center of glass";

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
  // Heat balance of surface node
  // These equations are from Window 6 Technical report, (2.1-14) to (2.1-17)
  0 = port_a.Q_flow + port_b.Q_flow + QAbs_flow + JIn_a  + JIn_b - JOut_a - JOut_b;
  u * (port_b.T-port_a.T) = 2*R * (-port_a.Q_flow-QAbs_flow/2-JIn_a+JOut_a + tauIR * (JIn_a - JIn_b));
  // Radiosity balance
  if linearize then
    T4_a = 4*T03*port_a.T - 3*T04;
    T4_b = 4*T03*port_b.T - 3*T04;
  else
    if homotopyInitialization then
      T4_a = homotopy(actual=port_a.T^4, simplified=4*T03*port_a.T - 3*T04);
      T4_b = homotopy(actual=port_b.T^4, simplified=4*T03*port_b.T - 3*T04);
    else
      T4_a = port_a.T^4;
      T4_b = port_b.T^4;
    end if;
  end if;
  // Emissive power
  E_a = u * A * absIR_a * Modelica.Constants.sigma * T4_a;
  E_b = u * A * absIR_b * Modelica.Constants.sigma * T4_b;
  // Radiosities that are outgoing from the surface, which are
  // equal to the infrared absorptivity plus the reflected incoming
  // radiosity plus the radiosity that is transmitted from the
  // other surface.
  JOut_a = E_a + rhoIR_a * JIn_a + tauIR * JIn_b;
  JOut_b = E_b + rhoIR_b * JIn_b + tauIR * JIn_a;
end GlassLayer;


Parameter, equal to true if the window has a shade. Heat capacitor in which the capacity is scaled based on the input signal u.

within Buildings.HeatTransfer.Windows.BaseClasses;
model HeatCapacity
  extends Buildings.BaseClasses.BaseIcon;

  parameter Boolean haveShade
    "Parameter, equal to true if the window has a shade"

  parameter Modelica.Units.SI.HeatCapacity C
    "Heat capacity of element (= cp*m)";

  Modelica.Blocks.Interfaces.RealInput ySha
    if haveShade
    "Control signal for shade"

  Modelica.Blocks.Interfaces.RealInput yCom
  if haveShade
  "Input 1-y"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a portUns
    "Heat port to unshaded part of the window"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a portSha(
    T = TSha,
    Q_flow = QSha_flow)
    if haveShade
    "Heat port to shaded part of the window"

  Modelica.Units.SI.Temperature TUns(start=293.15)
    "Temperature of unshaded part of window";

  Modelica.Units.SI.Temperature TSha(start=293.15)
    "Temperature of unshaded part of window";

  Modelica.Units.SI.TemperatureSlope der_TUns(start=0)
    "Time derivative of temperature (= der(T))";

  Modelica.Units.SI.TemperatureSlope der_TSha(start=0)
    "Time derivative of temperature (= der(T))";

protected
  final parameter Real CInv(unit="K/J") = 1/C
    "Inverse of heat capacity";

  Modelica.Blocks.Interfaces.RealInput ySha_internal
    "Internal connector";

  Modelica.Blocks.Interfaces.RealInput yCom_internal
    "Internal connector";

  Modelica.Units.SI.HeatFlowRate QSha_flow
    "Heat flow rate for shaded part of the window";

equation
  connect(ySha, ySha_internal);
  connect(yCom, yCom_internal);
  portUns.T = TUns;

  if haveShade then
    der_TUns = der(TUns);
    der_TSha = der(TSha);

    // Energy balance of window
    yCom_internal * der_TUns = CInv * portUns.Q_flow;
    ySha_internal * der_TSha = CInv * QSha_flow;
  else
    der_TUns = der(TUns);
    der_TSha = 0;

    der_TUns = portUns.Q_flow * CInv;
    TSha = 293.15;
    QSha_flow = 0;

    ySha_internal = 0;
    yCom_internal = 1;
  end if;
end HeatCapacity;


Model for a interior (room-side) convective heat transfer with variable surface area. This is a model for a convective heat transfer for interior, room-facing surfaces.
The parameter conMod determines the model that is used to compute
the heat transfer coefficient:

within Buildings.HeatTransfer.Windows.BaseClasses;
model InteriorConvection
  "Model for a interior (room-side) convective heat transfer with variable surface area"
  extends Buildings.HeatTransfer.Convection.BaseClasses.PartialConvection;

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

  parameter Buildings.HeatTransfer.Types.InteriorConvection conMod=
    Buildings.HeatTransfer.Types.InteriorConvection.Fixed
    "Convective heat transfer model"

  parameter Modelica.Units.SI.CoefficientOfHeatTransfer hFixed=3
    "Constant convection coefficient"

  parameter Modelica.Units.SI.Angle til(displayUnit="deg") "Surface tilt"

  Modelica.Blocks.Interfaces.RealInput u
    "Input connector, used to scale the surface area to take into account an operable shading device"

protected
  constant Modelica.Units.SI.Temperature dT0=2
    "Initial temperature used in homotopy method";

  final parameter Real cosTil=Modelica.Math.cos(til) "Cosine of window tilt";
  final parameter Real sinTil=Modelica.Math.sin(til) "Sine of window tilt";
  final parameter Boolean is_ceiling = abs(sinTil) < 10E-10 and cosTil > 0
    "Flag, true if the surface is a ceiling";
  final parameter Boolean is_floor = abs(sinTil) < 10E-10 and cosTil < 0
    "Flag, true if the surface is a floor";

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
  if (conMod == Buildings.HeatTransfer.Types.InteriorConvection.Fixed) then
    q_flow = u*hFixed * dT;
  else
    // Even if hCon is a step function with a step at zero,
    // the product hCon*dT is differentiable at zero with
    // a continuous first derivative
    if homotopyInitialization then
      if is_ceiling then
         q_flow = u*homotopy(actual=Buildings.HeatTransfer.Convection.Functions.HeatFlux.ceiling(dT=dT),
                      simplified=dT/dT0*Buildings.HeatTransfer.Convection.Functions.HeatFlux.ceiling(dT=dT0));
      elseif is_floor then
         q_flow = u*homotopy(actual=Buildings.HeatTransfer.Convection.Functions.HeatFlux.floor(dT=dT),
                      simplified=dT/dT0*Buildings.HeatTransfer.Convection.Functions.HeatFlux.floor(dT=dT0));
      else
         q_flow = u*homotopy(actual=Buildings.HeatTransfer.Convection.Functions.HeatFlux.wall(dT=dT),
                      simplified=dT/dT0*Buildings.HeatTransfer.Convection.Functions.HeatFlux.wall(dT=dT0));
      end if;
    else
      if is_ceiling then
         q_flow = u*Buildings.HeatTransfer.Convection.Functions.HeatFlux.ceiling(dT=dT);
      elseif is_floor then
         q_flow = u*Buildings.HeatTransfer.Convection.Functions.HeatFlux.floor(dT=dT);
      else
         q_flow = u*Buildings.HeatTransfer.Convection.Functions.HeatFlux.wall(dT=dT);
      end if;
    end if;

  end if;
end InteriorConvection;


Model for the heat transfer coefficient at the inside of the window.

within Buildings.HeatTransfer.Windows.BaseClasses;
model InteriorConvectionCoefficient
  "Model for the heat transfer coefficient at the inside of the window"
  extends Modelica.Blocks.Icons.Block;
  parameter Modelica.Units.SI.Area A "Heat transfer area";

  Modelica.Blocks.Interfaces.RealOutput GCon(unit="W/K")
    "Convective thermal conductance"

equation
  GCon = 4*A;
end InteriorConvectionCoefficient;


For a window with an overhang, outputs the fraction of the area that is sun exposed. For a window with an overhang, this block outputs the fraction of
the area that is exposed to the sun.
This models can also be used for doors with an overhang.

within Buildings.HeatTransfer.Windows.BaseClasses;
block Overhang
  "For a window with an overhang, outputs the fraction of the area that is sun exposed"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.ThermalZones.Detailed.BaseClasses.Overhang;

  Modelica.Blocks.Interfaces.RealInput verAzi(
    quantity="Angle",
    unit="rad",
    displayUnit="deg")
    "Wall solar azimuth angle (angle between projection of sun's rays and normal to vertical surface)"

   Modelica.Blocks.Interfaces.RealInput alt(
     quantity="Angle",
     unit="rad",
     displayUnit="deg") "Altitude angle"

  Modelica.Blocks.Interfaces.RealOutput fraSun(final min=0,
                                               final max=1,
                                               final unit="1")
    "Fraction of window area exposed to the sun"

  parameter Modelica.Units.SI.Angle azi(displayUnit="deg")
    "Surface azimuth; azi= -90 degree East; azi= 0 degree South";

// Window dimensions
  parameter Modelica.Units.SI.Length hWin "Window height"
  parameter Modelica.Units.SI.Length wWin "Window width"

  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data"

protected
  constant Modelica.Units.SI.Angle delSolAzi=0.005
    "Half-width of transition interval between left and right formulation for overhang";

  final parameter Modelica.Units.SI.Area AWin=hWin*wWin "Window area";
  parameter Modelica.Units.SI.Length tmpH[4](each fixed=false)
    "Height rectangular sections used for superposition";
  Modelica.Units.SI.Length w
    "Either wL or wR, depending on the sun relative to the wall azimuth";
  Modelica.Units.SI.Length tmpW[4]
    "Width of rectangular sections used for superpositions";
  Modelica.Units.SI.Length del_L=wWin/100
    "Fraction of window dimension over which min-max functions are smoothened";
  Modelica.Units.SI.Length x1
    "Horizontal distance between window side edge and shadow corner";
  Modelica.Units.SI.Length x2[4]
    "Horizontal distance between window side edge and point where shadow line and window lower edge intersects";
  Modelica.Units.SI.Length y1
    "Vertical distance between overhang and shadow lower edge";
  Modelica.Units.SI.Length y2[4]
    "Window height (vertical distance corresponding to x2)";
  Real shdwTrnglRtio "Ratio of y1 and x1";
  Modelica.Units.SI.Area area[4]
    "Shaded areas of the sections used in superposition";
  Modelica.Units.SI.Area shdArea "Shaded area calculated from equations";
  Modelica.Units.SI.Area crShdArea "Final value for shaded area";
  Modelica.Units.SI.Area crShdArea1
    "Corrected for the sun behind the surface/wall";
  Modelica.Units.SI.Area crShdArea2 "Corrected for the sun below horizon";

  Buildings.BoundaryConditions.SolarGeometry.BaseClasses.SolarAzimuth solAzi
    "Solar azimuth"

initial equation
  assert(wL >= 0,  "Overhang must cover complete window
    Received overhang width on left hand side, wL = " + String(wL));
  assert(wR >= 0,  "Overhang must cover complete window
    Received overhang width on right hand side, wR = " + String(wR));

  for i in 1:4 loop
    tmpH[i] = gap + mod((i - 1), 2)*hWin;
  end for;

equation
  // if dep=0, then the equation
  //   y1*Modelica.Math.cos(verAzi) = dep*Modelica.Math.tan(alt);
  // is singular. Hence, we treat this special case with an
  // if-then construct.
  // This also increases computing efficiency in
  // Buildings.HeatTransfer.Windows.FixedShade in case the window has no overhang.

  if haveOverhang then
    //Temporary height and widths are for the areas below the overhang
    //These areas are used in superposition
    w = Buildings.Utilities.Math.Functions.spliceFunction(
            pos=wL,
            neg=wR,
            x=solAzi.solAzi-azi,
            deltax=delSolAzi);
    tmpW[1] = w + wWin;
    tmpW[2] = w;
    tmpW[3] = w;
    tmpW[4] = w + wWin;
    y1*Modelica.Math.cos(verAzi) = dep*Modelica.Math.tan(alt);
    x1 = dep*Modelica.Math.tan(verAzi);
    shdwTrnglRtio*x1 = y1;
    for i in 1:4 loop
      y2[i] = tmpH[i];
      // For the equation below, Dymola generated the following code in MixedAirFreeResponse.
      // This led to a division by zero as y1 crosses zero. The problem occurred in an
      // FMU simulation. Therefore, we guard against division by zero when computing
      // x2[i].
      //  roo.bouConExtWin.sha[1].ove.x2[1] := roo.bouConExtWin.sha[1].ove.x1*
      //  roo.bouConExtWin.sha[1].ove.tmpH[1]/roo.bouConExtWin.sha[1].ove.y1;
      // x2[i]*y1 = x1*tmpH[i];

      x2[i] = x1*tmpH[i]/Buildings.Utilities.Math.Functions.smoothMax(
        x1=y1, x2=1E-8*hWin, deltaX=1E-9*hWin);
      area[i] = Buildings.Utilities.Math.Functions.smoothMin(
        x1=y1,
        x2=y2[i],
          deltaX=del_L)*tmpW[i] - (Buildings.Utilities.Math.Functions.smoothMin(
        y1,
        tmpH[i],
        del_L)*Buildings.Utilities.Math.Functions.smoothMin(
        x1=x2[i],
        x2=y1,
        deltaX=del_L)/2) + Buildings.Utilities.Math.Functions.smoothMax(
        x1=shdwTrnglRtio*(Buildings.Utilities.Math.Functions.smoothMin(
          x1=x1,
          x2=x2[i],
          deltaX=del_L) - tmpW[i]),
        x2=0,
        deltaX=del_L)*Buildings.Utilities.Math.Functions.smoothMax(
        x1=(Buildings.Utilities.Math.Functions.smoothMin(
          x1=x1,
          x2=x2[i],
          deltaX=del_L) - tmpW[i]),
        x2=0,
        deltaX=del_L)/2;
    end for;
    shdArea = area[4] + area[3] - area[2] - area[1];
  // correction case: Sun not in front of the wall
    crShdArea1 = Buildings.Utilities.Math.Functions.spliceFunction(
      pos=shdArea,
      neg=AWin,
      x=(Modelica.Constants.pi/2)-verAzi,
      deltax=0.01);
  // correction case: Sun not above horizon
    crShdArea2 = Buildings.Utilities.Math.Functions.spliceFunction(
      pos=shdArea,
      neg=AWin,
      x=alt,
      deltax=0.01);
    crShdArea=Buildings.Utilities.Math.Functions.smoothMax(x1=crShdArea1,
                                                           x2=crShdArea2,
                                                           deltaX=0.01);
    fraSun = Buildings.Utilities.Math.Functions.smoothMin(
        x1=Buildings.Utilities.Math.Functions.smoothMax(x1=1-crShdArea/AWin,x2=0,deltaX=0.01),
        x2=1.0,
        deltaX=0.01);
  else
    w = 0;
    tmpW=fill(0.0, 4);
    y1 = 0;
    x1 = 0;
    shdwTrnglRtio = 0;
    for i in 1:4 loop
      y2[i] = 0;
      x2[i] = 0;
      area[i] = 0;
    end for;
    shdArea = 0;
    crShdArea1 = 0;
    crShdArea2 = 0;
    crShdArea  = 0;
    fraSun     = 0;
   end if;

  connect(weaBus.solTim, solAzi.solTim)
  connect(weaBus.solZen, solAzi.zen)
  connect(weaBus.solDec, solAzi.decAng)

  connect(weaBus.lat, solAzi.lat)
end Overhang;


within Buildings.HeatTransfer.Windows;
package BaseClasses "Package with base classes for Buildings.HeatTransfer.Windows"
  extends Modelica.Icons.BasesPackage;
end BaseClasses;


Partial model for variables and data used in radiation calculation.

within Buildings.HeatTransfer.Windows.BaseClasses;
partial block PartialRadiation
  "Partial model for variables and data used in radiation calculation"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.HeatTransfer.Windows.BaseClasses.RadiationBaseData;

  ////////////////// Parameters that are not used by RadiationData
  parameter Boolean haveExteriorShade
    "Set to true if window has an exterior shade";
  parameter Boolean haveInteriorShade
    "Set to true if window has an interior shade";
  parameter Modelica.Units.SI.Area AWin "Area of window";

  ////////////////// Derived parameters
  final parameter Boolean haveShade=haveExteriorShade or haveInteriorShade
    "Set to true if window has a shade"
  final parameter Buildings.HeatTransfer.Windows.BaseClasses.RadiationData
    radDat(
    final N=N,
    final tauGlaSol=tauGlaSol,
    final rhoGlaSol_a=rhoGlaSol_a,
    final rhoGlaSol_b=rhoGlaSol_b,
    final xGla=xGla,
    final tauShaSol_a=tauShaSol_a,
    final tauShaSol_b=tauShaSol_b,
    final rhoShaSol_a=rhoShaSol_a,
    final rhoShaSol_b=rhoShaSol_b)
    "Optical properties of window for different irradiation angles"
  Modelica.Blocks.Interfaces.RealInput uSha(min=0, max=1) if haveShade
    "Control signal for shading (0: unshaded; 1: fully shaded)"
  Modelica.Blocks.Interfaces.RealInput HDif(quantity="RadiantEnergyFluenceRate",
      unit="W/m2") "Diffussive solar radiation"
  Modelica.Blocks.Interfaces.RealInput incAng(
    final quantity="Angle",
    final unit="rad",
    displayUnit="deg") "Incident angle"
  Modelica.Blocks.Interfaces.RealInput HDir(quantity="RadiantEnergyFluenceRate",
      unit="W/m2") "Direct solar radiation"

protected
  Modelica.Blocks.Interfaces.RealInput uSha_internal(min=0, max=1)
    "Control signal for shading (0: unshaded; 1: fully shaded)";
initial equation
  /* Current model assumes that the window only has either an interior or exterior shade.
     Warn user if it has an interior and exterior shade.
     Allowing both shades at the same time would require rewriting part of the model. */
  assert(not (haveExteriorShade and haveInteriorShade),
    "Window radiation model does not support an exterior and interior shade at the same time.");
equation
  // Connect statement for conditionally removed connector uSha
  connect(uSha, uSha_internal);
  if (not haveShade) then
    uSha_internal = 0;
  end if;
end PartialRadiation;


Partial model to implement overhang and side fins with weather bus connector. Partial model to implement overhang and side fin model with weather bus as a connector.

within Buildings.HeatTransfer.Windows.BaseClasses;
partial model PartialShade_weatherBus
  "Partial model to implement overhang and side fins with weather bus connector"
  extends Buildings.HeatTransfer.Windows.BaseClasses.ShadeInterface_weatherBus;
  // Window dimensions
  parameter Modelica.Units.SI.Length hWin "Window height"
  parameter Modelica.Units.SI.Length wWin "Window width"

protected
  Buildings.BoundaryConditions.SolarGeometry.BaseClasses.WallSolarAzimuth walSolAzi
    "Wall solar azimuth"

  Modelica.Blocks.Math.Product product

equation
  connect(weaBus.solAlt, walSolAzi.alt)
  connect(walSolAzi.incAng, incAng)
  connect(product.y, HDirTil)
  connect(product.u1, HDirTilUns)
end PartialShade_weatherBus;


Partial model for heat convection or radiation between a possibly shaded window that can be outside or inside the room. Partial model for boundary conditions for convection and radiation for a window surface with or without shade,
that is outside or inside the room.

within Buildings.HeatTransfer.Windows.BaseClasses;
partial model PartialWindowBoundaryCondition
  "Partial model for heat convection or radiation between a possibly shaded window that can be outside or inside the room"
  parameter Modelica.Units.SI.Area A "Heat transfer area of frame and window";
  parameter Real fFra "Fraction of window frame divided by total window area";
  final parameter Modelica.Units.SI.Area AFra=fFra*A "Frame area";
  final parameter Modelica.Units.SI.Area AGla=A - AFra "Glass area";

  parameter Boolean haveExteriorShade
    "Set to true if window has exterior shade (at surface a)"
  parameter Boolean haveInteriorShade
    "Set to true if window has interior shade (at surface b)"

  final parameter Boolean haveShade = haveExteriorShade or haveInteriorShade
    "Set to true if window system has a shade"
  parameter Boolean thisSideHasShade
    "Set to true if this side of the model has a shade"

  Modelica.Blocks.Interfaces.RealInput uSha if haveShade
    "Input connector, used to scale the surface area to take into account an operable shading device, 0: unshaded; 1: fully shaded"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a air
    "Port that connects to the air (room or outside)"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glaUns
    "Heat port that connects to unshaded part of glass"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glaSha if haveShade
    "Heat port that connects to shaded part of glass"

protected
  Modelica.Blocks.Math.Product proSha if haveShade
    "Product for shaded part of window"

  ShadingSignal shaSig(final haveShade=haveShade)
    "Conversion for shading signal"
public
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a frame
    "Heat port at window frame"
initial equation
  assert(( thisSideHasShade and haveShade)  or (not thisSideHasShade),
    "Parameters \"thisSideHasShade\" and \"haveShade\" are not consistent. Check parameters");

equation
   connect(uSha, shaSig.u)
  connect(proSha.u2, shaSig.y)
end PartialWindowBoundaryCondition;


Basic parameters for window radiation calculation. Record that defines basic parameters for the window radiation calculation.
The parameter NSta is the number of states. Regular glass
has NSta=1, whereas electrochromic windows have NSta > 1.

within Buildings.HeatTransfer.Windows.BaseClasses;
partial record RadiationBaseData
  "Basic parameters for window radiation calculation"
  extends Modelica.Icons.Record;

  parameter Integer N(min=1) "Number of glass layers"

  final parameter Integer NSta(min=1, start=1) = size(tauGlaSol, 2)
    "Number of window states for electrochromic windows (set to 1 for regular windows)"

  parameter Modelica.Units.SI.Length xGla[N] "Thickness of glass"
  parameter Modelica.Units.SI.TransmissionCoefficient tauGlaSol[N,:]
    "Solar transmissivity of glass"
  parameter Modelica.Units.SI.ReflectionCoefficient rhoGlaSol_a[N,NSta]
    "Solar reflectivity of glass at surface a (facing outside)"
  parameter Modelica.Units.SI.ReflectionCoefficient rhoGlaSol_b[N,NSta]
    "Solar reflectivity of glass at surface b (facing room-side)"

  parameter Modelica.Units.SI.TransmissionCoefficient tauShaSol_a
    "Solar transmissivity of shade for irradiation from air-side"
  parameter Modelica.Units.SI.TransmissionCoefficient tauShaSol_b
    "Solar transmissivity of shade for irradiation from glass-side"
  parameter Modelica.Units.SI.ReflectionCoefficient rhoShaSol_a
    "Solar reflectivity of shade for irradiation from air-side"
  parameter Modelica.Units.SI.ReflectionCoefficient rhoShaSol_b
    "Solar reflectivity of shade for irradiation from glass-side"
end RadiationBaseData;


Radiation data of a window.

within Buildings.HeatTransfer.Windows.BaseClasses;
record RadiationData "Radiation data of a window"
  extends Modelica.Icons.Record;
  extends Buildings.HeatTransfer.Windows.BaseClasses.RadiationBaseData;
  final parameter Real glass[3, N, NSta]={tauGlaSol, rhoGlaSol_a, rhoGlaSol_b}
    "Glass solar transmissivity, solar reflectivity at surface a and b, at normal incident angle";
  final parameter Real traRefShaDev[2, 2]={{tauShaSol_a,tauShaSol_b},{
      rhoShaSol_a,rhoShaSol_b}} "Shading device property";
  final parameter Integer NDIR=10 "Number of incident angles";
  final parameter Integer HEM=NDIR + 1 "Index of hemispherical integration";
  final parameter Modelica.Units.SI.Angle psi[NDIR]=
      Buildings.HeatTransfer.Windows.Functions.getAngle(NDIR)
    "Incident angles used for solar radiation calculation";
  final parameter Real layer[3, N, HEM, NSta]=
    Buildings.HeatTransfer.Windows.Functions.glassProperty(
      N=N,
      NSta=NSta,
      HEM=HEM,
      glass=glass,
      xGla=xGla,
      psi=psi) "Angular and hemispherical transmissivity, front (outside-facing) and back (room facing) reflectivity
      of each glass pane";
  final parameter Real traRef[3, N, N, HEM, NSta]=
    Buildings.HeatTransfer.Windows.Functions.getGlassTR(
      N=N,
      NSta=NSta,
      HEM=HEM,
      layer=layer) "Angular and hemispherical transmissivity, front (outside-facing) and back (room facing) reflectivity
      between glass panes for exterior or interior irradiation without shading";
  final parameter Real absExtIrrNoSha[N, HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsExteriorIrradiationNoShading(
      traRef=traRef,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical absorptivity of each glass pane
      for exterior irradiation without shading";
  final parameter Real absIntIrrNoSha[N, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsInteriorIrradiationNoShading(
      traRef=traRef,
      N=N,
      NSta=NSta,
      HEM=HEM) "Hemispherical absorptivity of each glass pane
      for interior irradiation without shading";
  final parameter Real winTraExtIrrExtSha[HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.winTExteriorIrradiatrionExteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical transmissivity of a window system (glass + exterior shading device)
     for exterior irradiation";
  final parameter Real absExtIrrExtSha[N, HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsExteriorIrradiationExteriorShading(
      absExtIrrNoSha=absExtIrrNoSha,
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical absorptivity of each glass pane
      for exterior irradiation with exterior shading";
  final parameter Real winTraExtIrrIntSha[HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.winTExteriorIrradiationInteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical transmissivity of a window system (glass and interior shading device)
      for exterior irradiation";
  final parameter Real absExtIrrIntSha[N, HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsExteriorIrradiationInteriorShading(
      absExtIrrNoSha=absExtIrrNoSha,
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical absorptivity of each glass layer
     for exterior irradiation with interior shading";
  final parameter Real devAbsExtIrrIntShaDev[HEM, NSta]=
      Buildings.HeatTransfer.Windows.Functions.devAbsExteriorIrradiationInteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Angular and hemispherical absorptivity of an interior shading device
      for exterior irradiation";
  final parameter Real winTraRefIntIrrExtSha[3, NSta]=
      Buildings.HeatTransfer.Windows.Functions.winTRInteriorIrradiationExteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Hemisperical transmissivity and reflectivity of a window system (glass and exterior shadig device)
      for interior irradiation. traRefIntIrrExtSha[1]: transmissivity,
      traRefIntIrrExtSha[2]: Back reflectivity; traRefIntIrrExtSha[3]: dummy value";
  final parameter Real absIntIrrExtSha[N, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsInteriorIrradiationExteriorShading(
      absIntIrrNoSha=absIntIrrNoSha,
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Hemispherical absorptivity of each glass pane
      for interior irradiation with exterior shading";
  final parameter Real absIntIrrIntSha[N, NSta]=
      Buildings.HeatTransfer.Windows.Functions.glassAbsInteriorIrradiationInteriorShading(
      absIntIrrNoSha=absIntIrrNoSha,
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Hemispherical absorptivity of each glass pane
      for interior irradiation with interior shading";
  final parameter Real winTraRefIntIrrIntSha[3, NSta]=
      Buildings.HeatTransfer.Windows.Functions.winTRInteriorIrradiationInteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM) "Hemisperical transmissivity and back reflectivity of a window system (glass and interior shadig device)
      for interior irradiation";
  final parameter Real devAbsIntIrrIntSha[NSta]=
      Buildings.HeatTransfer.Windows.Functions.devAbsInteriorIrradiationInteriorShading(
      traRef=traRef,
      traRefShaDev=traRefShaDev,
      N=N,
      NSta=NSta,
      HEM=HEM)
    "Hemiperical absorptivity of an interior shading device for interior irradiation";
end RadiationData;


Model for convective heat balance of a layer that may or may not have a shade. Model for the convective heat balance
of a shade that is in the outside or the room-side of a window.

within Buildings.HeatTransfer.Windows.BaseClasses;
model ShadeConvection
  "Model for convective heat balance of a layer that may or may not have a shade"

  parameter Modelica.Units.SI.Area A "Heat transfer area";
  parameter Boolean thisSideHasShade
    "Set to true if this side of the window has a shade";

  parameter Real k(min=0, max=1)=1
    "Coefficient used to scale convection between shade and glass";

  Modelica.Blocks.Interfaces.RealInput Gc(unit="W/K")
    "Signal representing the convective thermal conductance"

  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a air
    "Port that connects to the air (room or outside)"
  Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b glass
    "Heat port that connects to shaded part of glass"
 Modelica.Blocks.Interfaces.RealInput QRadAbs_flow(unit="W")
    "Total net radiation that is absorbed by the shade (positive if absorbed)"

  Modelica.Blocks.Interfaces.RealOutput TSha(quantity="ThermodynamicTemperature",
      unit="K") "Shade temperature"
equation
  if thisSideHasShade then
    // Convective heat balance of shade.
    // The term 2*Gc is to combine the parallel convective heat transfer resistances,
    // see figure in info section.
 //   2*(air.T-TSha) = k*(glass.T-TSha);
    // Convective heat flow at air node
    air.Q_flow   = Gc*(2*(air.T-TSha) + (air.T-glass.T));
    // Convective heat flow at glass node
    glass.Q_flow = Gc*((glass.T-air.T)+k*(glass.T-TSha));
    air.Q_flow + glass.Q_flow + QRadAbs_flow = 0;
  else
    air.Q_flow   = Gc*(air.T-glass.T);
    air.Q_flow + glass.Q_flow = 0;
    TSha = (air.T+glass.T)/2;
  end if;
end ShadeConvection;


Base class for models of window shade and overhangs. Partial model to implement overhang and side fin model with weather bus as a connector.

within Buildings.HeatTransfer.Windows.BaseClasses;
partial model ShadeInterface_weatherBus
  "Base class for models of window shade and overhangs"
  extends Modelica.Blocks.Icons.Block;

  Buildings.BoundaryConditions.WeatherData.Bus weaBus "Weather data bus"

  Modelica.Blocks.Interfaces.RealInput incAng(quantity="Angle",
                                              unit="rad",
                                              displayUnit="rad")
    "Solar incidence angle"

  Modelica.Blocks.Interfaces.RealInput HDirTilUns(
                         quantity="RadiantEnergyFluenceRate",
                         unit="W/m2")
    "Direct solar irradiation on tilted, unshaded surface"

  Modelica.Blocks.Interfaces.RealOutput HDirTil(
                         quantity="RadiantEnergyFluenceRate",
                         unit="W/m2")
    "Direct solar irradiation on tilted, shaded surface"
  Modelica.Blocks.Interfaces.RealOutput fraSun(final min=0,
                                               final max=1,
                                               final unit="1")
    "Fraction of the area that is unshaded"
end ShadeInterface_weatherBus;


Model for infrared radiative heat balance of a layer that may or may not have a shade. Model for the infrared radiative heat balance
of a shade that is at the outside or the room-side of a window.
The model also includes the absorbed solar radiation.

within Buildings.HeatTransfer.Windows.BaseClasses;
model ShadeRadiation
  "Model for infrared radiative heat balance of a layer that may or may not have a shade"

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

  parameter Modelica.Units.SI.Area A "Heat transfer area";
  parameter Modelica.Units.SI.Emissivity absIR_air
    "Infrared absorptivity of surface that faces air";
  parameter Modelica.Units.SI.Emissivity absIR_glass
    "Infrared absorptivity of surface that faces glass";
  parameter Modelica.Units.SI.TransmissionCoefficient tauIR_air
    "Infrared transmissivity of shade for radiation coming from the exterior or the room";
  parameter Modelica.Units.SI.TransmissionCoefficient tauIR_glass
    "Infrared transmissivity of shade for radiation coming from the glass";
  parameter Boolean thisSideHasShade
    "Set to true if this side of the window has a shade";
  final parameter Modelica.Units.SI.ReflectionCoefficient rhoIR_air=1 -
      absIR_air - tauIR_air "Infrared reflectivity of surface that faces air";
  final parameter Modelica.Units.SI.ReflectionCoefficient rhoIR_glass=1 -
      absIR_glass - tauIR_glass
    "Infrared reflectivity of surface that faces glass";
  parameter Boolean linearize = false "Set to true to linearize emissive power"

  parameter Modelica.Units.SI.Temperature T0=293.15
    "Temperature used to linearize radiative heat transfer"

  Modelica.Blocks.Interfaces.RealInput u
    "Input connector, used to scale the surface area to take into account an operable shading device"

  Modelica.Blocks.Interfaces.RealInput QSolAbs_flow(unit="W", quantity="Power")
    "Solar radiation absorbed by shade"

  Interfaces.RadiosityInflow JIn_air(start=A*0.8*Modelica.Constants.sigma*293.15^4)
    "Incoming radiosity at the air-side surface of the shade"
  Interfaces.RadiosityInflow JIn_glass(start=A*0.8*Modelica.Constants.sigma*293.15^4)
    "Incoming radiosity at the glass-side surface of the shade"
  Interfaces.RadiosityOutflow JOut_air
    "Outgoing radiosity at the air-side surface of the shade"
  Interfaces.RadiosityOutflow JOut_glass
    "Outgoing radiosity at the glass-side surface of the shade"

 Modelica.Blocks.Interfaces.RealOutput QRadAbs_flow(unit="W")
    "Total net radiation that is absorbed by the shade (positive if absorbed)"

  Modelica.Blocks.Interfaces.RealInput TSha(quantity="ThermodynamicTemperature",
      unit="K",
      start=293.15)
      if thisSideHasShade "Shade temperature"

protected
   Modelica.Blocks.Interfaces.RealInput TSha_internal(quantity="ThermodynamicTemperature",
      unit="K",
      start=293.15) "Internal connector for shade temperature";

 final parameter Real T03(min=0, final unit="K3")=T0^3
    "3rd power of temperature T0";
 Real T4(min=1E8, start=293.15^4, nominal=1E10, final unit="K4")
    "4th power of temperature";
  Modelica.Units.SI.RadiantPower E_air
    "Emissive power of surface that faces air";
  Modelica.Units.SI.RadiantPower E_glass
    "Emissive power of surface that faces glass";

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(TSha_internal, TSha);
  if thisSideHasShade then
  // Radiosities that are outgoing from the surface, which are
  // equal to the infrared absorptivity plus the reflected incoming
  // radiosity plus the radiosity that is transmitted from the
  // other surface.
    if linearize then
      T4 = T03 * TSha_internal;
    else
      if homotopyInitialization then
        T4 = homotopy(actual=(TSha_internal)^4, simplified=T03 * TSha_internal);
      else
        T4 = TSha_internal^4;
      end if;
    end if;

    E_air   = u * A * absIR_air   * Modelica.Constants.sigma * T4;
    E_glass = u * A * absIR_glass * Modelica.Constants.sigma * T4;
    // Radiosity outgoing from shade towards air side and glass side
    JOut_air   = E_air   + tauIR_glass * JIn_glass + rhoIR_air*JIn_air;
    JOut_glass = E_glass + tauIR_air   * JIn_air   + rhoIR_glass*JIn_glass;
    // Radiative heat balance of shade.
    QSolAbs_flow + absIR_air*JIn_air + absIR_glass*JIn_glass
      = E_air+E_glass+QRadAbs_flow;
  else
    QRadAbs_flow = 0;
    T4 = T03 * T0;
    E_air = 0;
    E_glass = 0;
    JOut_air = JIn_glass;
    JOut_glass = JIn_air;
    TSha_internal = T0;
  end if;
end ShadeRadiation;


Converts the shading signal to be strictly bigger than 0 and smaller than 1.

within Buildings.HeatTransfer.Windows.BaseClasses;
block ShadingSignal
  "Converts the shading signal to be strictly bigger than 0 and smaller than 1"
  extends Modelica.Blocks.Interfaces.SO;
  parameter Boolean haveShade "Set to true if a shade is present"
  Modelica.Blocks.Interfaces.RealInput u if haveShade
    "Shading control signal, 0: unshaded; 1: fully shaded"
  Modelica.Blocks.Interfaces.RealOutput yCom "1-u"
protected
  constant Real y0 = 1E-6 "Smallest allowed value for y if a shade is present";
  constant Real k = 1-2*y0 "Gain for shading signal";
  Modelica.Blocks.Interfaces.RealInput u_in_internal
    "Needed to connect to conditional connector";
equation
  connect(u, u_in_internal);
  if not haveShade then
    u_in_internal = 0;
  end if;
  if haveShade then
    y = y0 + k *  u_in_internal;
    yCom = 1-y;
  else
    y = 0;
    yCom = 1;
  end if;
end ShadingSignal;


For a window with side fins, outputs the fraction of the area that is sun exposed. For a window with side fins, this block outputs the fraction of
the area that is exposed to the sun.
This models can also be used for doors with side fins.

within Buildings.HeatTransfer.Windows.BaseClasses;
block SideFins
  "For a window with side fins, outputs the fraction of the area that is sun exposed"
  extends Modelica.Blocks.Icons.Block;
  extends Buildings.ThermalZones.Detailed.BaseClasses.SideFins;
  Modelica.Blocks.Interfaces.RealInput alt(quantity="Angle",
                                           unit="rad",
                                           displayUnit="deg")
    "Solar altitude angle (angle between sun ray and horizontal surface)"
  Modelica.Blocks.Interfaces.RealInput verAzi(quantity="Angle",
                                              unit="rad",
                                              displayUnit="deg")
    "Angle between projection of sun's rays and normal to vertical surface"
  Modelica.Blocks.Interfaces.RealOutput fraSun(final min=0,
                                               final max=1,
                                               final unit="1")
    "Fraction of window area exposed to the sun"
// Window dimensions
  parameter Modelica.Units.SI.Length hWin "Window height"
  parameter Modelica.Units.SI.Length wWin "Window width"
// Other calculation variables
protected
  final parameter Modelica.Units.SI.Length tmpH[4]={h + hWin,h,h + hWin,h}
    "Height of rectangular sections used for superposition";
  final parameter Modelica.Units.SI.Length tmpW[4]={gap + wWin,gap + wWin,gap,
      gap} "Width of rectangular sections used for superpositions; c1,c2 etc";
  final parameter Modelica.Units.SI.Length deltaL=wWin/100
    "Fraction of window dimension over which min-max functions are smoothened";
  final parameter Modelica.Units.SI.Area AWin=hWin*wWin "Window area";
  Modelica.Units.SI.Length x1[4]
    "Horizontal distance between side fin and point where shadow line and window lower edge intersects";
  Modelica.Units.SI.Length x2
    "Horizontal distance between side fin and shadow corner";
  Modelica.Units.SI.Length x3[4] "Window width";
  Modelica.Units.SI.Length y1[4] "Window height";
  Modelica.Units.SI.Length y2
    "Vertical distance between window upper edge and shadow corner";
  Modelica.Units.SI.Length y3[4]
    "Vertical distance between window upper edge and point where shadow line and window side edge intersects";
  Modelica.Units.SI.Area area[4]
    "Shaded areas of the sections used in superposition";
  Modelica.Units.SI.Area shdArea "Shaded area";
  Modelica.Units.SI.Area crShdArea "Final value of shaded area";
  Modelica.Units.SI.Area crShdArea1
    "Shaded area, corrected for the sun behind the surface/wall";
  Modelica.Units.SI.Area crShdArea2
    "Shaded area, corrected for the sun below horizon";
  Modelica.Units.SI.Length minX[4];
  Modelica.Units.SI.Length minY[4];
  Modelica.Units.SI.Length minX2X3[4];
  Modelica.Units.SI.Length minY2Y3[4];
  Real delta=1e-6 "Small number to avoid division by zero";
  Real tanLambda
    "Tangent of angle between horizontal and sun ray projection on vertical wall";
  Real verAzi_t;
  Real lambda_t;
  Real verAzi_c;
  Real alt_t;
initial equation
  assert(h >= 0, "Sidefin parameter 'h' must be at least zero.
  It is measured from the upper edge of the window to the top of the side fin.
  Received h = " + String(h));
equation
  // This if-then construct below increases computing efficiency in
  // Buildings.HeatTransfer.Windows.FixedShade in case the window has no overhang.
  if haveSideFins then
  //avoiding division by zero
    lambda_t = Buildings.Utilities.Math.Functions.smoothMax(
      x1=tanLambda,
      x2=delta,
      deltaX=delta/10);
    verAzi_t = Buildings.Utilities.Math.Functions.smoothMax(
      x1=Modelica.Math.tan(verAzi),
      x2=delta,
      deltaX=delta/10);
    verAzi_c = Buildings.Utilities.Math.Functions.smoothMax(
      x1=Modelica.Math.cos(verAzi),
      x2=delta,
      deltaX=delta/10);
    alt_t = Buildings.Utilities.Math.Functions.smoothMax(
      x1=Modelica.Math.tan(alt),
      x2=delta,
      deltaX=delta/10);
    tanLambda = alt_t / verAzi_t;
    y2 = dep*alt_t/verAzi_c;
    x2 = dep*verAzi_t;
    for i in 1:4 loop
      x1[i] = tmpH[i]/lambda_t;
      x3[i] = tmpW[i];
      y1[i] = tmpH[i];
      y3[i] = tmpW[i]*lambda_t;
      minX2X3[i] = Buildings.Utilities.Math.Functions.smoothMin(
        x1=x2,
        x2=x3[i],
        deltaX=deltaL);
      minX[i] = Buildings.Utilities.Math.Functions.smoothMin(
        x1=x1[i],
        x2=minX2X3[i],
        deltaX=deltaL);
      minY2Y3[i] = Buildings.Utilities.Math.Functions.smoothMin(
        x1=y2,
        x2=y3[i],
        deltaX=deltaL);
      minY[i] = Buildings.Utilities.Math.Functions.smoothMin(
        x1=y1[i],
        x2=minY2Y3[i],
        deltaX=deltaL);
      area[i] = tmpH[i]*minX[i] - minX[i]*minY[i]/2;
    end for;
  //by superposition
    shdArea = area[1] + area[4] - area[2] - area[3];
    // The corrections below ensure that the shaded area is 1 if the
    // sun is below the horizon or behind the wall.
    // This correction is not required (because the direct solar irradiation
    // will be zero in this case), but it leads to more realistic time series
    // of this model.
  //correction case: Sun not in front of the wall
    crShdArea1 = Buildings.Utilities.Math.Functions.spliceFunction(
       pos=shdArea,
       neg=AWin,
       x=(Modelica.Constants.pi/2)-verAzi,
       deltax=0.01);
  //correction case: Sun below horizon
    crShdArea2 = Buildings.Utilities.Math.Functions.spliceFunction(
       pos=shdArea,
       neg=AWin,
       x=alt,
       deltax=0.01);
    crShdArea=Buildings.Utilities.Math.Functions.smoothMax(
       x1=crShdArea1,
       x2=crShdArea2,
       deltaX=0.0001*AWin);
    fraSun = 1-crShdArea/AWin;
  else
    lambda_t = 0;
    verAzi_t = 0;
    verAzi_c = 0;
    alt_t =    0;
    tanLambda = 0;
    y2 = 0;
    x2 = 0;
    x1 = fill(0.0, 4);
    x3 = fill(0.0, 4);
    y1 = fill(0.0, 4);
    y3 = fill(0.0, 4);
    minX2X3 = fill(0.0, 4);
    minX = fill(0.0, 4);
    minY2Y3 = fill(0.0, 4);
    minY = fill(0.0, 4);
    area = fill(0.0, 4);
    shdArea = 0;
    crShdArea1 = 0;
    crShdArea2 = 0;
    crShdArea  = 0;
    fraSun     = 0;
  end if;
end SideFins;


Block to interpolate between different window states. This block interpolates the radiation data for the actual
state of the window.
For windows with only one state, e.g., conventional windows,
this block outputs H=HSta[1].
For windows with multiple states, it outputs the
interpolated radiation using cubic spline interpolation.

within Buildings.HeatTransfer.Windows.BaseClasses;
block StateInterpolator "Block to interpolate between different window states"
  extends Modelica.Blocks.Icons.Block;

  parameter Integer NSta(min=1)
    "Number of window states for electrochromic windows"

  Modelica.Blocks.Interfaces.RealInput uSta(min=0, max=1, unit="1")
    if NSta > 1 "Control signal for window state"
  Modelica.Blocks.Interfaces.RealInput HSta[NSta]
    "Radiation for each window state"
  Modelica.Blocks.Interfaces.RealOutput H "Interpolated radiation"

protected
  parameter Real uSup[NSta] = {(i-1.0)/max(1.0, (NSta-1)) for i in 1:NSta}
    "Support points for the radiations HSta";
  Modelica.Blocks.Interfaces.RealInput uSta_internal(min=0, max=1, unit="1")
    "Control signal for window state";
equation
  if NSta == 1 then
    uSta_internal = 0;
    H = HSta[1];
  else
    connect(uSta, uSta_internal);
    // Linear interpolation. y=0 means off-state, in which case HSta[1] needs to
    // be assigned to the output.
    H = uSta_internal*HSta[2]+(1-uSta_internal)*HSta[1];
      Buildings.Utilities.Math.Functions.smoothInterpolation(
        x=uSta_internal,
        xSup=uSup,
        ySup=HSta,
        ensureMonotonicity=true);
  end if;
end StateInterpolator;


Lumped thermal element with variable area, transporting heat without storing it.

within Buildings.HeatTransfer.Windows.BaseClasses;
model ThermalConductor
  "Lumped thermal element with variable area, transporting heat without storing it"
  extends Modelica.Thermal.HeatTransfer.Interfaces.Element1D;
  parameter Modelica.Units.SI.ThermalConductance G
    "Constant thermal conductance of material";
  Modelica.Blocks.Interfaces.RealInput u(min=0)
    "Input signal for thermal conductance"
equation
  Q_flow = u*G*dT;
end ThermalConductor;