-
Notifications
You must be signed in to change notification settings - Fork 394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix array bounds error for interzone windows and fix convexity of mirrored surfaces #10498
Conversation
…indowsAndSurfs20PlusVertices
Added some unit tests for surfaces with >=20 vertices. Here's a plot of the vertices for the defect file surface that fails the original Here's the surface object shown above
|
Noticed this comment in EnergyPlus/src/EnergyPlus/SurfaceGeometry.cc Lines 9758 to 9761 in 4d39dff
But vertices haven't been So let's try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code walkthrough.
Real64 constexpr OneThousandth = 1.0e-3; // Used as a tolerance in various places | ||
Real64 constexpr OneMillionth = 1.0e-6; // Used as a tolerance in various places | ||
|
||
Real64 constexpr DistTooSmall(1.e-4); // Geometric tolerance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some new constants that are used as tolerances in various places in surface geometry and shadowing calculations. DistToolSmall
was moved up from a local declaration in Vectors.cc - decided to keep the same name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does DistTooSmall represent a unit or is it dimensionless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does DistTooSmall represent a unit or is it dimensionless?
Good questions. After some digging, it's in meters. And after some discussion with @JasonGlazer about other geometric tolerances, I'm going to make some other changes. How do you feel about names like this?
Real64 constexpr 1centimeter = 0.01 // Distance tolerance [m]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I mean that exact name won't compile since it starts with a numeric literal :) But I think oneCentimeter
is fine. Or you could just call it oneHundredth and allow it to be used for multiple units. As long as it's pretty obvious I'm not too picky.
@@ -88,15 +87,6 @@ using namespace WindowManager; | |||
|
|||
Array1D_string const cExtBoundCondition({-6, 0}, {"KivaFoundation", "FCGround", "OSCM", "OSC", "OSC", "Ground", "ExternalEnvironment"}); | |||
|
|||
// Parameters to indicate surface classes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed some comments that were left behind at some point when the parameters were moved to an enum
.
assert((shapeCat == ShapeCat::Nonconvex) || (crossEdges.size() == 2)); | ||
assert((shapeCat == ShapeCat::Nonconvex) || (crossEdges.size() == 2u)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the assert that was failing. Initially, I thought it was incorrect and should be >=2
, but in the end the failing surface was ShapeCat:Convex
here when it should have been Nonconvex
.
auto &origSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); | ||
auto &newSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1); | ||
newSurface = origSurface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In MakeMirrorSurface
just copy the entire original surface into the new surface instead of trying to copy each pertinent field individually. Then go about modifying name, vertices and other things. See #10498 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a more reliable option. 👍
@@ -110,16 +106,6 @@ Vector const XUnit(1.0, 0.0, 0.0); | |||
Vector const YUnit(0.0, 1.0, 0.0); | |||
Vector const ZUnit(0.0, 0.0, 1.0); | |||
|
|||
// DERIVED TYPE DEFINITIONS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some housekeeping throughout Vectors.cc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay!
@@ -244,6 +244,154 @@ TEST_F(EnergyPlusFixture, SurfaceTest_Surface2D) | |||
} | |||
} | |||
|
|||
TEST_F(EnergyPlusFixture, SurfaceTest_Surface2D_bigVertices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2 new unit tests added related to the failed assert in Surface2D
. The first is a convex surface, the second is nonconvex. In hindsight, this isn't focusing on the root problems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you feel more tests are justified? Or is this still covering the issue enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on what I'm seeing here, I'm good with this. I like the increased uniformity with named tolerances, and so much cleanup :). I'm curious about the DistTooSmall units and if you think you need more unit tests, but otherwise it seems good to go.
Real64 constexpr OneThousandth = 1.0e-3; // Used as a tolerance in various places | ||
Real64 constexpr OneMillionth = 1.0e-6; // Used as a tolerance in various places | ||
|
||
Real64 constexpr DistTooSmall(1.e-4); // Geometric tolerance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does DistTooSmall represent a unit or is it dimensionless?
@@ -311,7 +311,7 @@ namespace SolarReflectionManager { | |||
ObsVec = state.dataSurface->Surface(ObsSurfNum).Vertex(loop); | |||
DotProd = dot(state.dataSolarReflectionManager->SolReflRecSurf(RecSurfNum).NormVec, ObsVec - RecVec); | |||
// CR8251 IF(DotProd > 0.01d0) THEN ! This obstructing-surface vertex is not behind receiving surface | |||
if (DotProd > 1.0e-6) { // This obstructing-surface vertex is not behind receiving surface | |||
if (DotProd > Constant::OneMillionth) { // This obstructing-surface vertex is not behind receiving surface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, that's actually really satisfying to read like this.
auto &origSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum); | ||
auto &newSurface = state.dataSurfaceGeometry->SurfaceTmp(SurfNum + 1); | ||
newSurface = origSurface; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like a more reliable option. 👍
@@ -110,16 +106,6 @@ Vector const XUnit(1.0, 0.0, 0.0); | |||
Vector const YUnit(0.0, 1.0, 0.0); | |||
Vector const ZUnit(0.0, 0.0, 1.0); | |||
|
|||
// DERIVED TYPE DEFINITIONS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay!
@@ -244,6 +244,154 @@ TEST_F(EnergyPlusFixture, SurfaceTest_Surface2D) | |||
} | |||
} | |||
|
|||
TEST_F(EnergyPlusFixture, SurfaceTest_Surface2D_bigVertices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you feel more tests are justified? Or is this still covering the issue enough?
@mjwitte I'm marking this waiting on developer per your comment about "more changes". Ping me back if it's ready for me to review again! |
…indowsAndSurfs20PlusVertices
…indowsAndSurfs20PlusVertices
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Follow up code walkthru. Some additional changes to note. CI is looking green so far. This is complete pending final review.
@@ -1983,7 +1983,7 @@ \subsection{Surface Vertices}\label{surface-vertices} | |||
use the same vertex input. The numeric parameters indicated below are taken from the \hyperref[buildingsurfacedetailed]{BuildingSurface:Detailed} definition; the others may not be exactly the same but are identical in configuration. They are also ``extensible'' -- so, to define more vertices for these surfaces, simply add the required number of vertices (X, Y, and Z coordinates for each vertex) to the input file. Note that \hyperref[fenestrationsurfacedetailed]{FenestrationSurface:Detailed} is not extensible and is limited to 4 (max) vertices. If the Number of Surface Vertex groups is left blank or entered as \textbf{autocalculate}, EnergyPlus looks at the number of groups entered and figures out how many coordinate groups are entered. | |||
|
|||
\begin{callout} | |||
\warning{Note that the resolution on the surface vertex input is 1 millimeter (.001 meter). Therefore, using vertices that are very close together (\textless{} 1 mm) may result in invalid dot product and fatal errors during shading calculations.} | |||
\warning{Note that the resolution for surface vertex input is 1 centimeter (0.01 meter). Vertices that are \textless{} 1 cm apart will be combined.} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discovered that the I/O Ref was incorrect.
Real64 constexpr OneCentimeter = 0.01; // Geometric tolerance in meters | ||
Real64 constexpr TwoCentimeters = 0.02; // Geometric tolerance in meters | ||
Real64 constexpr SmallDistance = 1.0e-4; // Geometric tolerance in meters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More new (and revised) constants
for (int MZ = 1; MZ <= NumberOfEnclosures; ++MZ, ++l) { | ||
assert(state.dataHeatBalSurf->ZoneFractDifShortZtoZ.isize1() == numEnclosures); | ||
assert(state.dataHeatBalSurf->ZoneFractDifShortZtoZ.isize2() == numEnclosures); | ||
for (int NZ = 1; NZ <= numEnclosures; ++NZ) { | ||
for (int MZ = 1; MZ <= numEnclosures; ++MZ) { | ||
if (MZ == NZ) continue; | ||
if (state.dataHeatBalSurf->ZoneFractDifShortZtoZ[l] > 0.0) { // [ l ] == ( MZ, NZ ) | ||
if (state.dataHeatBalSurf->ZoneFractDifShortZtoZ(MZ, NZ) > 0.0) { | ||
state.dataHeatBalSurf->EnclSolRecDifShortFromZ(NZ) = true; | ||
break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I extended the unit test for the interzone window function, I found that this loop was broken. The l
counter was added as an efficiency measure long ago, but l
doesn't get incremented when the inner loop break
s out. Reverted (way-way-back) to using the dual subscripts instead of l
.
void ComputeDifSolExcZonesWIZWindows(EnergyPlusData &state, int const NumberOfEnclosures) // Number of solar enclosures | ||
void ComputeDifSolExcZonesWIZWindows(EnergyPlusData &state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dumped the second parameter, because that's already known in state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it ❤️
if (std::abs(maxZ - wallHeightZ) > 0.0254) { // 2.54 cm = 1 inch | ||
if (std::abs(maxZ - wallHeightZ) > Constant::TwoCentimeters) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a 1:1 replacement, but it shouldn't cause any problems.
@@ -13080,7 +13010,6 @@ namespace SurfaceGeometry { | |||
{ | |||
// J. Glazer - March 2017 | |||
|
|||
Real64 tol = 0.0127; // 1.27 cm = 1/2 inch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per discussion with @JasonGlazer this group of functions are using OneCentimeter
instead of 1.27cm
state->dataViewFactor->NumOfSolarEnclosures = 2; | ||
state->dataViewFactor->NumOfSolarEnclosures = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extended this unit test to cover the real defect here (interior window with numEnclosres>numZones).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
b.x = 7.01; | ||
b.y = 11.01; | ||
b.z = 17.01; | ||
b.x = 7.0095; | ||
b.y = 11.0095; | ||
b.z = 17.0095; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted this unit test due to the tighter tolerance in these functions (1cm instead of 1.27cm).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
void ComputeDifSolExcZonesWIZWindows(EnergyPlusData &state, int const NumberOfEnclosures) // Number of solar enclosures | ||
void ComputeDifSolExcZonesWIZWindows(EnergyPlusData &state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it ❤️
@@ -5746,7 +5746,7 @@ void SHADOW(EnergyPlusData &state, | |||
state.dataSurface->Surface(NGRS).lcsz.y * state.dataSolarShading->SUNCOS(2) + | |||
state.dataSurface->Surface(NGRS).lcsz.z * state.dataSolarShading->SUNCOS(3); | |||
|
|||
if (std::abs(ZS) > 1.e-4) { | |||
if (std::abs(ZS) > Constant::SmallDistance) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:)
state->dataViewFactor->NumOfSolarEnclosures = 2; | ||
state->dataViewFactor->NumOfSolarEnclosures = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
All green here, and all happy with develop pulled in. Thanks @mjwitte, this is a great set of changes. |
Pull request overview
MakeMirrorSurface
to properly setIsConvex
for the mirrored surface. When a mirrored surface is created, the original surface has already setIsConvex
for itself. The formerMakeMirrorSurface
copied a list of specific attributes to the new surface, but did not copyIsConvex
so it was always true. This resulted in a non-convex surface being classified as convex which then failed debug assert inSurface2D
for mirrored nonconvex shading surfaces with 20 or more vertices (that's a mouthful). The defect file tripped on thisassert
in a debug build, masking the arrays bounds issue.MakeMirrorSurface
.1.0e-6
and the like.ComputeDifSolExcZonesWIZWindows
(uncertain impact on models with interior windows).Defects Fixed
Revised defect file (which runs faster): 10490.idf.txt
The defect file crashed with a release build and failed an assert with a debug build revealing two separate issues.
The defect file now runs to completion with both release and debug builds.
Diffs
There are no diffs. There was an expectation that diffs might show up from fixing the mirrored surface convexity. This fix only impacts the mirrored side of a non-convex shading surface which will only impact the results if the mirrored side casts shadows toward the building and if the non-convex shape is such that the Polygon Clipping Algorithm does not handle it correctly.
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.