-
Notifications
You must be signed in to change notification settings - Fork 460
Fix #10899 - Output:Table:Monthly: SumOrAverageDuringHoursShown doesn't follow previous variable
#10901
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
Conversation
| constexpr std::array<std::string_view, (int)AggType::Num> AggTypeNamesUC{ | ||
| "SUMORAVERAGE", | ||
| "MAXIMUM", | ||
| "MINIMUM", | ||
| "VALUEWHENMAXIMUMORMINIMUM", | ||
| "HOURSZERO", | ||
| "HOURSNONZERO", | ||
| "HOURSPOSITIVE", | ||
| "HOURSNONPOSITIVE", | ||
| "HOURSNEGATIVE", | ||
| "HOURSNONNEGATIVE", | ||
| "SUMORAVERAGEDURINGHOURSSHOWN", | ||
| "MAXIMUMDURINGHOURSSHOWN", | ||
| "MINIMUMDURINGHOURSSHOWN", | ||
| }; |
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.
Unrelated, but started by adding a getEnumValues call to replace a big if-else (1/2)
| // kind of aggregation identified (see AggType parameters) | ||
| AggType curAggType = static_cast<AggType>(getEnumValue(AggTypeNamesUC, Util::makeUPPER(curAggString))); | ||
| // set accumulator values to default as appropriate for aggregation type | ||
| if (Util::SameString(curAggString, "SumOrAverage")) { | ||
| curAggType = AggType::SumOrAvg; | ||
| } else if (Util::SameString(curAggString, "Maximum")) { | ||
| curAggType = AggType::Maximum; | ||
| } else if (Util::SameString(curAggString, "Minimum")) { | ||
| curAggType = AggType::Minimum; | ||
| } else if (Util::SameString(curAggString, "ValueWhenMaximumOrMinimum")) { | ||
| curAggType = AggType::ValueWhenMaxMin; | ||
| } else if (Util::SameString(curAggString, "HoursZero")) { | ||
| curAggType = AggType::HoursZero; | ||
| } else if (Util::SameString(curAggString, "HoursNonzero")) { | ||
| curAggType = AggType::HoursNonZero; | ||
| } else if (Util::SameString(curAggString, "HoursPositive")) { | ||
| curAggType = AggType::HoursPositive; | ||
| } else if (Util::SameString(curAggString, "HoursNonpositive")) { | ||
| curAggType = AggType::HoursNonPositive; | ||
| } else if (Util::SameString(curAggString, "HoursNegative")) { | ||
| curAggType = AggType::HoursNegative; | ||
| } else if (Util::SameString(curAggString, "HoursNonnegative")) { | ||
| curAggType = AggType::HoursNonNegative; | ||
| } else if (Util::SameString(curAggString, "SumOrAverageDuringHoursShown")) { | ||
| curAggType = AggType::SumOrAverageHoursShown; | ||
| } else if (Util::SameString(curAggString, "MaximumDuringHoursShown")) { | ||
| curAggType = AggType::MaximumDuringHoursShown; | ||
| } else if (Util::SameString(curAggString, "MinimumDuringHoursShown")) { | ||
| curAggType = AggType::MinimumDuringHoursShown; | ||
| } else { | ||
| curAggType = AggType::SumOrAvg; | ||
| if (curAggType == AggType::Invalid) { |
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.
Unrelated, but started by adding a getEnumValues call to replace a big if-else (2/2)
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.
Yes, very nice!
| format("{}: Blank column specified in '{}', need to provide a variable or meter name ", | ||
| CurrentModuleObject, | ||
| ort->MonthlyInput(TabNum).name)); | ||
| continue; |
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 because the previous chain was
for (int jField = 2; jField <= NumAlphas; jField += 2) {
if (AlphArray(jField).empty()) {
ShowWarningError(...);
}
AggType curAggType= ...;
if (!AlphArray(jField).empty()) {
AddMonthlyFieldSetInput(state, curTable, AlphArray(jField), "", curAggType);
}
}I just simplified it (if the field is blank and is going to be ignored, there's not really a good value addition of checking the AggType is valid anyways):
for (int jField = 2; jField <= NumAlphas; jField += 2) {
if (AlphArray(jField).empty()) {
ShowWarningError(...);
continue;
}
AggType curAggType= ...;
AddMonthlyFieldSetInput(state, curTable, AlphArray(jField), "", curAggType);
}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.
👍
| // If the hours variable is active then scan through the rest of the variables | ||
| // and accumulate | ||
| if (activeHoursShown) { | ||
| bool exit_loop = false; |
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.
sentinal variable to know when to break the for loop
| case AggType::HoursNegative: | ||
| case AggType::HoursNonNegative: | ||
| // end scanning since these might reset | ||
| exit_loop = true; |
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.
The issue was that an if else ladder inside a loop was incorrectly refactored to a switch case:
This was the original thing
for (int i = ....) {
SELECT_CASE_var = XXXX
if (SELECT_CASE_var == blabla) {
break; // THIS BREAKS THE FOR LOOP
} else ...
}The refactor:
for (int i = ....) {
switch (XXX) {
case blabla:
break; // THIS DO NOT BREAK THE FOR LOOP, it just prevents other `case`s to be processed (fallthrough)
}
...
}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.
Great find.
| std::string const idf_objects = delimited_string({ | ||
|
|
||
| "Output:Table:Monthly,", | ||
| " Test, !- Name", | ||
| " 3, !- Digits After Decimal", | ||
| " ConditionA, !- Variable or Meter 1 Name", | ||
| " HoursNonZero, !- Aggregation Type for Variable or Meter 1", | ||
| " VariableToBeSummedDuringHoursShown, !- Variable or Meter 2 Name", | ||
| " SumOrAverageDuringHoursShown, !- Aggregation Type for Variable or Meter 2", | ||
| " ConditionA_Inverse, !- Variable or Meter 3 Name", | ||
| " HoursNonZero, !- Aggregation Type for Variable or Meter 3", | ||
| " VariableToBeSummedDuringHoursShown, !- Variable or Meter 4 Name", | ||
| " SumOrAverageDuringHoursShown, !- Aggregation Type for Variable or Meter 4", | ||
| " VariableToBeSummedDuringHoursShown, !- Variable or Meter 5 Name", | ||
| " SumOrAverage; !- Aggregation Type for Variable or Meter 5", |
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.
test input data, mimics the defect file in #10899
| Real64 /* const */ VariableToBeSummedDuringHourShown = 0.0; | ||
| Real64 ConditionA = 0.0; | ||
| Real64 ConditionNotA = 0.0; | ||
|
|
||
| Real64 expectedTotalConditionA = 0.0; | ||
| Real64 expectedTotalConditionNotA = 0.0; | ||
|
|
||
| auto setConditionAB = [&ConditionA, &ConditionNotA, &expectedTotalConditionA, &expectedTotalConditionNotA](bool isConditionA) { | ||
| if (isConditionA) { | ||
| ConditionA = 1.0; | ||
| ConditionNotA = 0.0; | ||
| } else { | ||
| ConditionA = 0.0; | ||
| ConditionNotA = 1.0; | ||
| } | ||
| expectedTotalConditionA += ConditionA; | ||
| expectedTotalConditionNotA += ConditionNotA; | ||
| }; |
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.
I'm going to be checking:
- VariableToBeSummedDuringHourShown when Condition A
- VariableToBeSummedDuringHourShown when Condition is not(A)
- VariableToBeSummedDuringHourShown with no condition
| { | ||
| VariableToBeSummedDuringHourShown = 1.0; | ||
| setConditionAB(true); | ||
| GatherMonthlyResultsForTimestep(*state, OutputProcessor::TimeStepType::Zone); | ||
| compare_err_stream(""); | ||
| EXPECT_EQ(1.0, ort->MonthlyColumns(colConditionA).reslt(12)); | ||
| EXPECT_EQ(1.0, ort->MonthlyColumns(colValueWhenConditionA).reslt(12)); | ||
| EXPECT_EQ(0.0, ort->MonthlyColumns(colConditionNotA).reslt(12)); | ||
| EXPECT_EQ(0.0, ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)); | ||
| EXPECT_EQ(1.0, ort->MonthlyColumns(colValue).reslt(12)); |
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.
It already goes sideways before fix here.
You expect colValueWhenConditionNotA to be zero, yet it's 1.0 here.
Full test output before fix
[ RUN ] EnergyPlusFixture.OutputReportTabularMonthly_HandleMultipleDuringHoursShown
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13785: Failure
Expected equality of these values:
0.0
Which is: 0
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 1
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13795: Failure
Expected equality of these values:
0.0
Which is: 0
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 2
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13805: Failure
Expected equality of these values:
1.0
Which is: 1
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 3
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13815: Failure
Expected equality of these values:
2.0
Which is: 2
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 4
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13824: Failure
Expected equality of these values:
2.0
Which is: 2
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 5
[ FAILED ] EnergyPlusFixture.OutputReportTabularMonthly_HandleMultipleDuringHoursShown (2280 ms)
```
[ RUN ] EnergyPlusFixture.OutputReportTabularMonthly_HandleMultipleDuringHoursShown
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13785: Failure
Expected equality of these values:
0.0
Which is: 0
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 1
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13795: Failure
Expected equality of these values:
0.0
Which is: 0
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 2
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13805: Failure
Expected equality of these values:
1.0
Which is: 1
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 3
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13815: Failure
Expected equality of these values:
2.0
Which is: 2
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 4
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputReportTabular.unit.cc:13824: Failure
Expected equality of these values:
2.0
Which is: 2
ort->MonthlyColumns(colValueWhenConditionNotA).reslt(12)
Which is: 5
[ FAILED ] EnergyPlusFixture.OutputReportTabularMonthly_HandleMultipleDuringHoursShown (2280 ms)
```
The issue was that an if else ladder inside a loop was incorrectly refactored to a switch case:
This was the original thing
```c++
for (int i = ....) {
SELECT_CASE_var = XXXX
if (SELECT_CASE_var == blabla) {
break; // THIS BREAKS THE FOR LOOP
} else ...
}
```
The refactor:
```c++
for (int i = ....) {
switch (XXX) {
case blabla:
break; // THIS DO NOT BREAK THE FOR LOOP, it just prevents other `case`s to be processed (fallthrough)
}
...
}
```
255e7e939fc?w=1#diff-79e778e07bedf79acf027aa76c1235badd89a6f3014b6f0cdadc4ada74402ae3R3817-R3827
ed14832 to
78f9058
Compare
Myoldmopar
left a 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.
Great stuff here. Will test and try to get this merged asap.
| // kind of aggregation identified (see AggType parameters) | ||
| AggType curAggType = static_cast<AggType>(getEnumValue(AggTypeNamesUC, Util::makeUPPER(curAggString))); | ||
| // set accumulator values to default as appropriate for aggregation type | ||
| if (Util::SameString(curAggString, "SumOrAverage")) { | ||
| curAggType = AggType::SumOrAvg; | ||
| } else if (Util::SameString(curAggString, "Maximum")) { | ||
| curAggType = AggType::Maximum; | ||
| } else if (Util::SameString(curAggString, "Minimum")) { | ||
| curAggType = AggType::Minimum; | ||
| } else if (Util::SameString(curAggString, "ValueWhenMaximumOrMinimum")) { | ||
| curAggType = AggType::ValueWhenMaxMin; | ||
| } else if (Util::SameString(curAggString, "HoursZero")) { | ||
| curAggType = AggType::HoursZero; | ||
| } else if (Util::SameString(curAggString, "HoursNonzero")) { | ||
| curAggType = AggType::HoursNonZero; | ||
| } else if (Util::SameString(curAggString, "HoursPositive")) { | ||
| curAggType = AggType::HoursPositive; | ||
| } else if (Util::SameString(curAggString, "HoursNonpositive")) { | ||
| curAggType = AggType::HoursNonPositive; | ||
| } else if (Util::SameString(curAggString, "HoursNegative")) { | ||
| curAggType = AggType::HoursNegative; | ||
| } else if (Util::SameString(curAggString, "HoursNonnegative")) { | ||
| curAggType = AggType::HoursNonNegative; | ||
| } else if (Util::SameString(curAggString, "SumOrAverageDuringHoursShown")) { | ||
| curAggType = AggType::SumOrAverageHoursShown; | ||
| } else if (Util::SameString(curAggString, "MaximumDuringHoursShown")) { | ||
| curAggType = AggType::MaximumDuringHoursShown; | ||
| } else if (Util::SameString(curAggString, "MinimumDuringHoursShown")) { | ||
| curAggType = AggType::MinimumDuringHoursShown; | ||
| } else { | ||
| curAggType = AggType::SumOrAvg; | ||
| if (curAggType == AggType::Invalid) { |
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.
Yes, very nice!
| case AggType::HoursNegative: | ||
| case AggType::HoursNonNegative: | ||
| // end scanning since these might reset | ||
| exit_loop = true; |
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.
Great find.
| format("{}: Blank column specified in '{}', need to provide a variable or meter name ", | ||
| CurrentModuleObject, | ||
| ort->MonthlyInput(TabNum).name)); | ||
| continue; |
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 happy, merging. Thanks @jmarrec |

Pull request overview
Output:Table:Monthly:SumOrAverageDuringHoursShowndoesn't follow previous variable #10899Pull 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.