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 fdf04a0d4e4..05ac62fc52d 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 @@ -4971,11 +4971,11 @@ \subsubsection{Inputs}\label{inputs-33-001} \paragraph{Field: Number of Horizontal Dividers}\label{field-number-of-horizontal-dividers} -The number of divider elements parallel to the top and bottom of the window. Default: 0. +The number of divider elements parallel to the top and bottom of the window. Default: 0. The total horizontal divider width (Divider Width times Number of Horizontal Dividers) must not exceed the glazed opening height of the window. \paragraph{Field: Number of Vertical Dividers}\label{field-number-of-vertical-dividers} -The number of divider elements parallel to the sides of the window. Default: 0. +The number of divider elements parallel to the sides of the window. Default: 0. The total vertical divider width (Divider Width times Number of Vertical Dividers) must not exceed the glazed opening width of the window. \paragraph{Field: Divider Outside Projection}\label{field-divider-outside-projection} diff --git a/src/EnergyPlus/SurfaceGeometry.cc b/src/EnergyPlus/SurfaceGeometry.cc index 17b73de79ee..8b1c3587693 100644 --- a/src/EnergyPlus/SurfaceGeometry.cc +++ b/src/EnergyPlus/SurfaceGeometry.cc @@ -13035,23 +13035,40 @@ namespace SurfaceGeometry { // If exterior window has divider, subtract divider area to get glazed area DivWidth = state.dataSurface->FrameDivider(surf.FrameDivider).DividerWidth; if (DivWidth > 0.0 && !ErrorInSurface) { - DivArea = DivWidth * (state.dataSurface->FrameDivider(FrDivNum).HorDividers * surf.Width + - state.dataSurface->FrameDivider(FrDivNum).VertDividers * surf.Height - - state.dataSurface->FrameDivider(FrDivNum).HorDividers * - state.dataSurface->FrameDivider(FrDivNum).VertDividers * DivWidth); - state.dataSurface->SurfWinDividerArea(ThisSurf) = DivArea * surf.Multiplier; - if (DivArea <= 0.0) { - ShowSevereError(state, std::format("{}Calculated Divider Area <= 0.0 for Window={}", RoutineName, surf.Name)); + if (DivWidth * state.dataSurface->FrameDivider(FrDivNum).HorDividers > surf.Height) { + ShowSevereError(state, + std::format("{}Horizontal dividers exceed glazed opening height for window {}", RoutineName, surf.Name)); + ShowContinueError( + state, + std::format("Number of horizontal dividers=[{}], divider width=[{:.2f}] m, glazed opening height=[{:.2f}] m.", + state.dataSurface->FrameDivider(FrDivNum).HorDividers, + DivWidth, + surf.Height)); ErrorInSurface = true; - } else if ((surf.Area - state.dataSurface->SurfWinDividerArea(ThisSurf)) <= 0.0) { - ShowSevereError(state, std::format("{}Divider area exceeds glazed opening for window {}", RoutineName, surf.Name)); - ShowContinueError(state, - std::format("Window surface area=[{:.2f}] m2, divider area=[{:.2f}] m2.", - surf.Area, - state.dataSurface->SurfWinDividerArea(ThisSurf))); + } + if (DivWidth * state.dataSurface->FrameDivider(FrDivNum).VertDividers > surf.Width) { + ShowSevereError(state, + std::format("{}Vertical dividers exceed glazed opening width for window {}", RoutineName, surf.Name)); + ShowContinueError( + state, + std::format("Number of vertical dividers=[{}], divider width=[{:.2f}] m, glazed opening width=[{:.2f}] m.", + state.dataSurface->FrameDivider(FrDivNum).VertDividers, + DivWidth, + surf.Width)); ErrorInSurface = true; - } else { - surf.Area -= state.dataSurface->SurfWinDividerArea(ThisSurf); // Glazed area + } + if (!ErrorInSurface) { + // total divider length + Real64 const DivLenTotal = state.dataSurface->FrameDivider(FrDivNum).HorDividers * surf.Width + + state.dataSurface->FrameDivider(FrDivNum).VertDividers * surf.Height; + // length of dividers overlapping themselves + Real64 const DivLenOvlp = state.dataSurface->FrameDivider(FrDivNum).HorDividers * + state.dataSurface->FrameDivider(FrDivNum).VertDividers * DivWidth; + // actual divider area minus self-overlap + DivArea = DivWidth * (DivLenTotal - DivLenOvlp); + state.dataSurface->SurfWinDividerArea(ThisSurf) = DivArea * surf.Multiplier; + // Glazed area + surf.Area -= state.dataSurface->SurfWinDividerArea(ThisSurf); } } diff --git a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc index 6c0831950a7..9be567173bf 100644 --- a/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc +++ b/tst/EnergyPlus/unit/SurfaceGeometry.unit.cc @@ -12753,6 +12753,50 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_BadDividerGeometry) " 0.8, !- Divider Visible Absorptance", " 0.9; !- Divider Thermal Hemispherical Emissivity", + " WindowProperty:FrameAndDivider,", + " BadDividerGeometry2, !- Name", + " 0.05, !- Frame Width {m}", + " 0.01, !- Frame Outside Projection {m}", + " 0.01, !- Frame Inside Projection {m}", + " 5.0, !- Frame Conductance {W/m2-K}", + " 1.2, !- Ratio of Frame-Edge Glass Conductance to Center-Of-Glass Conductance", + " 0.8, !- Frame Solar Absorptance", + " 0.8, !- Frame Visible Absorptance", + " 0.9, !- Frame Thermal Hemispherical Emissivity", + " DividedLite, !- Divider Type", + " 0.5, !- Divider Width {m}", + " 20, !- Number of Horizontal Dividers", + " 20, !- Number of Vertical Dividers", + " 0.00, !- Divider Outside Projection {m}", + " 0.00, !- Divider Inside Projection {m}", + " 5.0, !- Divider Conductance {W/m2-K}", + " 1.2, !- Ratio of Divider-Edge Glass Conductance to Center-Of-Glass Conductance", + " 0.8, !- Divider Solar Absorptance", + " 0.8, !- Divider Visible Absorptance", + " 0.9; !- Divider Thermal Hemispherical Emissivity", + + " WindowProperty:FrameAndDivider,", + " BadDividerGeometry3, !- Name", + " 0.05, !- Frame Width {m}", + " 0.01, !- Frame Outside Projection {m}", + " 0.01, !- Frame Inside Projection {m}", + " 5.0, !- Frame Conductance {W/m2-K}", + " 1.2, !- Ratio of Frame-Edge Glass Conductance to Center-Of-Glass Conductance", + " 0.8, !- Frame Solar Absorptance", + " 0.8, !- Frame Visible Absorptance", + " 0.9, !- Frame Thermal Hemispherical Emissivity", + " DividedLite, !- Divider Type", + " 0.5, !- Divider Width {m}", + " 50, !- Number of Horizontal Dividers", + " 50, !- Number of Vertical Dividers", + " 0.00, !- Divider Outside Projection {m}", + " 0.00, !- Divider Inside Projection {m}", + " 5.0, !- Divider Conductance {W/m2-K}", + " 1.2, !- Ratio of Divider-Edge Glass Conductance to Center-Of-Glass Conductance", + " 0.8, !- Divider Solar Absorptance", + " 0.8, !- Divider Visible Absorptance", + " 0.9; !- Divider Thermal Hemispherical Emissivity", + " FenestrationSurface:Detailed,", " FenestrationSurface, !- Name", " Window, !- Surface Type", @@ -12768,6 +12812,36 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_BadDividerGeometry) " 9.900000,0.0,0.1000000, !- X,Y,Z ==> Vertex 3 {m}", " 9.900000,0.0,9.900000; !- X,Y,Z ==> Vertex 4 {m}", + " FenestrationSurface:Detailed,", + " FenestrationSurface2, !- Name", + " Window, !- Surface Type", + " WindowConstruction, !- Construction Name", + " Wall2, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " 0.5000000, !- View Factor to Ground", + " BadDividerGeometry2, !- Frame and Divider Name", + " 1.0, !- Multiplier", + " 4, !- Number of Vertices", + " 0.200000,0.0,9.900000, !- X,Y,Z ==> Vertex 1 {m}", + " 0.200000,0.0,0.1000000, !- X,Y,Z ==> Vertex 2 {m}", + " 9.900000,0.0,0.1000000, !- X,Y,Z ==> Vertex 3 {m}", + " 9.900000,0.0,9.900000; !- X,Y,Z ==> Vertex 4 {m}", + + " FenestrationSurface:Detailed,", + " FenestrationSurface3, !- Name", + " Window, !- Surface Type", + " WindowConstruction, !- Construction Name", + " Wall3, !- Building Surface Name", + " , !- Outside Boundary Condition Object", + " 0.5000000, !- View Factor to Ground", + " BadDividerGeometry3, !- Frame and Divider Name", + " 1.0, !- Multiplier", + " 4, !- Number of Vertices", + " 0.200000,0.0,9.900000, !- X,Y,Z ==> Vertex 1 {m}", + " 0.200000,0.0,0.1000000, !- X,Y,Z ==> Vertex 2 {m}", + " 9.900000,0.0,0.1000000, !- X,Y,Z ==> Vertex 3 {m}", + " 9.900000,0.0,9.900000; !- X,Y,Z ==> Vertex 4 {m}", + " SurfaceProperty:LocalEnvironment,", " LocEnv:FenestrationSurface, !- Name", " FenestrationSurface, !- Exterior Surface Name", @@ -12832,6 +12906,40 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_BadDividerGeometry) " 10.00000,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m}", " 10.00000,0.0,10.00000; !- X,Y,Z ==> Vertex 4 {m}", + " BuildingSurface:Detailed,", + " Wall2, !- Name", + " Wall, !- Surface Type", + " WallConstruction, !- Construction Name", + " Zone, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " 0.5000000, !- View Factor to Ground", + " 4, !- Number of Vertices", + " 1.0,0.000000,10.00000, !- X,Y,Z ==> Vertex 1 {m}", + " 1.0,0.000000,0.0, !- X,Y,Z ==> Vertex 2 {m}", + " 11.00000,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m}", + " 11.00000,0.0,10.00000; !- X,Y,Z ==> Vertex 4 {m}", + + " BuildingSurface:Detailed,", + " Wall3, !- Name", + " Wall, !- Surface Type", + " WallConstruction, !- Construction Name", + " Zone, !- Zone Name", + " , !- Space Name", + " Outdoors, !- Outside Boundary Condition", + " , !- Outside Boundary Condition Object", + " SunExposed, !- Sun Exposure", + " WindExposed, !- Wind Exposure", + " 0.5000000, !- View Factor to Ground", + " 4, !- Number of Vertices", + " 2.0,0.000000,10.00000, !- X,Y,Z ==> Vertex 1 {m}", + " 2.0,0.000000,0.0, !- X,Y,Z ==> Vertex 2 {m}", + " 12.00000,0.0,0.0, !- X,Y,Z ==> Vertex 3 {m}", + " 12.00000,0.0,10.00000; !- X,Y,Z ==> Vertex 4 {m}", + " BuildingSurface:Detailed,", " Floor, !- Name", " Floor, !- Surface Type", @@ -12873,11 +12981,18 @@ TEST_F(EnergyPlusFixture, SurfaceGeometry_BadDividerGeometry) HeatBalanceManager::GetConstructData(*state, ErrorsFound); HeatBalanceManager::GetBuildingData(*state, ErrorsFound); - EXPECT_TRUE(compare_err_stream_substring(delimited_string({ - " ** Severe ** ProcessSurfaceVertices: Divider area exceeds glazed opening for window FENESTRATIONSURFACE", - " ** ~~~ ** Window surface area=[95.06] m2, divider area=[95.10] m2.", - - }))); + EXPECT_TRUE(ErrorsFound); + EXPECT_TRUE(compare_err_stream_substring( + delimited_string({" ** Severe ** ProcessSurfaceVertices: Horizontal dividers exceed glazed opening height for window FENESTRATIONSURFACE", + " ** ~~~ ** Number of horizontal dividers=[20], divider width=[0.50] m, glazed opening height=[9.80] m.", + " ** Severe ** ProcessSurfaceVertices: Horizontal dividers exceed glazed opening height for window FENESTRATIONSURFACE2", + " ** ~~~ ** Number of horizontal dividers=[20], divider width=[0.50] m, glazed opening height=[9.80] m.", + " ** Severe ** ProcessSurfaceVertices: Vertical dividers exceed glazed opening width for window FENESTRATIONSURFACE2", + " ** ~~~ ** Number of vertical dividers=[20], divider width=[0.50] m, glazed opening width=[9.70] m.", + " ** Severe ** ProcessSurfaceVertices: Horizontal dividers exceed glazed opening height for window FENESTRATIONSURFACE3", + " ** ~~~ ** Number of horizontal dividers=[50], divider width=[0.50] m, glazed opening height=[9.80] m.", + " ** Severe ** ProcessSurfaceVertices: Vertical dividers exceed glazed opening width for window FENESTRATIONSURFACE3", + " ** ~~~ ** Number of vertical dividers=[50], divider width=[0.50] m, glazed opening width=[9.70] m."}))); } TEST_F(EnergyPlusFixture, SurfaceGeometry_GetVerticesDropDuplicates)