From 4867cf25c6a060861784b6d8679ea7aae4841981 Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Tue, 21 Jan 2025 16:31:52 -0600 Subject: [PATCH 01/11] Add Space as outside boundary condition choice - IDD --- idd/Energy+.idd.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index 38ae62ec980..79704e85be7 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 @@ -11381,6 +11383,7 @@ Wall:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Foundation \key Ground @@ -11572,6 +11575,7 @@ RoofCeiling:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Ground \key OtherSideCoefficients @@ -11761,6 +11765,7 @@ Floor:Detailed, \key Adiabatic \key Surface \key Zone + \key Space \key Outdoors \key Foundation \key Ground From e2663ea2d709d87ea8dd39d296c9b353684006ba Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Wed, 22 Jan 2025 16:55:08 -0600 Subject: [PATCH 02/11] Initial fix for Zone outside boundary condition --- src/EnergyPlus/SurfaceGeometry.cc | 271 ++++++++++++++++-------------- 1 file changed, 145 insertions(+), 126 deletions(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index ca9df306b89..c0cd1f4c61f 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -109,9 +109,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) { @@ -998,7 +1000,6 @@ namespace SurfaceGeometry { static constexpr std::string_view RoutineName = "GetSurfaceData: "; - int Found; // For matching interzone surfaces bool NonMatch(false); // Error for non-matching interzone surfaces int MovedSurfs; // Number of Moved Surfaces (when sorting into hierarchical structure) bool SurfError(false); // General Surface Error, causes fatal error at end of routine @@ -1195,134 +1196,130 @@ namespace SurfaceGeometry { // add the "need to add" surfaces // Debug write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) { - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond != UnenteredAdjacentZoneSurface) continue; + auto &curSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); + if ((curSurf.ExtBoundCond != unenteredAdjacentZoneSurface) && (curSurf.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 = curSurf; // Basic parameters are the same for both surfaces. - Found = Util::FindItemInList( - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).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 (curSurf.ExtBoundCond == unenteredAdjacentZoneSurface) { + int Found = Util::FindItemInList(curSurf.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 = newZone.spaceIndexes[0]; + if (newZone.spaceIndexes.size() > 1) { + ShowWarningError( + state, format("{}Outside Boundary Condition=Zone but Zone has more than one Space, Surface={}", RoutineName, curSurf.Name)); + ShowContinueError( + state, + format("Zone={}. Setting outside boundary to first Space={}. For more control, use Outside Boundary Condition=Space.", + newZone.Name, + state.dataHeatBal->space(newSurf.spaceNum).Name)); + } + } else if (curSurf.ExtBoundCond == unenteredAdjacentSpaceSurface) { + int Found = Util::FindItemInList(curSurf.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, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction, SurfError); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ConstructionStoredInputValue = - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Construction; + newSurf.Construction = DataHeatBalance::AssignReverseConstructionNumber(state, curSurf.Construction, SurfError); + newSurf.ConstructionStoredInputValue = newSurf.Construction; // Reverse Vertices - int NVert = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; - for (int Vert = 1; Vert <= state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Sides; ++Vert) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Vertex(Vert) = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Vertex(NVert); + int NVert = curSurf.Sides; + for (int Vert = 1; Vert <= curSurf.Sides; ++Vert) { + newSurf.Vertex(Vert) = curSurf.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::DegToRadians); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).SinTilt = std::sin(SurfTilt * Constant::DegToRadians); - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).CosTilt = std::cos(SurfTilt * Constant::DegToRadians); + newSurf.SinAzim = std::sin(SurfWorldAz * Constant::DegToRadians); + newSurf.CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians); + newSurf.SinTilt = std::sin(SurfTilt * Constant::DegToRadians); + newSurf.CosTilt = std::cos(SurfTilt * Constant::DegToRadians); // 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-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; + newSurf.Name = "iz-" + curSurf.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; - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface; - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).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; + curSurf.ExtBoundCond = unreconciledZoneSurface; + newSurf.ExtBoundCondName = curSurf.Name; + curSurf.ExtBoundCondName = newSurf.Name; + if (newSurf.Class == SurfaceClass::Roof || newSurf.Class == SurfaceClass::Wall || newSurf.Class == SurfaceClass::Floor) { // base surface - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Roof) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Floor; + if (curSurf.Class == SurfaceClass::Roof) { + newSurf.Class = SurfaceClass::Floor; // Debug write(outputfiledebug,*) ' new surfaces is a floor' - } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Class == SurfaceClass::Floor) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).Class = SurfaceClass::Roof; + } else if (curSurf.Class == SurfaceClass::Floor) { + 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 = Util::FindItemInList("iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, - state.dataSurfaceGeometry->SurfaceTmp, - FirstTotalSurfaces + CurNewSurf - 1); + int Found = + Util::FindItemInList("iz-" + curSurf.BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, FirstTotalSurfaces + CurNewSurf - 1); if (Found > 0) { - state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf).BaseSurfName = - "iz-" + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).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-" + curSurf.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 = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).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 = curSurf.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 { ShowSevereError(state, - format("{}Adding unentered subsurface, could not find base surface=iz-{}", - RoutineName, - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName)); + format("{}Adding unentered subsurface, could not find base surface=iz-{}", RoutineName, curSurf.BaseSurfName)); SurfError = true; } } @@ -1334,6 +1331,7 @@ namespace SurfaceGeometry { for (int SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) { if (!state.dataSurfaceGeometry->SurfaceTmp(SurfNum).HeatTransSurf) continue; + int Found = 0; // why are we doing this again? this should have already been done. if (Util::SameString(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name)) { Found = SurfNum; @@ -1666,8 +1664,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 { @@ -1677,7 +1676,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, @@ -3777,7 +3776,7 @@ namespace SurfaceGeometry { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = DataSurfaces::ExternalEnvironment; } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Adiabatic")) { - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unreconciledZoneSurface; state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; } else if (Util::SameString(s_ipsc->cAlphaArgs(ArgPointer), "Ground")) { @@ -3866,7 +3865,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. - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unreconciledZoneSurface; if (s_ipsc->lAlphaFieldBlanks(ArgPointer + 1)) { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; ShowSevereError(state, @@ -3881,7 +3880,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. - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unenteredAdjacentZoneSurface; // check OutsideFaceEnvironment for legal zone Found = Util::FindItemInList( state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); @@ -3898,6 +3897,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) { @@ -4146,7 +4165,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 @@ -4240,13 +4259,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; @@ -4264,13 +4283,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; @@ -4282,13 +4301,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; } @@ -4428,7 +4447,7 @@ namespace SurfaceGeometry { // state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtEcoRoof = // state.dataConstruction->Construct(state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Construction).TypeIsEcoRoof; - } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { + } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { if (GettingIZSurfaces) { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = s_ipsc->cAlphaArgs(OtherSurfaceField); Found = Util::FindItemInList( @@ -4436,7 +4455,7 @@ namespace SurfaceGeometry { // see if match to zone, then it's an unentered other surface, else reconciled later if (Found > 0) { ++NeedToAddSurfaces; - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unenteredAdjacentZoneSurface; } } else { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; @@ -4937,7 +4956,7 @@ namespace SurfaceGeometry { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Zone = state.dataSurfaceGeometry->SurfaceTmp(Found).Zone; state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ZoneName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; state.dataSurfaceGeometry->SurfaceTmp(SurfNum).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, @@ -4981,7 +5000,7 @@ namespace SurfaceGeometry { } } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (!s_ipsc->lAlphaFieldBlanks(5)) { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = s_ipsc->cAlphaArgs(5); } else { @@ -5000,7 +5019,7 @@ namespace SurfaceGeometry { } } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface ++NeedToAddSurfaces; // ignoring window5datafiles for now -- will need to add. } @@ -5365,7 +5384,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, @@ -5380,7 +5399,7 @@ namespace SurfaceGeometry { "Interzone surfaces for transmission to result."); } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (!GettingIZSurfaces) { ShowSevereError(state, format("{}=\"{}\", invalid use of object", @@ -5398,12 +5417,12 @@ namespace SurfaceGeometry { } } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { // "Surface" Base Surface + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { // "Surface" Base Surface if (GettingIZSurfaces) { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = s_ipsc->cAlphaArgs(OtherSurfaceField); IZFound = Util::FindItemInList( state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); - if (IZFound > 0) state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface; + if (IZFound > 0) state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unenteredAdjacentZoneSurface; } else { // Interior Window state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; } @@ -5411,7 +5430,7 @@ namespace SurfaceGeometry { // This is the parent's property: if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == - UnenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface + unenteredAdjacentZoneSurface) { // OtherZone - unmatched interior surface if (GettingIZSurfaces) { ++NeedToAddSubSurfaces; } else { // Interior Window @@ -5430,13 +5449,13 @@ namespace SurfaceGeometry { if (s_ipsc->lAlphaFieldBlanks(OtherSurfaceField)) { // blank -- set it up for unentered adjacent zone if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == - UnenteredAdjacentZoneSurface) { // already set but need Zone + unenteredAdjacentZoneSurface) { // already set but need Zone state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ExtBoundCondName; // base surface has it - } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { + } else if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(Found).ZoneName; // base surface has it - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnenteredAdjacentZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unenteredAdjacentZoneSurface; } else { // not correct boundary condition for interzone subsurface ShowSevereError(state, format("{}=\"{}\", invalid Base Surface type for Interzone Surface", @@ -6230,7 +6249,7 @@ namespace SurfaceGeometry { s_ipsc->cAlphaArgs(2))); ErrorsFound = true; } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6242,7 +6261,7 @@ namespace SurfaceGeometry { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = DataSurfaces::ExternalEnvironment; // reset so program won't crash during "add surfaces" } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6461,7 +6480,7 @@ namespace SurfaceGeometry { ErrorsFound = true; continue; } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6473,7 +6492,7 @@ namespace SurfaceGeometry { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = DataSurfaces::ExternalEnvironment; // reset so program won't crash during "add surfaces" } - if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == UnreconciledZoneSurface) { + if (state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond == unreconciledZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -7035,7 +7054,7 @@ namespace SurfaceGeometry { state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurf = SurfNum; state.dataSurfaceGeometry->SurfaceTmp(SurfNum).BaseSurfName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCondName = state.dataSurfaceGeometry->SurfaceTmp(SurfNum).Name; - state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = UnreconciledZoneSurface; + state.dataSurfaceGeometry->SurfaceTmp(SurfNum).ExtBoundCond = unreconciledZoneSurface; } } } From db7d6b0c2f2b903d49eff31f134472d3a9a9fb35 Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Thu, 23 Jan 2025 15:36:36 -0600 Subject: [PATCH 03/11] Merge repairs --- src/EnergyPlus/SurfaceGeometry.cc | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 8ec212fad8b..99a3546b372 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -1248,10 +1248,10 @@ namespace SurfaceGeometry { newSurf.convOrientation = Convect::GetSurfConvOrientation(newSurf.Tilt); // Sine and cosine of azimuth and tilt - newSurf.SinAzim = std::sin(SurfWorldAz * Constant::DegToRadians); - newSurf.CosAzim = std::cos(SurfWorldAz * Constant::DegToRadians); - newSurf.SinTilt = std::sin(SurfTilt * Constant::DegToRadians); - newSurf.CosTilt = std::cos(SurfTilt * Constant::DegToRadians); + 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) newSurf.OutNormVec = newSurf.NewellSurfaceNormalVector; for (int n = 1; n <= 3; ++n) { @@ -3748,7 +3748,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 +3827,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 +3842,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; @@ -4391,14 +4391,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; @@ -4900,7 +4900,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 { @@ -4915,7 +4915,7 @@ namespace SurfaceGeometry { } } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { // "Zone" - unmatched interior surface ++NeedToAddSurfaces; // ignoring window5datafiles for now -- will need to add. } @@ -5282,7 +5282,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( @@ -5296,18 +5296,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 @@ -5325,11 +5325,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, @@ -6078,7 +6078,7 @@ namespace SurfaceGeometry { s_ipsc->cAlphaArgs(2))); ErrorsFound = true; } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6090,7 +6090,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, @@ -6275,7 +6275,7 @@ namespace SurfaceGeometry { ErrorsFound = true; continue; } - if (surfTemp.ExtBoundCond == UnenteredAdjacentZoneSurface) { + if (surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) { ShowSevereError(state, format("{}=\"{}\", invalid {}=\"{}", s_ipsc->cCurrentModuleObject, @@ -6286,7 +6286,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, @@ -6833,7 +6833,7 @@ namespace SurfaceGeometry { surfTemp.BaseSurf = SurfNum; surfTemp.BaseSurfName = surfTemp.Name; surfTemp.ExtBoundCondName = surfTemp.Name; - surfTemp.ExtBoundCond = UnreconciledZoneSurface; + surfTemp.ExtBoundCond = unreconciledZoneSurface; } } } From f3bf9be5bd161e85ae83c14461b7eff4ad9dcb4a Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Thu, 23 Jan 2025 17:19:40 -0600 Subject: [PATCH 04/11] Take 2 - fix for Zone outside boundary condition --- src/EnergyPlus/SurfaceGeometry.cc | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 99a3546b372..4994812fc4f 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -1208,16 +1208,7 @@ namespace SurfaceGeometry { auto &newZone = state.dataHeatBal->Zone(Found); newSurf.ZoneName = newZone.Name; assert(newZone.spaceIndexes.size() >= 1); - newSurf.spaceNum = newZone.spaceIndexes[0]; - if (newZone.spaceIndexes.size() > 1) { - ShowWarningError( - state, format("{}Outside Boundary Condition=Zone but Zone has more than one Space, Surface={}", RoutineName, curSurf.Name)); - ShowContinueError( - state, - format("Zone={}. Setting outside boundary to first Space={}. For more control, use Outside Boundary Condition=Space.", - newZone.Name, - state.dataHeatBal->space(newSurf.spaceNum).Name)); - } + newSurf.spaceNum = 0; // clear this here and set later } else if (curSurf.ExtBoundCond == unenteredAdjacentSpaceSurface) { int Found = Util::FindItemInList(curSurf.ExtBoundCondName, state.dataHeatBal->space, state.dataGlobal->numSpaces); if (Found == 0) continue; @@ -2721,7 +2712,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 +2730,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); From 2c87533e5e36621d7a77b82ab67a3277a35fb21d Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Fri, 31 Jan 2025 10:29:47 -0600 Subject: [PATCH 05/11] Unit tests for zone or space outside BC --- tst/EnergyPlus/unit/SurfaceGeometry.unit.cc | 946 ++++++++++++++++++++ 1 file changed, 946 insertions(+) diff --git a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc index f11cfcea2df..0e3fa179ab9 100644 --- a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc +++ b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc @@ -14591,3 +14591,949 @@ 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", + + "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}", + + }); + 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("")); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 2); + EXPECT_EQ("ZONE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("ZONE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("ZONE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("ZONE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + // 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 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"); +} +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", + + "Space,", + " Space1, !- Name", + " Zone1; !- Zone Name", + + "Space,", + " Space2, !- Name", + " Zone2; !- 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}", + + }); + 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("")); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 2); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + // 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 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"); +} +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", + + "Space,", + " Space1, !- Name", + " Zone1; !- Zone Name", + + "Space,", + " Space2, !- Name", + " Zone2; !- 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}", + + }); + 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("")); + + EXPECT_FALSE(ErrorsFound); // expect no errors + + EXPECT_EQ(state->dataViewFactor->NumOfRadiantEnclosures, 2); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).Name); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).Name); + EXPECT_EQ("SPACE1", state->dataViewFactor->EnclRadInfo(1).spaceNames[0]); + EXPECT_EQ("SPACE2", state->dataViewFactor->EnclRadInfo(2).spaceNames[0]); + EXPECT_EQ(state->dataHeatBal->space(1).radiantEnclosureNum, 1); + EXPECT_EQ(state->dataHeatBal->space(2).radiantEnclosureNum, 2); + EXPECT_EQ(state->dataHeatBal->space(1).surfaces.size(), 7); + EXPECT_EQ(state->dataHeatBal->space(2).surfaces.size(), 7); + + int originalIntWallNum = Util::FindItemInList("SPACE1-INTERIORWALL", state->dataSurface->Surface); + int originalIntDoorNum = Util::FindItemInList("SPACE1-INTERIORDOOR", state->dataSurface->Surface); + int izIntWallNum = Util::FindItemInList("iz-SPACE1-INTERIORWALL", state->dataSurface->Surface); + int izIntDoorNum = Util::FindItemInList("iz-SPACE1-INTERIORDOOR", state->dataSurface->Surface); + auto &originalIntWall = state->dataSurface->Surface(originalIntWallNum); + auto &originalIntDoor = state->dataSurface->Surface(originalIntDoorNum); + auto &izIntWall = state->dataSurface->Surface(izIntWallNum); + auto &izIntDoor = state->dataSurface->Surface(izIntDoorNum); + // 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 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"); +} From 7da6acdca240db3bf0e3198e10884550425274ff Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Fri, 31 Jan 2025 10:32:50 -0600 Subject: [PATCH 06/11] Fix for subsurfaces - found by new unit test --- src/EnergyPlus/SurfaceGeometry.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index e5ec596841e..e184a17a7e5 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -4910,7 +4910,7 @@ 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. } From c1ef53e485f42c9f200e9c21f04322e047321acf Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Fri, 31 Jan 2025 11:31:57 -0600 Subject: [PATCH 07/11] format --- src/EnergyPlus/SurfaceGeometry.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index e184a17a7e5..a07f3ad429f 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -4910,7 +4910,8 @@ namespace SurfaceGeometry { } } - if ((surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) || (surfTemp.ExtBoundCond == unenteredAdjacentSpaceSurface)) { // "Zone" - unmatched interior surface + if ((surfTemp.ExtBoundCond == unenteredAdjacentZoneSurface) || + (surfTemp.ExtBoundCond == unenteredAdjacentSpaceSurface)) { // "Zone" - unmatched interior surface ++NeedToAddSurfaces; // ignoring window5datafiles for now -- will need to add. } From eb2eef1ad7b7915aa8b5fcaaac2c093a8078036e Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Fri, 31 Jan 2025 12:49:50 -0600 Subject: [PATCH 08/11] Docs for space outside BC --- .../a-methodology-for-using-energyplus.tex | 3 ++- ...roup-thermal-zone-description-geometry.tex | 26 ++++++++++++------- idd/Energy+.idd.in | 8 +++--- 3 files changed, 23 insertions(+), 14 deletions(-) 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 79704e85be7..d3c91f1ad09 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -10216,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 @@ -11401,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 @@ -11591,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 @@ -11783,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 From 65dba650762a58a39f82a00eb58a4b2aaad7db59 Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Mon, 3 Feb 2025 14:29:21 -0600 Subject: [PATCH 09/11] revert shortcut name --- src/EnergyPlus/SurfaceGeometry.cc | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index a07f3ad429f..343d05a1d29 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -1193,24 +1193,24 @@ namespace SurfaceGeometry { // add the "need to add" surfaces // Debug write(outputfiledebug,*) ' need to add ',NeedtoAddSurfaces+NeedToAddSubSurfaces for (int SurfNum = 1; SurfNum <= FirstTotalSurfaces; ++SurfNum) { - auto &curSurf = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); - if ((curSurf.ExtBoundCond != unenteredAdjacentZoneSurface) && (curSurf.ExtBoundCond != unenteredAdjacentSpaceSurface)) continue; + auto &surfTemp = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); + if ((surfTemp.ExtBoundCond != unenteredAdjacentZoneSurface) && (surfTemp.ExtBoundCond != unenteredAdjacentSpaceSurface)) continue; // Need to add surface ++CurNewSurf; // Debug write(outputfiledebug,*) ' adding surface=',curnewsurf auto &newSurf = state.dataSurfaceGeometry->SurfaceTmp(CurNewSurf); - newSurf = curSurf; + newSurf = surfTemp; // Basic parameters are the same for both surfaces. - if (curSurf.ExtBoundCond == unenteredAdjacentZoneSurface) { - int Found = Util::FindItemInList(curSurf.ExtBoundCondName, state.dataHeatBal->Zone, state.dataGlobal->NumOfZones); + 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 (curSurf.ExtBoundCond == unenteredAdjacentSpaceSurface) { - int Found = Util::FindItemInList(curSurf.ExtBoundCondName, state.dataHeatBal->space, state.dataGlobal->numSpaces); + } 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; @@ -1218,12 +1218,12 @@ namespace SurfaceGeometry { newSurf.ZoneName = state.dataHeatBal->Zone(zoneNum).Name; } // Reverse Construction - newSurf.Construction = DataHeatBalance::AssignReverseConstructionNumber(state, curSurf.Construction, SurfError); + newSurf.Construction = DataHeatBalance::AssignReverseConstructionNumber(state, surfTemp.Construction, SurfError); newSurf.ConstructionStoredInputValue = newSurf.Construction; // Reverse Vertices - int NVert = curSurf.Sides; - for (int Vert = 1; Vert <= curSurf.Sides; ++Vert) { - newSurf.Vertex(Vert) = curSurf.Vertex(NVert); + int NVert = surfTemp.Sides; + for (int Vert = 1; Vert <= surfTemp.Sides; ++Vert) { + newSurf.Vertex(Vert) = surfTemp.Vertex(NVert); --NVert; } if (newSurf.Sides > 2) { @@ -1262,19 +1262,19 @@ namespace SurfaceGeometry { } // Change Name - newSurf.Name = "iz-" + curSurf.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) newSurf.ExtBoundCond = unreconciledZoneSurface; - curSurf.ExtBoundCond = unreconciledZoneSurface; - newSurf.ExtBoundCondName = curSurf.Name; - curSurf.ExtBoundCondName = newSurf.Name; + 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 (curSurf.Class == SurfaceClass::Roof) { + if (surfTemp.Class == SurfaceClass::Roof) { newSurf.Class = SurfaceClass::Floor; // Debug write(outputfiledebug,*) ' new surfaces is a floor' - } else if (curSurf.Class == SurfaceClass::Floor) { + } else if (surfTemp.Class == SurfaceClass::Floor) { newSurf.Class = SurfaceClass::Roof; // Debug write(outputfiledebug,*) ' new surfaces is a roof' } @@ -1284,9 +1284,9 @@ namespace SurfaceGeometry { } else { // subsurface int Found = - Util::FindItemInList("iz-" + curSurf.BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, FirstTotalSurfaces + CurNewSurf - 1); + Util::FindItemInList("iz-" + surfTemp.BaseSurfName, state.dataSurfaceGeometry->SurfaceTmp, FirstTotalSurfaces + CurNewSurf - 1); if (Found > 0) { - newSurf.BaseSurfName = "iz-" + curSurf.BaseSurfName; + newSurf.BaseSurfName = "iz-" + surfTemp.BaseSurfName; newSurf.BaseSurf = Found; auto &foundBaseSurf = state.dataSurfaceGeometry->SurfaceTmp(Found); foundBaseSurf.Area -= newSurf.Area; @@ -1296,7 +1296,7 @@ namespace SurfaceGeometry { foundBaseSurf.NetAreaShadowCalc -= newSurf.Area; } newSurf.ExtBoundCond = foundBaseSurf.ExtBoundCond; - newSurf.ExtBoundCondName = curSurf.Name; + newSurf.ExtBoundCondName = surfTemp.Name; newSurf.ExtSolar = foundBaseSurf.ExtSolar; newSurf.ExtWind = foundBaseSurf.ExtWind; newSurf.Zone = foundBaseSurf.Zone; @@ -1307,7 +1307,7 @@ namespace SurfaceGeometry { // Debug write(outputfiledebug,*) ' subsurf, basesurf=',TRIM('iz-'//SurfaceTmp(SurfNum)%BaseSurfName) } else { ShowSevereError(state, - format("{}Adding unentered subsurface, could not find base surface=iz-{}", RoutineName, curSurf.BaseSurfName)); + format("{}Adding unentered subsurface, could not find base surface=iz-{}", RoutineName, surfTemp.BaseSurfName)); SurfError = true; } } From dc095217d09e2a6053283968e01d5e9add5ec7d9 Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Mon, 3 Feb 2025 15:41:42 -0600 Subject: [PATCH 10/11] Add warning is other side zone has >1 spaces --- src/EnergyPlus/SurfaceGeometry.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 343d05a1d29..f40696941a5 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -2696,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 @@ -2756,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."); + } + } } } } From bd9595771fd362a9dc6325275abfc10202e8c488 Mon Sep 17 00:00:00 2001 From: "Michael J. Witte" Date: Mon, 3 Feb 2025 15:58:10 -0600 Subject: [PATCH 11/11] Extend unit tests --- tst/EnergyPlus/unit/SurfaceGeometry.unit.cc | 593 +++++++++++++++++++- 1 file changed, 584 insertions(+), 9 deletions(-) diff --git a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc index 0e3fa179ab9..61b4495842e 100644 --- a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc +++ b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc @@ -14629,6 +14629,9 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) "Zone,", " Zone2; !- Name", + "Zone,", + " Zone3; !- Name", + "BuildingSurface:Detailed,", " Space1-Ceiling, !- Name", " Roof, !- Surface Type", @@ -14831,6 +14834,142 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) " 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); @@ -14852,28 +14991,42 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) // 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("")); + 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, 2); + 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(1).surfaces.size(), 7); + 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); @@ -14887,6 +15040,19 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) 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); @@ -14900,6 +15066,20 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesNotInput) 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) { @@ -14939,6 +15119,9 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) "Zone,", " Zone2; !- Name", + "Zone,", + " Zone3; !- Name", + "Space,", " Space1, !- Name", " Zone1; !- Zone Name", @@ -14947,6 +15130,14 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) " 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", @@ -15149,6 +15340,143 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) " 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); @@ -15170,28 +15498,56 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) // 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("")); + + 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, 2); + 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(1).surfaces.size(), 7); + 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); @@ -15205,6 +15561,19 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) 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); @@ -15218,6 +15587,20 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_ZoneOutsideBC_SpacesInput) 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) { @@ -15257,6 +15640,9 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) "Zone,", " Zone2; !- Name", + "Zone,", + " Zone3; !- Name", + "Space,", " Space1, !- Name", " Zone1; !- Zone Name", @@ -15265,6 +15651,14 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) " 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", @@ -15467,6 +15861,143 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) " 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); @@ -15488,28 +16019,45 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) // 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("")); + 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, 2); + 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(1).surfaces.size(), 7); + 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); @@ -15523,6 +16071,19 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) 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); @@ -15536,4 +16097,18 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_SpaceOutsideBC_SpacesInput) 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"); }