From 575af850028f18d5ea9b4a298553f67c242947f8 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 29 Jul 2019 12:51:36 +0200 Subject: [PATCH 1/2] Write unit test for #6738 (WriteSourceEnergyEndUseSummary was untested until now) --- .../unit/OutputReportTabular.unit.cc | 182 ++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc index 850e3727a8f..ee4649fd5e7 100644 --- a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc +++ b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc @@ -7473,3 +7473,185 @@ TEST_F(EnergyPlusFixture, AzimuthToCardinal) i = i + 2; } } + + +TEST_F(SQLiteFixture, WriteSourceEnergyEndUseSummary_TestPerArea) { + + EnergyPlus::sqlite->sqliteBegin(); + EnergyPlus::sqlite->createSQLiteSimulationsRecord(1, "EnergyPlus Version", "Current Time"); + + OutputReportTabular::displaySourceEnergyEndUseSummary = true; + + + // DetermineBuildingFloorArea + + Latitude = 12.3; + Longitude = 45.6; + + TotSurfaces = 4; + Surface.allocate(TotSurfaces); + + // walls + Surface(1).Class = SurfaceClass_Wall; + Surface(1).HeatTransSurf = true; + Surface(1).ExtBoundCond = ExternalEnvironment; + Surface(1).Azimuth = 0.; + Surface(1).GrossArea = 200.; // 20 x 10 + Surface(1).Tilt = 90.; + Surface(1).Zone = 1; + + Surface(2).Class = SurfaceClass_Wall; + Surface(2).HeatTransSurf = true; + Surface(2).ExtBoundCond = ExternalEnvironment; + Surface(2).Azimuth = 90.; + Surface(2).GrossArea = 300.; // 30 x 10 + Surface(2).Tilt = 90.; + Surface(2).Zone = 2; + + // windows + Surface(3).Class = SurfaceClass_Window; + Surface(3).HeatTransSurf = true; + Surface(3).ExtBoundCond = ExternalEnvironment; + Surface(3).Azimuth = 0.; + Surface(3).GrossArea = 40.; + Surface(3).Height = 5; + Surface(3).Width = 8; + Surface(3).Tilt = 90.; + Surface(3).Zone = 1; + + Surface(4).Class = SurfaceClass_Window; + Surface(4).HeatTransSurf = true; + Surface(4).ExtBoundCond = ExternalEnvironment; + Surface(4).Azimuth = 90.; + Surface(4).GrossArea = 60.; + Surface(4).Height = 6; + Surface(4).Width = 10; + Surface(4).Tilt = 90.; + Surface(4).Zone = 2; + + // Loads + DataHeatBalance::TotLights = 3; + Lights.allocate(DataHeatBalance::TotLights); + + DataHeatBalance::TotPeople = 3; + People.allocate(DataHeatBalance::TotPeople); + + DataHeatBalance::TotElecEquip = 3; + ZoneElectric.allocate(DataHeatBalance::TotElecEquip); + + Lights(1).ZonePtr = 1; + Lights(1).DesignLevel = 1000.0; + Lights(2).ZonePtr = 2; + Lights(2).DesignLevel = 100.0; + Lights(3).ZonePtr = 3; + Lights(3).DesignLevel = 10.0; + + People(1).ZonePtr = 1; + People(1).NumberOfPeople = 10.0; + People(2).ZonePtr = 2; + People(2).NumberOfPeople = 5.0; + People(3).ZonePtr = 3; + People(3).NumberOfPeople = 1.0; + + ZoneElectric(1).ZonePtr = 1; + ZoneElectric(1).DesignLevel = 500.0; + ZoneElectric(2).ZonePtr = 2; + ZoneElectric(2).DesignLevel = 50.0; + ZoneElectric(3).ZonePtr = 3; + ZoneElectric(3).DesignLevel = 5.0; + + // zone + DataGlobals::NumOfZones = 3; + Zone.allocate(DataGlobals::NumOfZones); + Zone(1).Name = "PartofTot Conditioned Zone"; + Zone(1).SystemZoneNodeNumber = 1; // Conditioned + Zone(1).isPartOfTotalArea = true; + Zone(1).Multiplier = 1.; + Zone(1).ListMultiplier = 1.; + Zone(1).FloorArea = 1000.; + Zone(1).Volume = 2000.; + Zone(1).ExtGrossWallArea = 800.; + Zone(1).ExteriorTotalGroundSurfArea = 0; + Zone(1).ExtWindowArea = Surface(3).GrossArea + Surface(4).GrossArea; + + Zone(2).Name = "PartofTot Unconditioned Zone"; + Zone(2).SystemZoneNodeNumber = 0; // Unconditioned + Zone(2).isPartOfTotalArea = true; + Zone(2).Multiplier = 1.; + Zone(2).ListMultiplier = 1.; + Zone(2).FloorArea = 100.; + Zone(2).Volume = 200.; + Zone(2).ExtGrossWallArea = 80.; + Zone(2).ExteriorTotalGroundSurfArea = 0; + Zone(2).ExtWindowArea = 0.0; + + Zone(3).Name = "NOT PartofTot Conditioned Zone"; + Zone(3).SystemZoneNodeNumber = 1; // Conditioned + Zone(3).isPartOfTotalArea = false; + Zone(3).Multiplier = 1.; + Zone(3).ListMultiplier = 1.; + Zone(3).FloorArea = 10.; + Zone(3).Volume = 20.; + Zone(3).ExtGrossWallArea = 8.; + Zone(3).ExteriorTotalGroundSurfArea = 0; + Zone(3).ExtWindowArea = 0.0; + + // Gross takes all that are PartOfTot + Real64 expectedBuildingGrossFloorArea = Zone(1).FloorArea + Zone(2).FloorArea; + // Conditionned takes only PartOfTot AND COnditioned + Real64 expectedBuildingConditionedFloorArea = Zone(1).FloorArea; + + + // Assume that we only have electricity with a value of 3.6e6 * 1e4 J =10.000 kWh. + // And that this only comes for a single end use endUseHeating=1 + OutputReportTabular::gatherEndUseBySourceBEPS(1, DataGlobalConstants::endUseHeating) = 3.6e10; + OutputReportTabular::gatherTotalsBySourceBEPS(1) = 3.6e10; + Real64 eleckWh = 1e4; + + OutputReportTabular::unitsStyle = OutputReportTabular::unitsStyleJtoKWH; + + // Now we're ready to call the actual function of interest + OutputReportTabular::WriteSourceEnergyEndUseSummary(); + + + // Before we test the reporting itself, we check that DetermineBuildingFloorArea (called from WriteSourceEnergyEndUseSummary) + // actually did what we expected + EXPECT_EQ(expectedBuildingGrossFloorArea, OutputReportTabular::buildingGrossFloorArea); + EXPECT_EQ(expectedBuildingConditionedFloorArea, OutputReportTabular::buildingConditionedFloorArea); + + // Now we test the reporting itself: + // We consistently test in the same report (three different tables) and at the same column for fuel = Elec + const std::string reportName = "SourceEnergyEndUseComponentsSummary"; + const std::string columnName = "Source Electricity"; + + // We test for Heating and Total, since they should be the same + std::vector testRowNames = {"Heating", "Total Source Energy End Use Components"}; + + // TableName, value + std::vector> results({ + {"Source Energy End Use Components Summary", eleckWh}, + {"Source Energy End Use Component Per Conditioned Floor Area", 10000.0 / expectedBuildingConditionedFloorArea}, + {"Source Energy End Use Components Per Total Floor Area", 10000.0 / expectedBuildingGrossFloorArea}, + }); + + for (auto& v: results) { + + std::string tableName = std::get<0>(v); + Real64 expectedValue = std::get<1>(v); + + for (auto& rowName : testRowNames) { + std::string query("SELECT Value From TabularDataWithStrings" + " WHERE ReportName = '" + reportName + "'" + " AND TableName = '" + tableName + "'" + " AND RowName = '" + rowName + "'" + + " AND ColumnName = '" + columnName + "'"); + + Real64 return_val = execAndReturnFirstDouble(query); + + // Add informative message if failed + EXPECT_NEAR(expectedValue, return_val, 0.01) << "Failed for TableName=" << tableName << "; RowName=" << rowName; + } + } + + EnergyPlus::sqlite->sqliteCommit(); +} From 7af731efad4b8fd8f7e4297b02d91ca54088ab84 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 29 Jul 2019 12:52:19 +0200 Subject: [PATCH 2/2] Fix #6738 (and limit scope of variables to avoid future problems) --- src/EnergyPlus/OutputReportTabular.cc | 125 ++++++++++++++------------ 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 8b0b685f49f..634b50ccc6e 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -9160,7 +9160,6 @@ namespace OutputReportTabular { int jEndUse; Real64 largeConversionFactor; Real64 areaConversionFactor; - Real64 convBldgCondFloorArea; if (displaySourceEnergyEndUseSummary) { // show the headers of the report @@ -9216,9 +9215,6 @@ namespace OutputReportTabular { } } - // convert floor areas - convBldgCondFloorArea = buildingConditionedFloorArea / areaConversionFactor; - // convert units into MJ (divide by 1,000,000) if J otherwise kWh for (iResource = 1; iResource <= 5; ++iResource) { // don't do water for (jEndUse = 1; jEndUse <= NumEndUses; ++jEndUse) { @@ -9324,7 +9320,8 @@ namespace OutputReportTabular { "Source Energy End Use Components Summary"); } - //---- Normalized by Conditioned Area Sub-Table + + // Normalized by Area tables { auto const SELECT_CASE_var(unitsStyle); @@ -9349,69 +9346,79 @@ namespace OutputReportTabular { } } - tableBody = ""; - if (convBldgCondFloorArea > 0) { - for (iResource = 1; iResource <= 5; ++iResource) { - for (jEndUse = 1; jEndUse <= 14; ++jEndUse) { - tableBody(iResource, jEndUse) = RealToStr(useVal(iResource, jEndUse) / convBldgCondFloorArea, 2); + //---- Normalized by Conditioned Area Sub-Table + { + tableBody = ""; + // convert floor area + Real64 convBldgCondFloorArea = buildingConditionedFloorArea / areaConversionFactor; + if (convBldgCondFloorArea > 0) { + for (iResource = 1; iResource <= 5; ++iResource) { + for (jEndUse = 1; jEndUse <= 14; ++jEndUse) { + tableBody(iResource, jEndUse) = RealToStr(useVal(iResource, jEndUse) / convBldgCondFloorArea, 2); + } + tableBody(iResource, 16) = RealToStr(useVal(iResource, 15) / convBldgCondFloorArea, 2); } - tableBody(iResource, 16) = RealToStr(useVal(iResource, 15) / convBldgCondFloorArea, 2); } - } - WriteTextLine("Normalized Metrics", true); + WriteTextLine("Normalized Metrics", true); - // heading for the entire sub-table - WriteSubtitle("Source Energy End Use Components Per Conditioned Floor Area"); - WriteTable(tableBody, rowHead, columnHead, columnWidth); - if (sqlite) { - sqlite->createSQLiteTabularDataRecords(tableBody, - rowHead, - columnHead, - "SourceEnergyEndUseComponentsSummary", - "Entire Facility", - "Source Energy End Use Component Per Conditioned Floor Area"); - } - if (ResultsFramework::OutputSchema->timeSeriesAndTabularEnabled()) { - ResultsFramework::OutputSchema->TabularReportsCollection.addReportTable(tableBody, - rowHead, - columnHead, - "Source Energy End Use Components Summary", - "Entire Facility", - "Source Energy End Use Component Per Conditioned Floor Area"); - } + // heading for the entire sub-table + WriteSubtitle("Source Energy End Use Components Per Conditioned Floor Area"); + WriteTable(tableBody, rowHead, columnHead, columnWidth); + if (sqlite) { + sqlite->createSQLiteTabularDataRecords(tableBody, + rowHead, + columnHead, + "SourceEnergyEndUseComponentsSummary", + "Entire Facility", + "Source Energy End Use Component Per Conditioned Floor Area"); + } + if (ResultsFramework::OutputSchema->timeSeriesAndTabularEnabled()) { + ResultsFramework::OutputSchema->TabularReportsCollection.addReportTable(tableBody, + rowHead, + columnHead, + "Source Energy End Use Components Summary", + "Entire Facility", + "Source Energy End Use Component Per Conditioned Floor Area"); + } + } // End of Normalized by Conditioned Area //---- Normalized by Total Area Sub-Table - tableBody = ""; - if (convBldgCondFloorArea > 0) { - for (iResource = 1; iResource <= 5; ++iResource) { - for (jEndUse = 1; jEndUse <= 14; ++jEndUse) { - tableBody(iResource, jEndUse) = RealToStr(useVal(iResource, jEndUse) / convBldgCondFloorArea, 2); + { + tableBody = ""; + Real64 convBldgGrossFloorArea = buildingGrossFloorArea / areaConversionFactor; + + if (convBldgGrossFloorArea > 0) { + for (iResource = 1; iResource <= 5; ++iResource) { + for (jEndUse = 1; jEndUse <= 14; ++jEndUse) { + tableBody(iResource, jEndUse) = RealToStr(useVal(iResource, jEndUse) / convBldgGrossFloorArea, 2); + } + tableBody(iResource, 16) = RealToStr(useVal(iResource, 15) / convBldgGrossFloorArea, 2); } - tableBody(iResource, 16) = RealToStr(useVal(iResource, 15) / convBldgCondFloorArea, 2); } - } - // heading for the entire sub-table - WriteSubtitle("Source Energy End Use Components Per Total Floor Area"); - WriteTable(tableBody, rowHead, columnHead, columnWidth); - if (sqlite) { - sqlite->createSQLiteTabularDataRecords(tableBody, - rowHead, - columnHead, - "SourceEnergyEndUseComponentsSummary", - "Entire Facility", - "Source Energy End Use Components Per Total Floor Area"); - } - if (ResultsFramework::OutputSchema->timeSeriesAndTabularEnabled()) { - ResultsFramework::OutputSchema->TabularReportsCollection.addReportTable(tableBody, - rowHead, - columnHead, - "Source Energy End Use Components Summary", - "Entire Facility", - "Source Energy End Use Components Per Total Floor Area"); - } - } + // heading for the entire sub-table + WriteSubtitle("Source Energy End Use Components Per Total Floor Area"); + WriteTable(tableBody, rowHead, columnHead, columnWidth); + if (sqlite) { + sqlite->createSQLiteTabularDataRecords(tableBody, + rowHead, + columnHead, + "SourceEnergyEndUseComponentsSummary", + "Entire Facility", + "Source Energy End Use Components Per Total Floor Area"); + } + if (ResultsFramework::OutputSchema->timeSeriesAndTabularEnabled()) { + ResultsFramework::OutputSchema->TabularReportsCollection.addReportTable(tableBody, + rowHead, + columnHead, + "Source Energy End Use Components Summary", + "Entire Facility", + "Source Energy End Use Components Per Total Floor Area"); + } + } // End of Normalized by Total Area + + } // end if displaySourceEnergyEndUseSummary } void WriteDemandEndUseSummary()