Skip to content

Commit 4ccd87a

Browse files
authored
Merge pull request #10309 from NREL/ZoneNoSurfs10305
Fix vector error for when a zone or space has no surfaces
2 parents 321d7d1 + 405d8ea commit 4ccd87a

File tree

4 files changed

+2478
-130
lines changed

4 files changed

+2478
-130
lines changed

src/EnergyPlus/HeatBalanceIntRadExchange.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ namespace HeatBalanceIntRadExchange {
448448
// the grey interchange between surfaces in an enclosure.
449449

450450
// SUBROUTINE LOCAL VARIABLE DECLARATIONS:
451+
static constexpr std::string_view RoutineName("InitInteriorRadExchange: ");
451452
bool NoUserInputF; // Logical flag signifying no input F's for zone
452453
bool ErrorsFound(false);
453454
Real64 CheckValue1;
@@ -499,7 +500,10 @@ namespace HeatBalanceIntRadExchange {
499500
thisEnclosure.NumOfSurfaces = numEnclosureSurfaces;
500501
state.dataHeatBalIntRadExchg->MaxNumOfRadEnclosureSurfs =
501502
max(state.dataHeatBalIntRadExchg->MaxNumOfRadEnclosureSurfs, numEnclosureSurfaces);
502-
if (numEnclosureSurfaces < 1) ShowFatalError(state, "No surfaces in an enclosure in InitInteriorRadExchange");
503+
if (numEnclosureSurfaces < 1) {
504+
ShowSevereError(state, format("{}No surfaces in enclosure={}.", RoutineName, thisEnclosure.Name));
505+
ErrorsFound = true;
506+
}
503507

504508
// Allocate the parts of the derived type
505509
thisEnclosure.F.dimension(numEnclosureSurfaces, numEnclosureSurfaces, 0.0);
@@ -767,7 +771,7 @@ namespace HeatBalanceIntRadExchange {
767771
}
768772

769773
if (ErrorsFound) {
770-
ShowFatalError(state, "InitInteriorRadExchange: Errors found during initialization of radiant exchange. Program terminated.");
774+
ShowFatalError(state, format("{}Errors found during initialization of radiant exchange. Program terminated.", RoutineName));
771775
}
772776
}
773777

@@ -778,6 +782,7 @@ namespace HeatBalanceIntRadExchange {
778782

779783
Array2D<Real64> SaveApproximateViewFactors; // Save for View Factor reporting
780784
std::string Option1; // view factor report option
785+
static constexpr std::string_view RoutineName("InitSolarViewFactors: ");
781786

782787
bool ErrorsFound = false;
783788
bool ViewFactorReport = false;
@@ -817,7 +822,10 @@ namespace HeatBalanceIntRadExchange {
817822
}
818823
}
819824
thisEnclosure.NumOfSurfaces = numEnclosureSurfaces;
820-
if (numEnclosureSurfaces < 1) ShowFatalError(state, "No surfaces in an enclosure in InitSolarViewFactors");
825+
if (numEnclosureSurfaces < 1) {
826+
ShowSevereError(state, format("{}No surfaces in enclosure={}.", RoutineName, thisEnclosure.Name));
827+
ErrorsFound = true;
828+
}
821829

822830
// Allocate the parts of the derived type
823831
thisEnclosure.F.dimension(numEnclosureSurfaces, numEnclosureSurfaces, 0.0);
@@ -1048,7 +1056,7 @@ namespace HeatBalanceIntRadExchange {
10481056
}
10491057

10501058
if (ErrorsFound) {
1051-
ShowFatalError(state, "InitSolarViewFactors: Errors found during initialization of diffuse solar distribution. Program terminated.");
1059+
ShowFatalError(state, format("{}Errors found during initialization of diffuse solar distribution. Program terminated.", RoutineName));
10521060
}
10531061
}
10541062

src/EnergyPlus/SurfaceGeometry.cc

