Skip to content
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 #6738 - Source Energy End Use Components Per Conditioned Floor Area and Per Total Floor Area the same #7428

Merged
merged 3 commits into from
Aug 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 66 additions & 59 deletions src/EnergyPlus/OutputReportTabular.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9153,7 +9153,6 @@ namespace OutputReportTabular {
int jEndUse;
Real64 largeConversionFactor;
Real64 areaConversionFactor;
Real64 convBldgCondFloorArea;

if (displaySourceEnergyEndUseSummary) {
// show the headers of the report
Expand Down Expand Up @@ -9209,9 +9208,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) {
Expand Down Expand Up @@ -9317,7 +9313,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);
Expand All @@ -9342,69 +9339,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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, here's the difference. Using buildingGrossFloorArea instead of buildingConditionedFloorArea. 👍


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()
Expand Down
182 changes: 182 additions & 0 deletions tst/EnergyPlus/unit/OutputReportTabular.unit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7471,3 +7471,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<std::string> testRowNames = {"Heating", "Total Source Energy End Use Components"};

// TableName, value
std::vector<std::tuple<std::string, Real64>> 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.


// Add informative message if failed
EXPECT_NEAR(expectedValue, return_val, 0.01) << "Failed for TableName=" << tableName << "; RowName=" << rowName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very helpful

}
}

EnergyPlus::sqlite->sqliteCommit();
}