diff --git a/doc/getting-started/src/overall-scheme-methodology-for-running/a-methodology-for-using-energyplus.tex b/doc/getting-started/src/overall-scheme-methodology-for-running/a-methodology-for-using-energyplus.tex index 3baf92a6e3d..bc0e5c2cb15 100644 --- a/doc/getting-started/src/overall-scheme-methodology-for-running/a-methodology-for-using-energyplus.tex +++ b/doc/getting-started/src/overall-scheme-methodology-for-running/a-methodology-for-using-energyplus.tex @@ -144,6 +144,7 @@ \subsubsection{Step 3.1.~~~~~ Determine heat transfer and heat storage surfaces. \type choice \key Surface \key Zone + \key Space \key Outdoors \key Ground \key OtherSideCoefficients @@ -151,7 +152,7 @@ \subsubsection{Step 3.1.~~~~~ Determine heat transfer and heat storage surfaces. A6, \field Outside Boundary Condition Object \type object-list \object-list OutFaceEnvNames - \note Non-blank only if the field Outside Boundary Condition is Surface, Zone, OtherSideCoefficients, + \note Non-blank only if the field Outside Boundary Condition is Surface, Zone, Space, OtherSideCoefficients, \note or OtherSideConditionsModel \note If Surface, specify name of corresponding surface in adjacent zone or \note specify current surface name for internal partition separating like zones diff --git a/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex b/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex index 3582195a29f..2bd5b045df0 100644 --- a/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex +++ b/doc/input-output-reference/src/overview/group-thermal-zone-description-geometry.tex @@ -2056,6 +2056,8 @@ \subsubsection{Inputs}\label{inputs-20-007} \textbf{Adiabatic} -- an internal surface in the same Zone. This surface will not transfer heat out of the zone, but will still store heat in thermal mass. Only the inside face of the surface will exchange heat with the zone (i.e.~two adiabatic surfaces are required to model internal partitions where both sides of the surface are exchanging heat with the zone). The Outside Boundary Condition Object can be left blank. \item \textbf{Zone} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent zone when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. + \item + \textbf{Space} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent space when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. \item \textbf{Outdoors} -- if this surface is exposed to outside temperature conditions, then this is the choice. See Sun Exposure and Wind Exposure below for further specifications on this kind of surface. \item @@ -2086,11 +2088,11 @@ \subsubsection{Inputs}\label{inputs-20-007} \paragraph{Field: Outside Boundary Condition Object}\label{field-outside-boundary-condition-object-6} -If neither Surface, Zone, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. +If neither Surface, Zone, Space, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. As stated above, if the Outside Boundary Condition is ``Surface'', then this field's value must be the surface name whose inside face temperature will be forced on the outside face of the base surface. This permits heat exchange between adjacent zones (interzone heat transfer) when multiple zones are simulated, but can also be used to simulate middle zone behavior without modeling the adjacent zones. This is done by specifying a surface within the zone. For example, a middle floor zone can be modeled by making the floor the Outside Boundary Condition Object for the ceiling, and the ceiling the Outside Boundary Condition Object for the floor. -If the Outside Boundary Condition is Zone, then this field should contain the zone name of the adjacent zone for the surface. +If the Outside Boundary Condition is Zone or Space, then this field should contain the zone or space name for the adjacent surface. \begin{callout} Note: Zones with interzone heat transfer are not adiabatic and the internal surfaces contribute to gains or losses. Adiabatic surfaces are modeled by specifying the base surface itself in this field. Also, for interzone heat transfer, both surfaces must be represented -- for example, if you want interzone heat transfer to an attic space, the ceiling in the lower zone must have a surface object with the outside face environment as the floor in the attic and, likewise, there must be a floor surface object in the attic that references the ceiling surface name in the lower zone. @@ -2173,6 +2175,8 @@ \subsubsection{Inputs}\label{inputs-21-007} \textbf{Adiabatic} -- an internal surface in the same Zone. This surface will not transfer heat out of the zone, but will still store heat in thermal mass. Only the inside face of the surface will exchange heat with the zone (i.e.~two adiabatic surfaces are required to model internal partitions where both sides of the surface are exchanging heat with the zone). The Outside Boundary Condition Object can be left blank. \item \textbf{Zone} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent zone when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. + \item + \textbf{Space} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent space when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. \item \textbf{Outdoors} -- if this surface is exposed to outside temperature conditions, then this is the choice. See Sun Exposure and Wind Exposure below for further specifications on this kind of surface. \item @@ -2199,11 +2203,11 @@ \subsubsection{Inputs}\label{inputs-21-007} \paragraph{Field: Outside Boundary Condition Object}\label{field-outside-boundary-condition-object-7} -If neither Surface, Zone, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. +If neither Surface, Zone, Space, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. As stated above, if the Outside Boundary Condition is ``Surface'', then this field's value must be the surface name whose inside face temperature will be forced on the outside face of the base surface. This permits heat exchange between adjacent zones (interzone heat transfer) when multiple zones are simulated, but can also be used to simulate middle zone behavior without modeling the adjacent zones. This is done by specifying a surface within the zone. For example, a middle floor zone can be modeled by making the floor the Outside Boundary Condition Object for the ceiling, and the ceiling the Outside Boundary Condition Object for the floor. -If the Outside Boundary Condition is Zone, then this field should contain the zone name of the adjacent zone for the surface. +If the Outside Boundary Condition is Zone or Space, then this field should contain the zone or space name for the adjacent surface. \begin{callout} Note: Zones with interzone heat transfer are not adiabatic and the internal surfaces contribute to gains or losses. Adiabatic surfaces are modeled by specifying the base surface itself in this field. Also, for interzone heat transfer, both surfaces must be represented -- for example, if you want interzone heat transfer to an attic space, the ceiling in the lower zone must have a surface object with the outside face environment as the floor in the attic and, likewise, there must be a floor surface object in the attic that references the ceiling surface name in the lower zone. @@ -2286,6 +2290,8 @@ \subsubsection{Inputs}\label{inputs-22-006} \textbf{Adiabatic} -- an internal surface in the same Zone. This surface will not transfer heat out of the zone, but will still store heat in thermal mass. Only the inside face of the surface will exchange heat with the zone (i.e.~two adiabatic surfaces are required to model internal partitions where both sides of the surface are exchanging heat with the zone). The Outside Boundary Condition Object can be left blank. \item \textbf{Zone} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent zone when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. + \item + \textbf{Space} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent space when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. \item \textbf{Outdoors} -- if this surface is exposed to outside temperature conditions, then this is the choice. See Sun Exposure and Wind Exposure below for further specifications on this kind of surface. \item @@ -2316,11 +2322,11 @@ \subsubsection{Inputs}\label{inputs-22-006} \paragraph{Field: Outside Boundary Condition Object}\label{field-outside-boundary-condition-object-8} -If neither Surface, Zone, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. +If neither Surface, Zone, Space, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. As stated above, if the Outside Boundary Condition is ``Surface'', then this field's value must be the surface name whose inside face temperature will be forced on the outside face of the base surface. This permits heat exchange between adjacent zones (interzone heat transfer) when multiple zones are simulated, but can also be used to simulate middle zone behavior without modeling the adjacent zones. This is done by specifying a surface within the zone. For example, a middle floor zone can be modeled by making the floor the Outside Boundary Condition Object for the ceiling, and the ceiling the Outside Boundary Condition Object for the floor. -If the Outside Boundary Condition is Zone, then this field should contain the zone name of the adjacent zone for the surface. +If the Outside Boundary Condition is Zone or Space, then this field should contain the zone or space name for the adjacent surface. \begin{callout} Note: Zones with interzone heat transfer are not adiabatic and the internal surfaces contribute to gains or losses. Adiabatic surfaces are modeled by specifying the base surface itself in this field. Also, for interzone heat transfer, both surfaces must be represented -- for example, if you want interzone heat transfer to an attic space, the ceiling in the lower zone must have a surface object with the outside face environment as the floor in the attic and, likewise, there must be a floor surface object in the attic that references the ceiling surface name in the lower zone. @@ -2459,6 +2465,8 @@ \subsubsection{Inputs}\label{inputs-23-006} \textbf{Adiabatic} -- an internal surface in the same Zone. This surface will not transfer heat out of the zone, but will still store heat in thermal mass. Only the inside face of the surface will exchange heat with the zone (i.e.~two adiabatic surfaces are required to model internal partitions where both sides of the surface are exchanging heat with the zone). The Outside Boundary Condition Object can be left blank. \item \textbf{Zone} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent zone when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. + \item + \textbf{Space} -- this is similar to Surface but EnergyPlus will automatically create the required surface in the adjacent space when this is entered for the surface. If there are windows or doors on the surface, EnergyPlus automatically creates appropriate sub-surfaces as well. \item \textbf{Outdoors} -- if this surface is exposed to outside temperature conditions, then this is the choice. See Sun Exposure and Wind Exposure below for further specifications on this kind of surface. \item @@ -2489,11 +2497,11 @@ \subsubsection{Inputs}\label{inputs-23-006} \paragraph{Field: Outside Boundary Condition Object}\label{field-outside-boundary-condition-object-9} -If neither Surface, Zone, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. +If neither Surface, Zone, Space, Foundation, OtherSideCoefficients, or OtherSideConditionsModel are specified for the Outside Boundary Condition (previous field), then this field should be left blank. As stated above, if the Outside Boundary Condition is ``Surface'', then this field's value must be the surface name whose inside face temperature will be forced on the outside face of the base surface. This permits heat exchange between adjacent zones (interzone heat transfer) when multiple zones are simulated, but can also be used to simulate middle zone behavior without modeling the adjacent zones. This is done by specifying a surface within the zone. For example, a middle floor zone can be modeled by making the floor the Outside Boundary Condition Object for the ceiling, and the ceiling the Outside Boundary Condition Object for the floor. -If the Outside Boundary Condition is Zone, then this field should contain the zone name of the adjacent zone for the surface. +If the Outside Boundary Condition is Zone or Space, then this field should contain the zone or space name for the adjacent surface. \begin{callout} Note: Zones with interzone heat transfer are not adiabatic and the internal surfaces contribute to gains or losses. Adiabatic surfaces are modeled by specifying the base surface itself in this field. Also, for interzone heat transfer, both surfaces must be represented -- for example, if you want interzone heat transfer to an attic space, the ceiling in the lower zone must have a surface object with the outside face environment as the floor in the attic and, likewise, there must be a floor surface object in the attic that references the ceiling surface name in the lower zone. @@ -2619,7 +2627,7 @@ \subsubsection{Inputs}\label{inputs-24-004} If the base surface has Outside Boundary Condition = Surface or OtherSideCoefficients, then this field must also be specified for the subsurface. Otherwise, it can be left blank. -If the base surface has Outside Boundary Condition = Zone, then this surface retains that characteristic and uses the same zone of the base surface. It can be entered here for clarity or it can be left blank. +If the base surface has Outside Boundary Condition = Zone or Space, then this surface retains that characteristic and uses the same zone or space of the base surface. It can be entered here for clarity or it can be left blank. If Outside Boundary Condition for the base surface is Surface, this field should specify the subsurface in the opposing zone that is the counterpart to this subsurface. The constructions of the subsurface and opposing subsurface must match, except that, for multi-layer constructions, the layer order of the opposing subsurface's construction must be the reverse of that of the subsurface. diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index 38ae62ec980..d3c91f1ad09 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -9457,6 +9457,7 @@ Space, \reference SpaceNames \reference SpaceAndSpaceListNames \reference ZoneAndZoneListAndSpaceAndSpaceListNames + \reference OutFaceEnvNames A2, \field Zone Name \required-field \type object-list @@ -10197,6 +10198,7 @@ BuildingSurface:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Foundation \key Ground @@ -10214,7 +10216,7 @@ BuildingSurface:Detailed, \type object-list \object-list OutFaceEnvNames \note Non-blank only if the field Outside Boundary Condition is Surface, - \note Zone, OtherSideCoefficients or OtherSideConditionsModel + \note Zone, Space, OtherSideCoefficients or OtherSideConditionsModel \note If Surface, specify name of corresponding surface in adjacent zone or \note specify current surface name for internal partition separating like zones \note If Zone, specify the name of the corresponding zone and @@ -11381,6 +11383,7 @@ Wall:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Foundation \key Ground @@ -11398,7 +11401,7 @@ Wall:Detailed, \type object-list \object-list OutFaceEnvNames \note Non-blank only if the field Outside Boundary Condition is Surface, - \note Zone, OtherSideCoefficients or OtherSideConditionsModel + \note Zone, Space, OtherSideCoefficients or OtherSideConditionsModel \note If Surface, specify name of corresponding surface in adjacent zone or \note specify current surface name for internal partition separating like zones \note If Zone, specify the name of the corresponding zone and @@ -11572,6 +11575,7 @@ RoofCeiling:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Ground \key OtherSideCoefficients @@ -11587,7 +11591,7 @@ RoofCeiling:Detailed, \type object-list \object-list OutFaceEnvNames \note Non-blank only if the field Outside Boundary Condition is Surface, - \note Zone, OtherSideCoefficients or OtherSideConditionsModel + \note Zone, Space, OtherSideCoefficients or OtherSideConditionsModel \note If Surface, specify name of corresponding surface in adjacent zone or \note specify current surface name for internal partition separating like zones \note If Zone, specify the name of the corresponding zone and @@ -11761,6 +11765,7 @@ Floor:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Foundation \key Ground @@ -11778,7 +11783,7 @@ Floor:Detailed, \type object-list \object-list OutFaceEnvNames \note Non-blank only if the field Outside Boundary Condition is Surface, - \note Zone, OtherSideCoefficients or OtherSideConditionsModel + \note Zone, Space, OtherSideCoefficients or OtherSideConditionsModel \note If Surface, specify name of corresponding surface in adjacent zone or \note specify current surface name for internal partition separating like zones \note If Zone, specify the name of the corresponding zone and diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 96c5a191987..f40696941a5 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -108,9 +108,11 @@ namespace SurfaceGeometry { static std::string const BlankString; - int constexpr UnenteredAdjacentZoneSurface = -998; // allows users to enter one zone surface ("Zone") - // referencing another in adjacent zone - int constexpr UnreconciledZoneSurface = -999; // interim value between entering surfaces ("Surface") and reconciling + int constexpr unenteredAdjacentSpaceSurface = -997; // allows users to enter one zone surface ("Space") + // referencing another in adjacent space + int constexpr unenteredAdjacentZoneSurface = -998; // allows users to enter one zone surface ("Zone") + // referencing another in adjacent zone + int constexpr unreconciledZoneSurface = -999; // interim value between entering surfaces ("Surface") and reconciling void AllocateSurfaceWindows(EnergyPlusData &state, int NumSurfaces) { @@ -990,13 +992,10 @@ namespace SurfaceGeometry { // (you're on the outside looking toward the wall) as stored into // Surface%Vertex(1:) + static constexpr std::string_view RoutineName = "GetSurfaceData: "; using namespace Vectors; using namespace DataErrorTracking; - static constexpr std::string_view RoutineName("GetSurfaceData: "); - - int ConstrNum; // Construction number - int Found; // For matching interzone surfaces int ConstrNumFound; // Construction number of matching interzone surface bool NonMatch(false); // Error for non-matching interzone surfaces int MovedSurfs; // Number of Moved Surfaces (when sorting into hierarchical structure) @@ -1195,125 +1194,115 @@ namespace SurfaceGeometry { // Debug write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) { auto &surfTemp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); - if (surfTemp.ExtBoundCond != UnenteredAdjacentZoneSurface) continue; + if ((surfTemp.ExtBoundCond != unenteredAdjacentZoneSurface) && (surfTemp.ExtBoundCond != unenteredAdjacentSpaceSurface)) continue; // Need to add surface ++CurNewSurf; // Debug write(outputfiledebug,*) ' adding surface=',curnewsurf - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); + auto &newSurf = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf); + newSurf = surfTemp; // Basic parameters are the same for both surfaces. - Found = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); - if (Found == 0) continue; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = Found; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataHeatBal->Zone(Found).Name; + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { + int Found = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); + if (Found == 0) continue; + newSurf.Zone = Found; + auto &newZone = state.dataHeatBal->Zone(Found); + newSurf.ZoneName = newZone.Name; + assert(newZone.spaceIndexes.size() >= 1); + newSurf.spaceNum = 0; // clear this here and set later + } else if (surfTemp.ExtBoundCond == unenteredAdjacentSpaceSurface) { + int Found = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->space, state.dataGlobal->numSpaces); + if (Found == 0) continue; + newSurf.spaceNum = Found; + int zoneNum = state.dataHeatBal->space(Found).zoneNum; + newSurf.Zone = zoneNum; + newSurf.ZoneName = state.dataHeatBal->Zone(zoneNum).Name; + } // Reverse Construction - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction = - - DataHeatBalance::AssignReverseConstructionNumber(state, surfTemp.Construction, SurfError); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConstructionStoredInputValue = - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction; + newSurf.Construction = DataHeatBalance::AssignReverseConstructionNumber(state, surfTemp.Construction, SurfError); + newSurf.ConstructionStoredInputValue = newSurf.Construction; // Reverse Vertices int NVert = surfTemp.Sides; for (int Vert = 1; Vert <= surfTemp.Sides; ++Vert) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex(Vert) = surfTemp.Vertex(NVert); + newSurf.Vertex(Vert) = surfTemp.Vertex(NVert); --NVert; } - if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides > 2) { - Vectors::CreateNewellAreaVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea = - Vectors::VecLength(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellAreaVector); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).GrossArea; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NetAreaShadowCalc = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area; - Vectors::CreateNewellSurfaceNormalVector(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Sides, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector); - Vectors::DetermineAzimuthAndTilt(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex, - SurfWorldAz, - SurfTilt, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsx, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsy, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).lcsz, - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Azimuth = SurfWorldAz; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt = SurfTilt; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).convOrientation = - Convect::GetSurfConvOrientation(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Tilt); + if (newSurf.Sides > 2) { + Vectors::CreateNewellAreaVector(newSurf.Vertex, newSurf.Sides, newSurf.NewellAreaVector); + newSurf.GrossArea = Vectors::VecLength(newSurf.NewellAreaVector); + newSurf.Area = newSurf.GrossArea; + newSurf.NetAreaShadowCalc = newSurf.Area; + Vectors::CreateNewellSurfaceNormalVector(newSurf.Vertex, newSurf.Sides, newSurf.NewellSurfaceNormalVector); + Vectors::DetermineAzimuthAndTilt( + newSurf.Vertex, SurfWorldAz, SurfTilt, newSurf.lcsx, newSurf.lcsy, newSurf.lcsz, newSurf.NewellSurfaceNormalVector); + newSurf.Azimuth = SurfWorldAz; + newSurf.Tilt = SurfTilt; + newSurf.convOrientation = Convect::GetSurfConvOrientation(newSurf.Tilt); // Sine and cosine of azimuth and tilt - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinAzim = std::sin(SurfWorldAz * Constant::DegToRad); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosAzim = std::cos(SurfWorldAz * Constant::DegToRad); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinTilt = std::sin(SurfTilt * Constant::DegToRad); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt = std::cos(SurfTilt * Constant::DegToRad); + newSurf.SinAzim = std::sin(SurfWorldAz * Constant::DegToRad); + newSurf.CosAzim = std::cos(SurfWorldAz * Constant::DegToRad); + newSurf.SinTilt = std::sin(SurfTilt * Constant::DegToRad); + newSurf.CosTilt = std::cos(SurfTilt * Constant::DegToRad); // Outward normal unit vector (pointing away from room) - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec = - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).NewellSurfaceNormalVector; + newSurf.OutNormVec = newSurf.NewellSurfaceNormalVector; for (int n = 1; n <= 3; ++n) { - if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) - 1.0) < 1.e-06) - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = +1.0; - if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) + 1.0) < 1.e-06) - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = -1.0; - if (std::abs(state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n)) < 1.e-06) - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OutNormVec(n) = 0.0; + if (std::abs(newSurf.OutNormVec(n) - 1.0) < 1.e-06) newSurf.OutNormVec(n) = +1.0; + if (std::abs(newSurf.OutNormVec(n) + 1.0) < 1.e-06) newSurf.OutNormVec(n) = -1.0; + if (std::abs(newSurf.OutNormVec(n)) < 1.e-06) newSurf.OutNormVec(n) = 0.0; } // Can perform tests on this surface here - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky = - 0.5 * (1.0 + state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGround = - 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt); + newSurf.ViewFactorSky = 0.5 * (1.0 + newSurf.CosTilt); + newSurf.ViewFactorGround = 0.5 * (1.0 - newSurf.CosTilt); // The following IR view factors are modified in subr. SkyDifSolarShading if there are shadowing // surfaces - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSkyIR = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorSky; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ViewFactorGroundIR = - 0.5 * (1.0 - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt); + newSurf.ViewFactorSkyIR = newSurf.ViewFactorSky; + newSurf.ViewFactorGroundIR = 0.5 * (1.0 - newSurf.CosTilt); } // Change Name - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name = "iz-" + surfTemp.Name; + newSurf.Name = "iz-" + surfTemp.Name; // Debug write(outputfiledebug,*) ' new surf name=',TRIM(SurfaceTmp(CurNewSurf)%Name) // Debug write(outputfiledebug,*) ' new surf in zone=',TRIM(surfacetmp(curnewsurf)%zoneName) - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = UnreconciledZoneSurface; - surfTemp.ExtBoundCond = UnreconciledZoneSurface; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = surfTemp.Name; - surfTemp.ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name; - if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Roof || - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Wall || - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Floor) { + newSurf.ExtBoundCond = unreconciledZoneSurface; + surfTemp.ExtBoundCond = unreconciledZoneSurface; + newSurf.ExtBoundCondName = surfTemp.Name; + surfTemp.ExtBoundCondName = newSurf.Name; + if (newSurf.Class == SurfaceClass::Roof || newSurf.Class == SurfaceClass::Wall || newSurf.Class == SurfaceClass::Floor) { // base surface if (surfTemp.Class == SurfaceClass::Roof) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Floor; + newSurf.Class = SurfaceClass::Floor; // Debug write(outputfiledebug,*) ' new surfaces is a floor' } else if (surfTemp.Class == SurfaceClass::Floor) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Roof; + newSurf.Class = SurfaceClass::Roof; // Debug write(outputfiledebug,*) ' new surfaces is a roof' } - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = CurNewSurf; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Name; + newSurf.BaseSurf = CurNewSurf; + newSurf.BaseSurfName = newSurf.Name; // Debug write(outputfiledebug,*) ' basesurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName) } else { // subsurface - Found = + int Found = Util::FindItemInList("iz-" + surfTemp.BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, FirstTotalSurfaces + CurNewSurf - 1); if (Found > 0) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = "iz-" + surfTemp.BaseSurfName; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurf = Found; - state.dataSurfaceGeometry->SurfaceTmp(Found).Area -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area; - if (state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::Window || - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class == SurfaceClass::GlassDoor) { - state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -= - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area / state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Multiplier; + newSurf.BaseSurfName = "iz-" + surfTemp.BaseSurfName; + newSurf.BaseSurf = Found; + auto &foundBaseSurf = state.dataSurfaceGeometry->SurfaceTmp(Found); + foundBaseSurf.Area -= newSurf.Area; + if (newSurf.Class == SurfaceClass::Window || newSurf.Class == SurfaceClass::GlassDoor) { + foundBaseSurf.NetAreaShadowCalc -= newSurf.Area / newSurf.Multiplier; } else { // Door, TDD:Diffuser, TDD:DOME - state.dataSurfaceGeometry->SurfaceTmp(Found).NetAreaShadowCalc -= state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Area; - } - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCond = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = surfTemp.Name; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtSolar = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtSolar; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtWind = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtWind; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr; + foundBaseSurf.NetAreaShadowCalc -= newSurf.Area; + } + newSurf.ExtBoundCond = foundBaseSurf.ExtBoundCond; + newSurf.ExtBoundCondName = surfTemp.Name; + newSurf.ExtSolar = foundBaseSurf.ExtSolar; + newSurf.ExtWind = foundBaseSurf.ExtWind; + newSurf.Zone = foundBaseSurf.Zone; + newSurf.ZoneName = foundBaseSurf.ZoneName; + newSurf.spaceNum = foundBaseSurf.spaceNum; + newSurf.OSCPtr = foundBaseSurf.OSCPtr; // Debug write(outputfiledebug,*) ' subsurf, extboundcondname=',TRIM(SurfaceTmp(CurNewSurf)%ExtBoundCondName) // Debug write(outputfiledebug,*) ' subsurf, basesurf=',TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName) } else { @@ -1331,6 +1320,7 @@ namespace SurfaceGeometry { auto &surfTemp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); if (!surfTemp.HeatTransSurf) continue; + int Found = 0; // why are we doing this again? this should have already been done. if (Util::SameString(surfTemp.BaseSurfName, surfTemp.Name)) { Found = SurfNum; @@ -1658,8 +1648,9 @@ namespace SurfaceGeometry { // If other surface, match it up // Both interzone and "internal" surfaces have this pointer set // Internal surfaces point to themselves, Interzone to another - if (state.dataSurface->Surface(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { + if (state.dataSurface->Surface(SurfNum).ExtBoundCond == unreconciledZoneSurface) { if (not_blank(state.dataSurface->Surface(SurfNum).ExtBoundCondName)) { + int Found = 0; if (state.dataSurface->Surface(SurfNum).ExtBoundCondName == state.dataSurface->Surface(SurfNum).Name) { Found = SurfNum; } else { @@ -1669,7 +1660,7 @@ namespace SurfaceGeometry { state.dataSurface->Surface(SurfNum).ExtBoundCond = Found; // Check that matching surface is also "OtherZoneSurface" if (state.dataSurface->Surface(Found).ExtBoundCond <= 0 && - state.dataSurface->Surface(Found).ExtBoundCond != UnreconciledZoneSurface) { + state.dataSurface->Surface(Found).ExtBoundCond != unreconciledZoneSurface) { ShowSevereError(state, format("{}Potential \"OtherZoneSurface\" is not matched correctly:", RoutineName)); ShowContinueError(state, @@ -2705,6 +2696,7 @@ namespace SurfaceGeometry { void CreateMissingSpaces(EnergyPlusData &state, Array1D &Surfaces) { + static constexpr std::string_view RoutineName = "CreateMissingSpaces: "; // Scan surfaces to see if Space was assigned in input EPVector anySurfacesWithSpace; // True if any surfaces in a zone do not have a space assigned in input EPVector anySurfacesWithoutSpace; // True if any surfaces in a zone have a space assigned in input @@ -2721,7 +2713,10 @@ namespace SurfaceGeometry { } if (thisSurf.spaceNum > 0) { anySurfacesWithSpace(thisSurf.Zone) = true; - } else { + } else if (thisSurf.ExtBoundCond != unreconciledZoneSurface) { + anySurfacesWithoutSpace(thisSurf.Zone) = true; + } else if (thisSurf.Name.substr(0, 3) != "iz-") { + // Only trigger a new space if the spaceless surface is not an autogenerated interzone surface anySurfacesWithoutSpace(thisSurf.Zone) = true; } } @@ -2736,6 +2731,7 @@ namespace SurfaceGeometry { if (anySurfacesWithSpace(zoneNum)) { // Add new space ++state.dataGlobal->numSpaces; + assert(state.dataHeatBal->space.size() >= state.dataGlobal->numSpaces); state.dataHeatBal->space(state.dataGlobal->numSpaces).zoneNum = zoneNum; // Add to zone's list of spaces thisZone.spaceIndexes.emplace_back(state.dataGlobal->numSpaces); @@ -2761,6 +2757,21 @@ namespace SurfaceGeometry { int const numSpaces = state.dataHeatBal->Zone(thisSurf.Zone).numSpaces; int const lastSpaceForZone = state.dataHeatBal->Zone(thisSurf.Zone).spaceIndexes(numSpaces); thisSurf.spaceNum = lastSpaceForZone; + if ((thisSurf.ExtBoundCond == unreconciledZoneSurface) && (thisSurf.Name.substr(0, 3) == "iz-")) { + if (state.dataHeatBal->Zone(thisSurf.Zone).numSpaces > 1) { + // Only trigger warning if the spaceless surface is an autogenerated interzone surface + ShowWarningError(state, + format("{}Surface=\"{}\" has Outside Boundary Condition=Zone, but Zone=\"{}\" has more than 1 Space.", + RoutineName, + thisSurf.Name.substr(3), + thisSurf.ZoneName)); + ShowContinueError(state, + format("Auto-generated surface=\"{}\" will be assigned to Space=\"{}\"", + thisSurf.Name, + state.dataHeatBal->space(thisSurf.spaceNum).Name)); + ShowContinueError(state, "Use Outside Boundary Condition = Space to specify the exact Space for the outside boundary."); + } + } } } } @@ -3748,7 +3759,7 @@ namespace SurfaceGeometry { if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Outdoors")) { surfTemp.ExtBoundCond = DataSurfaces::ExternalEnvironment; } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Adiabatic")) { - surfTemp.ExtBoundCond = UnreconciledZoneSurface; + surfTemp.ExtBoundCond = unreconciledZoneSurface; surfTemp.ExtBoundCondName = surfTemp.Name; } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Ground")) { @@ -3827,7 +3838,7 @@ namespace SurfaceGeometry { // this will be found on the second pass through the surface input // for flagging, set the value to UnreconciledZoneSurface // name (ExtBoundCondName) will be validated later. - surfTemp.ExtBoundCond = UnreconciledZoneSurface; + surfTemp.ExtBoundCond = unreconciledZoneSurface; if (s_ipsc->lAlphaFieldBlanks(ArgPointer + 1)) { surfTemp.ExtBoundCondName = surfTemp.Name; ShowSevereError(state, @@ -3842,7 +3853,7 @@ namespace SurfaceGeometry { } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Zone")) { // This is the code for an unmatched "other surface" // will be set up later. - surfTemp.ExtBoundCond = UnenteredAdjacentZoneSurface; + surfTemp.ExtBoundCond = unenteredAdjacentZoneSurface; // check OutsideFaceEnvironment for legal zone Found = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); ++NeedToAddSurfaces; @@ -3858,6 +3869,26 @@ namespace SurfaceGeometry { ErrorsFound = true; } + } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Space")) { + // This is the code for an unmatched "other surface" + // will be set up later. + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unenteredAdjacentSpaceSurface; + // check OutsideFaceEnvironment for legal zone + Found = Util::FindItemInList( + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->space, state.dataGlobal->numSpaces); + ++NeedToAddSurfaces; + + if (Found == 0) { + ShowSevereError(state, + format("{}=\"{}\", invalid {}=\"{}\".", + s_ipsc->cCurrentModuleObject, + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name, + s_ipsc->cAlphaFieldNames(ArgPointer), + s_ipsc->cAlphaArgs(ArgPointer))); + ShowContinueError(state, "..Referenced as Space for this surface."); + ErrorsFound = true; + } + } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Foundation")) { if (!state.dataWeather->WeatherFileExists) { @@ -4090,7 +4121,7 @@ namespace SurfaceGeometry { // Check number of Vertex between base surface and Outside Boundary surface int ExtSurfNum; for (int i = 1; i <= SurfNum; i++) { - if (state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCond == UnreconciledZoneSurface && + if (state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCond == unreconciledZoneSurface && state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName != "") { ExtSurfNum = Util::FindItemInList(state.dataSurfaceGeometry->SurfaceTmp(i).ExtBoundCondName, state.dataSurfaceGeometry->SurfaceTmp); // If we cannot find the referenced surface @@ -4184,13 +4215,13 @@ namespace SurfaceGeometry { ItemsToGet = TotRectIntWalls; GettingIZSurfaces = false; OtherSurfaceField = 0; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 1; } else if (Item == 3) { ItemsToGet = TotRectIZWalls; GettingIZSurfaces = true; OtherSurfaceField = 5; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 1; } else if (Item == 4) { ItemsToGet = TotRectUGWalls; @@ -4208,13 +4239,13 @@ namespace SurfaceGeometry { ItemsToGet = TotRectCeilings; GettingIZSurfaces = false; OtherSurfaceField = 0; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 3; } else if (Item == 7) { ItemsToGet = TotRectIZCeilings; GettingIZSurfaces = false; OtherSurfaceField = 5; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 3; } else if (Item == 8) { ItemsToGet = TotRectGCFloors; @@ -4226,13 +4257,13 @@ namespace SurfaceGeometry { ItemsToGet = TotRectIntFloors; GettingIZSurfaces = false; OtherSurfaceField = 0; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 2; } else { // IF (Item == 10) THEN ItemsToGet = TotRectIZFloors; GettingIZSurfaces = true; OtherSurfaceField = 5; - ExtBoundCondition = UnreconciledZoneSurface; + ExtBoundCondition = unreconciledZoneSurface; ClassItem = 2; } @@ -4371,14 +4402,14 @@ namespace SurfaceGeometry { // surfTemp.ExtEcoRoof = // state.dataConstruction->Construct(surfTemp.Construction).TypeIsEcoRoof; - } else if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { + } else if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { if (GettingIZSurfaces) { surfTemp.ExtBoundCondName = s_ipsc->cAlphaArgs(OtherSurfaceField); Found = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); // see if match to zone, then it's an unentered other surface, else reconciled later if (Found > 0) { ++NeedToAddSurfaces; - surfTemp.ExtBoundCond = UnenteredAdjacentZoneSurface; + surfTemp.ExtBoundCond = unenteredAdjacentZoneSurface; } } else { surfTemp.ExtBoundCondName = surfTemp.Name; @@ -4840,7 +4871,7 @@ namespace SurfaceGeometry { surfTemp.Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; surfTemp.ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; surfTemp.OSCPtr = state.dataSurfaceGeometry->SurfaceTmp(Found).OSCPtr; - if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface && + if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == unreconciledZoneSurface && state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName == state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed ShowSevereError(state, @@ -4880,7 +4911,7 @@ namespace SurfaceGeometry { } } - if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (!s_ipsc->lAlphaFieldBlanks(5)) { surfTemp.ExtBoundCondName = s_ipsc->cAlphaArgs(5); } else { @@ -4895,7 +4926,8 @@ namespace SurfaceGeometry { } } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface + if ((surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) || + (surfTemp.ExtBoundCond == unenteredAdjacentSpaceSurface)) { // "Zone" - unmatched interior surface ++NeedToAddSurfaces; // ignoring window5datafiles for now -- will need to add. } @@ -5247,7 +5279,7 @@ namespace SurfaceGeometry { ErrorsFound = true; continue; } - if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == UnreconciledZoneSurface && + if (state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCond == unreconciledZoneSurface && state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName == state.dataSurfaceGeometry->SurfaceTmp(Found).Name) { // Adiabatic surface, no windows or doors allowed ShowSevereError(state, @@ -5262,7 +5294,7 @@ namespace SurfaceGeometry { "Interzone surfaces for transmission to result."); } - if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (!GettingIZSurfaces) { ShowSevereError(state, format("{}=\"{}\", invalid use of object", s_ipsc->cCurrentModuleObject, surfTemp.Name)); ShowContinueError( @@ -5276,18 +5308,18 @@ namespace SurfaceGeometry { } } - if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (GettingIZSurfaces) { surfTemp.ExtBoundCondName = s_ipsc->cAlphaArgs(OtherSurfaceField); IZFound = Util::FindItemInList(surfTemp.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); - if (IZFound > 0) surfTemp.ExtBoundCond = UnenteredAdjacentZoneSurface; + if (IZFound > 0) surfTemp.ExtBoundCond = unenteredAdjacentZoneSurface; } else { // Interior Window surfTemp.ExtBoundCondName = surfTemp.Name; } } // This is the parent's property: - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface if (GettingIZSurfaces) { ++NeedToAddSubSurfaces; } else { // Interior Window @@ -5305,11 +5337,11 @@ namespace SurfaceGeometry { if (GettingIZSurfaces) { if (s_ipsc->lAlphaFieldBlanks(OtherSurfaceField)) { // blank -- set it up for unentered adjacent zone - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { // already set but need Zone + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { // already set but need Zone surfTemp.ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName; // base surface has it - } else if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { + } else if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { surfTemp.ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // base surface has it - surfTemp.ExtBoundCond = UnenteredAdjacentZoneSurface; + surfTemp.ExtBoundCond = unenteredAdjacentZoneSurface; } else { // not correct boundary condition for interzone subsurface ShowSevereError( state, @@ -6058,7 +6090,7 @@ namespace SurfaceGeometry { s_ipsc->cAlphaArgs(2))); ErrorsFound = true; } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6070,7 +6102,7 @@ namespace SurfaceGeometry { surfTemp.ExtBoundCond = DataSurfaces::ExternalEnvironment; // reset so program won't crash during "add surfaces" } - if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { + if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6255,7 +6287,7 @@ namespace SurfaceGeometry { ErrorsFound = true; continue; } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6266,7 +6298,7 @@ namespace SurfaceGeometry { ErrorsFound = true; surfTemp.ExtBoundCond = DataSurfaces::ExternalEnvironment; // reset so program won't crash during "add surfaces" } - if (surfTemp.ExtBoundCond == UnreconciledZoneSurface) { + if (surfTemp.ExtBoundCond == unreconciledZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6813,7 +6845,7 @@ namespace SurfaceGeometry { surfTemp.BaseSurf = SurfNum; surfTemp.BaseSurfName = surfTemp.Name; surfTemp.ExtBoundCondName = surfTemp.Name; - surfTemp.ExtBoundCond = UnreconciledZoneSurface; + surfTemp.ExtBoundCond = unreconciledZoneSurface; } } } diff --git a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc index f11cfcea2df..61b4495842e 100644 --- a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc +++ b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc @@ -14591,3 +14591,1524 @@ TEST_F(EnergyPlusFixture, ExtSolarForShadingTest) EXPECT_FALSE(thisSG->SurfaceTmp(8).HeatTransSurf); EXPECT_TRUE(thisSG->SurfaceTmp(8).ExtSolar); } +TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) +{ + // Two 10x10m zones. A door between both that has a Construction:AirBoundary assigned (its base surface is a regular interior wall) + std::string const idf_objects = delimited_string({ + + "Material,", + " 8IN Concrete HW, !- Name", + " MediumRough, !- Roughness", + " 0.2033, !- Thickness {m}", + " 1.72959999999999, !- Conductivity {W/m-K}", + " 2242.99999999999, !- Density {kg/m3}", + " 836.999999999999, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.65, !- Solar Absorptance", + " 0.65; !- Visible Absorptance", + + "Material,", + " Gypsum Board, !- Name", + " MediumSmooth, !- Roughness", + " 0.0159, !- Thickness {m}", + " 0.16, !- Conductivity {W/m-K}", + " 800, !- Density {kg/m3}", + " 1090, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.7, !- Solar Absorptance", + " 0.7; !- Visible Absorptance", + + "Construction,", + " Regular Construction, !- Name", + " 8IN Concrete HW, !- Layer 1", + " Gypsum Board; !- Layer 2", + + "Zone,", + " Zone1; !- Name", + + "Zone,", + " Zone2; !- Name", + + "Zone,", + " Zone3; !- Name", + + "BuildingSurface:Detailed,", + " Space1-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Zone, !- Outside Boundary Condition", + " Zone2, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorDoor, !- Name", + " Door, !- Surface Type", + " Regular Construction, !- Construction Name", + " Space1-InteriorWall, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-West, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " , !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " , !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall2, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " , !- Space Name", + " Zone, !- Outside Boundary Condition", + " Zone3, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorWindow, !- Name", + " Window, !- Surface Type", + " SINGLE PANE HW WINDOW, !- Construction Name", + " Space1-InteriorWall2, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + " Construction,", + " SINGLE PANE HW WINDOW, !- Name", + " GLASS - CLEAR PLATE 1 / 4 IN; !- Outside Layer", + + " WindowMaterial:Glazing,", + " GLASS - CLEAR PLATE 1 / 4 IN, !- Name", + " SpectralAverage, !- Optical Data Type", + " , !- Window Glass Spectral Data Set Name", + " 6.0000001E-03, !- Thickness {m}", + " 0.7750000, !- Solar Transmittance at Normal Incidence", + " 7.1000002E-02, !- Front Side Solar Reflectance at Normal Incidence", + " 7.1000002E-02, !- Back Side Solar Reflectance at Normal Incidence", + " 0.8810000, !- Visible Transmittance at Normal Incidence", + " 7.9999998E-02, !- Front Side Visible Reflectance at Normal Incidence", + " 7.9999998E-02, !- Back Side Visible Reflectance at Normal Incidence", + " 0, !- Infrared Transmittance at Normal Incidence", + " 0.8400000, !- Front Side Infrared Hemispherical Emissivity", + " 0.8400000, !- Back Side Infrared Hemispherical Emissivity", + " 0.9000000; !- Conductivity {W/m-K}", + }); + ASSERT_TRUE(process_idf(idf_objects)); + state->init_state(*state); + + bool ErrorsFound = false; + + GetMaterialData(*state, ErrorsFound); // read material data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetConstructData(*state, ErrorsFound); // read construction data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetZoneData(*state, ErrorsFound); // read zone data + EXPECT_FALSE(ErrorsFound); // expect no errors + + // This is ill-named, but it will shut the "No Ground Temperature" warning when set to false + state->dataSurfaceGeometry->NoGroundTempObjWarning = false; + + // I don't do ASSERT_NO_THROW because I want to see the err stream to show original defect. But I ASSERT there's no err_stream because we can't + // continue if it did throw + EXPECT_NO_THROW(SetupZoneGeometry(*state, ErrorsFound)); + ASSERT_TRUE(compare_err_stream( + " ** Warning ** CalculateZoneVolume: 1 zone is not fully enclosed. For more details use: Output:Diagnostics,DisplayExtrawarnings; \n")); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 3); + EXPECT_EQ("ZONE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("ZONE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("ZONE3", state->dataViewFactor->EnclRadInfo(3).Name); + EXPECT_EQ("ZONE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("ZONE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ("ZONE3", state->dataViewFactor->EnclRadInfo(3).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(3).radiantEnclosureNum, 3); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 9); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(3).surfaces.size(), 7); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int originalIntWall2Num = Util::FindItemInList("SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int originalIntWinNum = Util::FindItemInList("SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWall2Num = Util::FindItemInList("iz-SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int izIntWinNum = Util::FindItemInList("iz-SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &originalIntWall2 = state->dataSurface->Surface(originalIntWall2Num); + auto &originalIntWin = state->dataSurface->Surface(originalIntWinNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + auto &izIntWall2 = state->dataSurface->Surface(izIntWall2Num); + auto &izIntWin = state->dataSurface->Surface(izIntWinNum); + + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone2 + EXPECT_EQ(originalIntWall.Zone, 1); + EXPECT_EQ(originalIntWall.spaceNum, 1); + EXPECT_EQ(originalIntWall.ExtBoundCond, izIntWallNum); + EXPECT_EQ(originalIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone2, points to original wall in Zone1 + EXPECT_EQ(izIntWall.Zone, 2); + EXPECT_EQ(izIntWall.spaceNum, 2); + EXPECT_EQ(izIntWall.ExtBoundCond, originalIntWallNum); + EXPECT_EQ(izIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone3, Space3 + EXPECT_EQ(originalIntWall2.Zone, 1); + EXPECT_EQ(originalIntWall2.spaceNum, 1); + EXPECT_EQ(originalIntWall2.ExtBoundCond, izIntWall2Num); + EXPECT_EQ(originalIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall2.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone3, Space3, points to original wall in Zone1 + EXPECT_EQ(izIntWall2.Zone, 3); + EXPECT_EQ(izIntWall2.spaceNum, 3); + EXPECT_EQ(izIntWall2.ExtBoundCond, originalIntWall2Num); + EXPECT_EQ(izIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall2.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Door input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated door in Zone2 + EXPECT_EQ(originalIntDoor.Zone, 1); + EXPECT_EQ(originalIntDoor.spaceNum, 1); + EXPECT_EQ(originalIntDoor.ExtBoundCond, izIntDoorNum); + EXPECT_EQ(originalIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(originalIntDoor.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated door in Zone2, points to original door in Zone1 + EXPECT_EQ(izIntDoor.Zone, 2); + EXPECT_EQ(izIntDoor.spaceNum, 2); + EXPECT_EQ(izIntDoor.ExtBoundCond, originalIntDoorNum); + EXPECT_EQ(izIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(izIntDoor.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Window input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated window in Zone3, Space3 + EXPECT_EQ(originalIntWin.Zone, 1); + EXPECT_EQ(originalIntWin.spaceNum, 1); + EXPECT_EQ(originalIntWin.ExtBoundCond, izIntWinNum); + EXPECT_EQ(originalIntWin.Class, DataSurfaces::SurfaceClass::Window); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); + // Auto-generated window in Zone3, points to original window in Zone1 + EXPECT_EQ(izIntWin.Zone, 3); + EXPECT_EQ(izIntWin.spaceNum, 3); + EXPECT_EQ(izIntWin.ExtBoundCond, originalIntWinNum); + EXPECT_EQ(izIntWin.Class, DataSurfaces::SurfaceClass::Window); + // SINGLE PANE HW WINDOW is a single-layer construction, so the same construction works for both sides + EXPECT_EQ(state->dataConstruction->Construct(izIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); +} +TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) +{ + // Two 10x10m zones. A door between both that has a Construction:AirBoundary assigned (its base surface is a regular interior wall) + std::string const idf_objects = delimited_string({ + + "Material,", + " 8IN Concrete HW, !- Name", + " MediumRough, !- Roughness", + " 0.2033, !- Thickness {m}", + " 1.72959999999999, !- Conductivity {W/m-K}", + " 2242.99999999999, !- Density {kg/m3}", + " 836.999999999999, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.65, !- Solar Absorptance", + " 0.65; !- Visible Absorptance", + + "Material,", + " Gypsum Board, !- Name", + " MediumSmooth, !- Roughness", + " 0.0159, !- Thickness {m}", + " 0.16, !- Conductivity {W/m-K}", + " 800, !- Density {kg/m3}", + " 1090, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.7, !- Solar Absorptance", + " 0.7; !- Visible Absorptance", + + "Construction,", + " Regular Construction, !- Name", + " 8IN Concrete HW, !- Layer 1", + " Gypsum Board; !- Layer 2", + + "Zone,", + " Zone1; !- Name", + + "Zone,", + " Zone2; !- Name", + + "Zone,", + " Zone3; !- Name", + + "Space,", + " Space1, !- Name", + " Zone1; !- Zone Name", + + "Space,", + " Space2, !- Name", + " Zone2; !- Zone Name", + + "Space,", + " Space3a, !- Name", + " Zone3; !- Zone Name", + + "Space,", + " Space3b, !- Name", + " Zone3; !- Zone Name", + + "BuildingSurface:Detailed,", + " Space1-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Zone, !- Outside Boundary Condition", + " Zone2, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorDoor, !- Name", + " Door, !- Surface Type", + " Regular Construction, !- Construction Name", + " Space1-InteriorWall, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-West, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3b, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3b, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall2, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Zone, !- Outside Boundary Condition", + " Zone3, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorWindow, !- Name", + " Window, !- Surface Type", + " SINGLE PANE HW WINDOW, !- Construction Name", + " Space1-InteriorWall2, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + " Construction,", + " SINGLE PANE HW WINDOW, !- Name", + " GLASS - CLEAR PLATE 1 / 4 IN; !- Outside Layer", + + " WindowMaterial:Glazing,", + " GLASS - CLEAR PLATE 1 / 4 IN, !- Name", + " SpectralAverage, !- Optical Data Type", + " , !- Window Glass Spectral Data Set Name", + " 6.0000001E-03, !- Thickness {m}", + " 0.7750000, !- Solar Transmittance at Normal Incidence", + " 7.1000002E-02, !- Front Side Solar Reflectance at Normal Incidence", + " 7.1000002E-02, !- Back Side Solar Reflectance at Normal Incidence", + " 0.8810000, !- Visible Transmittance at Normal Incidence", + " 7.9999998E-02, !- Front Side Visible Reflectance at Normal Incidence", + " 7.9999998E-02, !- Back Side Visible Reflectance at Normal Incidence", + " 0, !- Infrared Transmittance at Normal Incidence", + " 0.8400000, !- Front Side Infrared Hemispherical Emissivity", + " 0.8400000, !- Back Side Infrared Hemispherical Emissivity", + " 0.9000000; !- Conductivity {W/m-K}", + + }); + ASSERT_TRUE(process_idf(idf_objects)); + state->init_state(*state); + + bool ErrorsFound = false; + + GetMaterialData(*state, ErrorsFound); // read material data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetConstructData(*state, ErrorsFound); // read construction data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetZoneData(*state, ErrorsFound); // read zone data + EXPECT_FALSE(ErrorsFound); // expect no errors + + // This is ill-named, but it will shut the "No Ground Temperature" warning when set to false + state->dataSurfaceGeometry->NoGroundTempObjWarning = false; + + // I don't do ASSERT_NO_THROW because I want to see the err stream to show original defect. But I ASSERT there's no err_stream because we can't + // continue if it did throw + EXPECT_NO_THROW(SetupZoneGeometry(*state, ErrorsFound)); + + std::string const error_string = delimited_string( + {" ** Warning ** CreateMissingSpaces: Surface=\"SPACE1-INTERIORWALL2\" has Outside Boundary Condition=Zone, but Zone=\"ZONE3\" has more " + "than 1 Space.", + " ** ~~~ ** Auto-generated surface=\"iz-SPACE1-INTERIORWALL2\" will be assigned to Space=\"SPACE3B\"", + " ** ~~~ ** Use Outside Boundary Condition = Space to specify the exact Space for the outside boundary.", + " ** Warning ** CreateMissingSpaces: Surface=\"SPACE1-INTERIORWINDOW\" has Outside Boundary Condition=Zone, but Zone=\"ZONE3\" has more " + "than 1 Space.", + " ** ~~~ ** Auto-generated surface=\"iz-SPACE1-INTERIORWINDOW\" will be assigned to Space=\"SPACE3B\"", + " ** ~~~ ** Use Outside Boundary Condition = Space to specify the exact Space for the outside boundary.", + " ** Warning ** CalculateZoneVolume: 1 zone is not fully enclosed. For more details use: Output:Diagnostics,DisplayExtrawarnings; "}); + + ASSERT_TRUE(compare_err_stream(error_string)); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 4); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("SPACE3A", state->dataViewFactor->EnclRadInfo(3).Name); + EXPECT_EQ("SPACE3B", state->dataViewFactor->EnclRadInfo(4).Name); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ("SPACE3A", state->dataViewFactor->EnclRadInfo(3).spaceNames[0]); + EXPECT_EQ("SPACE3B", state->dataViewFactor->EnclRadInfo(4).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(3).radiantEnclosureNum, 3); + EXPECT_EQ(state->dataHeatBal->space(4).radiantEnclosureNum, 4); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 9); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(3).surfaces.size(), 3); + EXPECT_EQ(state->dataHeatBal->space(4).surfaces.size(), 4); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int originalIntWall2Num = Util::FindItemInList("SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int originalIntWinNum = Util::FindItemInList("SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWall2Num = Util::FindItemInList("iz-SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int izIntWinNum = Util::FindItemInList("iz-SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &originalIntWall2 = state->dataSurface->Surface(originalIntWall2Num); + auto &originalIntWin = state->dataSurface->Surface(originalIntWinNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + auto &izIntWall2 = state->dataSurface->Surface(izIntWall2Num); + auto &izIntWin = state->dataSurface->Surface(izIntWinNum); + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone2 + EXPECT_EQ(originalIntWall.Zone, 1); + EXPECT_EQ(originalIntWall.spaceNum, 1); + EXPECT_EQ(originalIntWall.ExtBoundCond, izIntWallNum); + EXPECT_EQ(originalIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone2, points to original wall in Zone1 + EXPECT_EQ(izIntWall.Zone, 2); + EXPECT_EQ(izIntWall.spaceNum, 2); + EXPECT_EQ(izIntWall.ExtBoundCond, originalIntWallNum); + EXPECT_EQ(izIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone3, Space3B + EXPECT_EQ(originalIntWall2.Zone, 1); + EXPECT_EQ(originalIntWall2.spaceNum, 1); + EXPECT_EQ(originalIntWall2.ExtBoundCond, izIntWall2Num); + EXPECT_EQ(originalIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall2.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone3, Space3B, points to original wall in Zone1 + EXPECT_EQ(izIntWall2.Zone, 3); + EXPECT_EQ(izIntWall2.spaceNum, 4); + EXPECT_EQ(izIntWall2.ExtBoundCond, originalIntWall2Num); + EXPECT_EQ(izIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall2.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Door input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated door in Zone2 + EXPECT_EQ(originalIntDoor.Zone, 1); + EXPECT_EQ(originalIntDoor.spaceNum, 1); + EXPECT_EQ(originalIntDoor.ExtBoundCond, izIntDoorNum); + EXPECT_EQ(originalIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(originalIntDoor.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated door in Zone2, points to original door in Zone1 + EXPECT_EQ(izIntDoor.Zone, 2); + EXPECT_EQ(izIntDoor.spaceNum, 2); + EXPECT_EQ(izIntDoor.ExtBoundCond, originalIntDoorNum); + EXPECT_EQ(izIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(izIntDoor.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Window input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated window in Zone3, Space3B + EXPECT_EQ(originalIntWin.Zone, 1); + EXPECT_EQ(originalIntWin.spaceNum, 1); + EXPECT_EQ(originalIntWin.ExtBoundCond, izIntWinNum); + EXPECT_EQ(originalIntWin.Class, DataSurfaces::SurfaceClass::Window); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); + // Auto-generated window in Zone3, Space3B, points to original window in Zone1 + EXPECT_EQ(izIntWin.Zone, 3); + EXPECT_EQ(izIntWin.spaceNum, 4); + EXPECT_EQ(izIntWin.ExtBoundCond, originalIntWinNum); + EXPECT_EQ(izIntWin.Class, DataSurfaces::SurfaceClass::Window); + // SINGLE PANE HW WINDOW is a single-layer construction, so the same construction works for both sides + EXPECT_EQ(state->dataConstruction->Construct(izIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); +} +TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) +{ + // Two 10x10m zones. A door between both that has a Construction:AirBoundary assigned (its base surface is a regular interior wall) + std::string const idf_objects = delimited_string({ + + "Material,", + " 8IN Concrete HW, !- Name", + " MediumRough, !- Roughness", + " 0.2033, !- Thickness {m}", + " 1.72959999999999, !- Conductivity {W/m-K}", + " 2242.99999999999, !- Density {kg/m3}", + " 836.999999999999, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.65, !- Solar Absorptance", + " 0.65; !- Visible Absorptance", + + "Material,", + " Gypsum Board, !- Name", + " MediumSmooth, !- Roughness", + " 0.0159, !- Thickness {m}", + " 0.16, !- Conductivity {W/m-K}", + " 800, !- Density {kg/m3}", + " 1090, !- Specific Heat {J/kg-K}", + " 0.9, !- Thermal Absorptance", + " 0.7, !- Solar Absorptance", + " 0.7; !- Visible Absorptance", + + "Construction,", + " Regular Construction, !- Name", + " 8IN Concrete HW, !- Layer 1", + " Gypsum Board; !- Layer 2", + + "Zone,", + " Zone1; !- Name", + + "Zone,", + " Zone2; !- Name", + + "Zone,", + " Zone3; !- Name", + + "Space,", + " Space1, !- Name", + " Zone1; !- Zone Name", + + "Space,", + " Space2, !- Name", + " Zone2; !- Zone Name", + + "Space,", + " Space3a, !- Name", + " Zone3; !- Zone Name", + + "Space,", + " Space3b, !- Name", + " Zone3; !- Zone Name", + + "BuildingSurface:Detailed,", + " Space1-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Space, !- Outside Boundary Condition", + " Space2, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorDoor, !- Name", + " Door, !- Surface Type", + " Regular Construction, !- Construction Name", + " Space1-InteriorWall, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-Wall-West, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 0, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 0, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 0, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 0, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space2-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone2, !- Zone Name", + " Space2, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Ceiling, !- Name", + " Roof, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 10, 2.4384, !- X,Y,Z Vertex 3 {m}", + " 10, 0, 2.4384; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Floor, !- Name", + " Floor, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Ground, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 0, 0, !- X,Y,Z Vertex 1 {m}", + " 10, 10, 0, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-East, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3b, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-North, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3b, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 20, 10, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 20, 10, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Zone3-Wall-South, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone3, !- Zone Name", + " Space3a, !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 20, 0, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 20, 0, 0; !- X,Y,Z Vertex 4 {m}", + + "BuildingSurface:Detailed,", + " Space1-InteriorWall2, !- Name", + " Wall, !- Surface Type", + " Regular Construction, !- Construction Name", + " Zone1, !- Zone Name", + " Space1, !- Space Name", + " Space, !- Outside Boundary Condition", + " Space3a, !- Outside Boundary Condition Object", + " NoSun, !- Sun Exposure", + " NoWind, !- Wind Exposure", + " , !- View Factor to Ground", + " , !- Number of Vertices", + " 10, 10, 2.4384, !- X,Y,Z Vertex 1 {m}", + " 10, 0, 2.4384, !- X,Y,Z Vertex 2 {m}", + " 10, 0, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 10, 0; !- X,Y,Z Vertex 4 {m}", + + "FenestrationSurface:Detailed,", + " Space1-InteriorWindow, !- Name", + " Window, !- Surface Type", + " SINGLE PANE HW WINDOW, !- Construction Name", + " Space1-InteriorWall2, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " , !- View Factor to Ground", + " , !- Frame and Divider Name", + " , !- Multiplier", + " , !- Number of Vertices", + " 10, 7.05, 2, !- X,Y,Z Vertex 1 {m}", + " 10, 7.05, 0, !- X,Y,Z Vertex 2 {m}", + " 10, 7.95, 0, !- X,Y,Z Vertex 3 {m}", + " 10, 7.95, 2; !- X,Y,Z Vertex 4 {m}", + + " Construction,", + " SINGLE PANE HW WINDOW, !- Name", + " GLASS - CLEAR PLATE 1 / 4 IN; !- Outside Layer", + + " WindowMaterial:Glazing,", + " GLASS - CLEAR PLATE 1 / 4 IN, !- Name", + " SpectralAverage, !- Optical Data Type", + " , !- Window Glass Spectral Data Set Name", + " 6.0000001E-03, !- Thickness {m}", + " 0.7750000, !- Solar Transmittance at Normal Incidence", + " 7.1000002E-02, !- Front Side Solar Reflectance at Normal Incidence", + " 7.1000002E-02, !- Back Side Solar Reflectance at Normal Incidence", + " 0.8810000, !- Visible Transmittance at Normal Incidence", + " 7.9999998E-02, !- Front Side Visible Reflectance at Normal Incidence", + " 7.9999998E-02, !- Back Side Visible Reflectance at Normal Incidence", + " 0, !- Infrared Transmittance at Normal Incidence", + " 0.8400000, !- Front Side Infrared Hemispherical Emissivity", + " 0.8400000, !- Back Side Infrared Hemispherical Emissivity", + " 0.9000000; !- Conductivity {W/m-K}", + + }); + ASSERT_TRUE(process_idf(idf_objects)); + state->init_state(*state); + + bool ErrorsFound = false; + + GetMaterialData(*state, ErrorsFound); // read material data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetConstructData(*state, ErrorsFound); // read construction data + EXPECT_FALSE(ErrorsFound); // expect no errors + + GetZoneData(*state, ErrorsFound); // read zone data + EXPECT_FALSE(ErrorsFound); // expect no errors + + // This is ill-named, but it will shut the "No Ground Temperature" warning when set to false + state->dataSurfaceGeometry->NoGroundTempObjWarning = false; + + // I don't do ASSERT_NO_THROW because I want to see the err stream to show original defect. But I ASSERT there's no err_stream because we can't + // continue if it did throw + EXPECT_NO_THROW(SetupZoneGeometry(*state, ErrorsFound)); + ASSERT_TRUE(compare_err_stream( + " ** Warning ** CalculateZoneVolume: 1 zone is not fully enclosed. For more details use: Output:Diagnostics,DisplayExtrawarnings; \n")); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 4); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("SPACE3A", state->dataViewFactor->EnclRadInfo(3).Name); + EXPECT_EQ("SPACE3B", state->dataViewFactor->EnclRadInfo(4).Name); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ("SPACE3A", state->dataViewFactor->EnclRadInfo(3).spaceNames[0]); + EXPECT_EQ("SPACE3B", state->dataViewFactor->EnclRadInfo(4).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(3).radiantEnclosureNum, 3); + EXPECT_EQ(state->dataHeatBal->space(4).radiantEnclosureNum, 4); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 9); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(3).surfaces.size(), 5); + EXPECT_EQ(state->dataHeatBal->space(4).surfaces.size(), 2); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int originalIntWall2Num = Util::FindItemInList("SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int originalIntWinNum = Util::FindItemInList("SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWall2Num = Util::FindItemInList("iz-SPACE1-INTERIORWALL2", state->dataSurface->Surface); + int izIntWinNum = Util::FindItemInList("iz-SPACE1-INTERIORWINDOW", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &originalIntWall2 = state->dataSurface->Surface(originalIntWall2Num); + auto &originalIntWin = state->dataSurface->Surface(originalIntWinNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + auto &izIntWall2 = state->dataSurface->Surface(izIntWall2Num); + auto &izIntWin = state->dataSurface->Surface(izIntWinNum); + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone2 + EXPECT_EQ(originalIntWall.Zone, 1); + EXPECT_EQ(originalIntWall.spaceNum, 1); + EXPECT_EQ(originalIntWall.ExtBoundCond, izIntWallNum); + EXPECT_EQ(originalIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone2, points to original wall in Zone1 + EXPECT_EQ(izIntWall.Zone, 2); + EXPECT_EQ(izIntWall.spaceNum, 2); + EXPECT_EQ(izIntWall.ExtBoundCond, originalIntWallNum); + EXPECT_EQ(izIntWall.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original wall input with Zone outside boundary condition + // Now points to auto-generated wall in Zone3, Space3B + EXPECT_EQ(originalIntWall2.Zone, 1); + EXPECT_EQ(originalIntWall2.spaceNum, 1); + EXPECT_EQ(originalIntWall2.ExtBoundCond, izIntWall2Num); + EXPECT_EQ(originalIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWall2.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated wall in Zone3, Space3A, points to original wall in Zone1 + EXPECT_EQ(izIntWall2.Zone, 3); + EXPECT_EQ(izIntWall2.spaceNum, 3); + EXPECT_EQ(izIntWall2.ExtBoundCond, originalIntWall2Num); + EXPECT_EQ(izIntWall2.Class, DataSurfaces::SurfaceClass::Wall); + EXPECT_EQ(state->dataConstruction->Construct(izIntWall2.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Door input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated door in Zone2 + EXPECT_EQ(originalIntDoor.Zone, 1); + EXPECT_EQ(originalIntDoor.spaceNum, 1); + EXPECT_EQ(originalIntDoor.ExtBoundCond, izIntDoorNum); + EXPECT_EQ(originalIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(originalIntDoor.Construction).Name, "REGULAR CONSTRUCTION"); + // Auto-generated door in Zone2, points to original door in Zone1 + EXPECT_EQ(izIntDoor.Zone, 2); + EXPECT_EQ(izIntDoor.spaceNum, 2); + EXPECT_EQ(izIntDoor.ExtBoundCond, originalIntDoorNum); + EXPECT_EQ(izIntDoor.Class, DataSurfaces::SurfaceClass::Door); + EXPECT_EQ(state->dataConstruction->Construct(izIntDoor.Construction).Name, "iz-REGULAR CONSTRUCTION"); + // Original Window input with blank outside boundary condition, inherits base surface boundary condition + // Now points to auto-generated window in Zone3, Space3B + EXPECT_EQ(originalIntWin.Zone, 1); + EXPECT_EQ(originalIntWin.spaceNum, 1); + EXPECT_EQ(originalIntWin.ExtBoundCond, izIntWinNum); + EXPECT_EQ(originalIntWin.Class, DataSurfaces::SurfaceClass::Window); + EXPECT_EQ(state->dataConstruction->Construct(originalIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); + // Auto-generated window in Zone3, Space3a points to original window in Zone1 + EXPECT_EQ(izIntWin.Zone, 3); + EXPECT_EQ(izIntWin.spaceNum, 3); + EXPECT_EQ(izIntWin.ExtBoundCond, originalIntWinNum); + EXPECT_EQ(izIntWin.Class, DataSurfaces::SurfaceClass::Window); + // SINGLE PANE HW WINDOW is a single-layer construction, so the same construction works for both sides + EXPECT_EQ(state->dataConstruction->Construct(izIntWin.Construction).Name, "SINGLE PANE HW WINDOW"); +}