Lines changed: 67 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -558,9 +558,10 @@ namespace SurfaceGeometry {
558558
for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
559559
auto &thisZone = state.dataHeatBal->Zone(ZoneNum);
560560
bool nonInternalMassSurfacesPresent = false;
561+
bool internalMassSurfacesPresent = false;
561562
Real64 TotSurfArea = 0.0;
562563
thisZone.Centroid = Vector(0.0, 0.0, 0.0);
563-
if (state.dataSurface->Surface(thisZone.AllSurfaceFirst).Sides > 0) {
564+
if ((thisZone.AllSurfaceFirst > 0) && (state.dataSurface->Surface(thisZone.AllSurfaceFirst).Sides > 0)) {
564565
thisZone.MinimumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
565566
thisZone.MaximumX = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).x;
566567
thisZone.MinimumY = state.dataSurface->Surface(thisZone.AllSurfaceFirst).Vertex(1).y;
@@ -573,8 +574,11 @@ namespace SurfaceGeometry {
573574

574575
for (int SurfNum = thisSpace.AllSurfaceFirst; SurfNum <= thisSpace.AllSurfaceLast; ++SurfNum) {
575576
auto &thisSurface = state.dataSurface->Surface(SurfNum);
576-
if (thisSurface.Class == SurfaceClass::IntMass) continue;
577-
nonInternalMassSurfacesPresent = true;
577+
if (thisSurface.Class == SurfaceClass::IntMass) {
578+
internalMassSurfacesPresent = true;
579+
continue;
580+
}
581+
if (!thisSurface.IsAirBoundarySurf) nonInternalMassSurfacesPresent = true;
578582
if (thisSurface.Class == SurfaceClass::Wall || (thisSurface.Class == SurfaceClass::Roof) ||
579583
(thisSurface.Class == SurfaceClass::Floor)) {
580584

@@ -596,7 +600,7 @@ namespace SurfaceGeometry {
596600
thisZone.Centroid.y /= TotSurfArea;
597601
thisZone.Centroid.z /= TotSurfArea;
598602
}
599-
if (!nonInternalMassSurfacesPresent) {
603+
if (internalMassSurfacesPresent && !nonInternalMassSurfacesPresent) {
600604
ShowSevereError(
601605
state, format("{}Zone=\"{}\" has only internal mass surfaces. Need at least one other surface.", RoutineName, thisZone.Name));
602606
ErrorsFound = true;
@@ -1739,7 +1743,7 @@ namespace SurfaceGeometry {
17391743

17401744
state.dataSurfaceGeometry->SurfaceTmp.deallocate(); // DeAllocate the Temp Surface derived type
17411745

1742-
createSpaceSurfaceLists(state, ErrorsFound);
1746+
createSpaceSurfaceLists(state);
17431747

17441748
// For each Base Surface Type (Wall, Floor, Roof)
17451749

@@ -2257,110 +2261,7 @@ namespace SurfaceGeometry {
22572261
}
22582262
}
22592263

2260-
//**********************************************************************************
2261-
// Set up Zone Surface Pointers
2262-
for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2263-
for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2264-
auto &thisSpace = state.dataHeatBal->space(spaceNum);
2265-
for (int SurfNum = 1; SurfNum <= MovedSurfs; ++SurfNum) { // TotSurfaces
2266-
if (state.dataSurface->Surface(SurfNum).spaceNum == spaceNum) {
2267-
if (thisSpace.AllSurfaceFirst == 0) {
2268-
thisSpace.AllSurfaceFirst = SurfNum;
2269-
}
2270-
if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) {
2271-
state.dataSurface->Surface(SurfNum).HeatTransSurf = false;
2272-
continue;
2273-
}
2274-
if (thisSpace.HTSurfaceFirst == 0) {
2275-
thisSpace.HTSurfaceFirst = SurfNum;
2276-
// Non window surfaces are grouped next within each zone
2277-
thisSpace.OpaqOrIntMassSurfaceFirst = SurfNum;
2278-
}
2279-
if ((thisSpace.WindowSurfaceFirst == 0) &&
2280-
((state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) ||
2281-
(state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
2282-
(state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Diffuser))) {
2283-
// Window surfaces are grouped last within each zone
2284-
thisSpace.WindowSurfaceFirst = SurfNum;
2285-
thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
2286-
}
2287-
if ((thisSpace.TDDDomeFirst == 0) && (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Dome)) {
2288-
// Window surfaces are grouped last within each zone
2289-
thisSpace.TDDDomeFirst = SurfNum;
2290-
if (thisSpace.WindowSurfaceFirst != 0) {
2291-
thisSpace.WindowSurfaceLast = SurfNum - 1;
2292-
} else {
2293-
// No window in the zone.
2294-
thisSpace.OpaqOrIntMassSurfaceLast = SurfNum - 1;
2295-
thisSpace.WindowSurfaceLast = -1;
2296-
}
2297-
break;
2298-
}
2299-
}
2300-
}
2301-
}
2302-
int firstSpaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
2303-
state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst = state.dataHeatBal->space(firstSpaceNum).AllSurfaceFirst;
2304-
}
2305-
// Surface First pointers are set, set last
2306-
if (state.dataGlobal->NumOfZones > 0) {
2307-
state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).AllSurfaceLast = state.dataSurface->TotSurfaces;
2308-
int lastSpaceNum = state.dataHeatBal->Zone(state.dataGlobal->NumOfZones)
2309-
.spaceIndexes(state.dataHeatBal->Zone(state.dataGlobal->NumOfZones).spaceIndexes.size());
2310-
state.dataHeatBal->space(lastSpaceNum).AllSurfaceLast = state.dataSurface->TotSurfaces;
2311-
}
2312-
for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2313-
if (ZoneNum < state.dataGlobal->NumOfZones) {
2314-
state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum + 1).AllSurfaceFirst - 1;
2315-
}
2316-
auto &thisSpaceList = state.dataHeatBal->Zone(ZoneNum).spaceIndexes;
2317-
int numSpacesInZone = thisSpaceList.size();
2318-
if (numSpacesInZone > 1) {
2319-
for (int spaceCount = 1; spaceCount <= numSpacesInZone - 1; ++spaceCount) {
2320-
auto &thisSpace = state.dataHeatBal->space(thisSpaceList(spaceCount));
2321-
auto &nextSpace = state.dataHeatBal->space(thisSpaceList(spaceCount + 1));
2322-
thisSpace.AllSurfaceLast = nextSpace.AllSurfaceFirst - 1;
2323-
}
2324-
state.dataHeatBal->space(thisSpaceList(numSpacesInZone)).AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
2325-
} else if (numSpacesInZone == 1) {
2326-
auto &thisSpace = state.dataHeatBal->space(thisSpaceList(numSpacesInZone));
2327-
thisSpace.AllSurfaceFirst = state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst;
2328-
thisSpace.AllSurfaceLast = state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast;
2329-
}
2330-
}
2331-
for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2332-
for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2333-
auto &thisSpace = state.dataHeatBal->space(spaceNum);
2334-
if (state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Dome) {
2335-
thisSpace.TDDDomeLast = thisSpace.AllSurfaceLast;
2336-
} else if ((state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::Window) ||
2337-
(state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
2338-
(state.dataSurface->Surface(thisSpace.AllSurfaceLast).Class == DataSurfaces::SurfaceClass::TDD_Diffuser)) {
2339-
thisSpace.TDDDomeLast = -1;
2340-
thisSpace.WindowSurfaceLast = thisSpace.AllSurfaceLast;
2341-
} else {
2342-
// If there are no windows in the zone, then set this to -1 so any for loops on WindowSurfaceFirst to WindowSurfaceLast
2343-
// will not execute. Same for TDDDome and its indices
2344-
thisSpace.TDDDomeLast = -1;
2345-
thisSpace.WindowSurfaceLast = -1;
2346-
thisSpace.OpaqOrIntMassSurfaceLast = thisSpace.AllSurfaceLast;
2347-
}
2348-
if (thisSpace.HTSurfaceFirst > 0) {
2349-
thisSpace.OpaqOrWinSurfaceFirst = thisSpace.HTSurfaceFirst;
2350-
thisSpace.OpaqOrWinSurfaceLast = std::max(thisSpace.OpaqOrIntMassSurfaceLast, thisSpace.WindowSurfaceLast);
2351-
thisSpace.HTSurfaceLast = thisSpace.AllSurfaceLast;
2352-
} else {
2353-
// If no heat transfer surfaces, make sure all others are set correctly
2354-
thisSpace.HTSurfaceLast = -1;
2355-
thisSpace.WindowSurfaceFirst = 0;
2356-
thisSpace.WindowSurfaceLast = -1;
2357-
thisSpace.OpaqOrWinSurfaceFirst = 0;
2358-
thisSpace.OpaqOrWinSurfaceLast = -1;
2359-
thisSpace.OpaqOrIntMassSurfaceFirst = 0;
2360-
thisSpace.OpaqOrIntMassSurfaceLast = -1;
2361-
}
2362-
}
2363-
}
2264+
setSurfaceFirstLast(state);
23642265

23652266
// Set up Floor Areas for Zones and Spaces
23662267
Real64 constexpr floorAreaTolerance(0.05);
@@ -3001,7 +2902,7 @@ namespace SurfaceGeometry {
30012902
}
30022903
}
30032904

3004-
void createSpaceSurfaceLists(EnergyPlusData &state, bool &ErrorsFound)
2905+
void createSpaceSurfaceLists(EnergyPlusData &state)
30052906
{
30062907
static constexpr std::string_view RoutineName("createSpaceSurfaceLists: ");
30072908
// Build Space surface lists now that all of the surface sorting is complete
@@ -3011,15 +2912,67 @@ namespace SurfaceGeometry {
30112912
// Add to Space's list of surfaces
30122913
state.dataHeatBal->space(thisSurf.spaceNum).surfaces.emplace_back(surfNum);
30132914
}
3014-
// TODO MJW: Is this necessary? Check that all Spaces have at least one Surface
3015-
for (int spaceNum = 1; spaceNum < state.dataGlobal->numSpaces; ++spaceNum) {
2915+
for (int spaceNum = 1; spaceNum <= state.dataGlobal->numSpaces; ++spaceNum) {
30162916
if (int(state.dataHeatBal->space(spaceNum).surfaces.size()) == 0) {
3017-
ShowSevereError(state, format("{}Space = {} has no surfaces.", RoutineName, state.dataHeatBal->space(spaceNum).Name));
3018-
ErrorsFound = true;
2917+
ShowWarningError(state, format("{}Space={} has no surfaces.", RoutineName, state.dataHeatBal->space(spaceNum).Name));
30192918
}
30202919
}
30212920
}
30222921

2922+
void setSurfaceFirstLast(EnergyPlusData &state)
2923+
{
2924+
// Set Zone and Space Surface First/Last Pointers
2925+
// Space surface lists have been built earlier in createSpaceSurfaceLists
2926+
for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
2927+
for (int spaceNum : state.dataHeatBal->Zone(ZoneNum).spaceIndexes) {
2928+
auto &thisSpace = state.dataHeatBal->space(spaceNum);
2929+
for (int SurfNum : thisSpace.surfaces) {
2930+
if (thisSpace.AllSurfaceFirst == 0) {
2931+
thisSpace.AllSurfaceFirst = SurfNum;
2932+
}
2933+
thisSpace.AllSurfaceLast = SurfNum;
2934+
2935+
if (state.dataSurface->Surface(SurfNum).IsAirBoundarySurf) {
2936+
state.dataSurface->Surface(SurfNum).HeatTransSurf = false;
2937+
continue;
2938+
}
2939+
// Non window surfaces are grouped next within each space
2940+
if (thisSpace.HTSurfaceFirst == 0) {
2941+
thisSpace.HTSurfaceFirst = SurfNum;
2942+
thisSpace.OpaqOrIntMassSurfaceFirst = SurfNum;
2943+
thisSpace.OpaqOrWinSurfaceFirst = SurfNum;
2944+
}
2945+
thisSpace.HTSurfaceLast = SurfNum;
2946+
2947+
// Window surfaces are grouped next within each space
2948+
if ((state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::Window) ||
2949+
(state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::GlassDoor) ||
2950+
(state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Diffuser)) {
2951+
if (thisSpace.WindowSurfaceFirst == 0) {
2952+
thisSpace.WindowSurfaceFirst = SurfNum;
2953+
}
2954+
thisSpace.WindowSurfaceLast = SurfNum;
2955+
} else if (state.dataSurface->Surface(SurfNum).Class != DataSurfaces::SurfaceClass::TDD_Dome) {
2956+
thisSpace.OpaqOrIntMassSurfaceLast = SurfNum;
2957+
}
2958+
2959+
// TDDDome surfaces are grouped last within each space
2960+
if (state.dataSurface->Surface(SurfNum).Class == DataSurfaces::SurfaceClass::TDD_Dome) {
2961+
if (thisSpace.TDDDomeFirst == 0) {
2962+
thisSpace.TDDDomeFirst = SurfNum;
2963+
}
2964+
thisSpace.TDDDomeLast = SurfNum;
2965+
} else {
2966+
thisSpace.OpaqOrWinSurfaceLast = SurfNum;
2967+
}
2968+
}
2969+
state.dataHeatBal->Zone(ZoneNum).AllSurfaceLast = thisSpace.AllSurfaceLast;
2970+
}
2971+
int firstSpaceNum = state.dataHeatBal->Zone(ZoneNum).spaceIndexes(1);
2972+
state.dataHeatBal->Zone(ZoneNum).AllSurfaceFirst = state.dataHeatBal->space(firstSpaceNum).AllSurfaceFirst;
2973+
}
2974+
}
2975+
30232976
void checkSubSurfAzTiltNorm(EnergyPlusData &state,
30242977
SurfaceData &baseSurface, // Base surface data (in)
30252978
SurfaceData &subSurface, // Subsurface data (in)

src/EnergyPlus/SurfaceGeometry.hh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ namespace SurfaceGeometry {
9090

9191
void CreateMissingSpaces(EnergyPlusData &state, Array1D<SurfaceGeometry::SurfaceData> &Surfaces);
9292

93-
void createSpaceSurfaceLists(EnergyPlusData &state, bool &ErrorsFound);
93+
void createSpaceSurfaceLists(EnergyPlusData &state);
94+
95+
void setSurfaceFirstLast(EnergyPlusData &state);
9496

9597
void checkSubSurfAzTiltNorm(EnergyPlusData &state,
9698
SurfaceData &baseSurface, // Base surface data (in)

0 commit comments

Comments
 (0)