Skip to content

OutputReportTabularAnnual Refactor#11421

Open
mitchute wants to merge 10 commits intodevelopfrom
output-table-refactor
Open

OutputReportTabularAnnual Refactor#11421
mitchute wants to merge 10 commits intodevelopfrom
output-table-refactor

Conversation

@mitchute
Copy link
Collaborator

@mitchute mitchute commented Feb 13, 2026

Pull request overview

After working on #11410, I started looking around in here and realized I could spend a little time streamlining some of the things in this module without too much trouble. That effort uncovered the potential bug in #11420. I tried to focus on applying some modernization and best practices (as far as I understand them). If this causes issues for one reason or another, let me know.

Description of the purpose of this PR

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies
  • If adding/removing any output files (e.g., eplustbl.*)
    • Update ..\scripts\Epl-run.bat
    • Update ..\scripts\RunEPlus.bat
    • Update ..\src\EPLaunch\ MainModule.bas, epl-ui.frm, and epl.vbp (VersionComments)
    • Update ...github\workflows\energyplus.py

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@mitchute mitchute self-assigned this Feb 13, 2026
@mitchute mitchute added this to the EnergyPlus 26.1 IOFreeze milestone Feb 13, 2026
@mitchute mitchute added the Refactoring Includes code changes that don't change the functionality of the program, just perform refactoring label Feb 13, 2026
Copy link
Collaborator Author

@mitchute mitchute left a comment

Choose a reason for hiding this comment

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

Walk through

fldStIt->getVariableKeysFromFldSt(state, typeVar, keyCount, fldStIt->m_namesOfKeys, fldStIt->m_indexesForKeyVar);
for (std::string nm : fldStIt->m_namesOfKeys) {
// Gather key lists for each field set and build the union of all keys (optionally filtered)
for (auto &fldSt : m_annualFields) {
Copy link
Collaborator Author

@mitchute mitchute Feb 13, 2026

Choose a reason for hiding this comment

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

Lots of opportunities for range-based loop conversions in here. I applied as many as I could, except for places where we have nested iterator based loops indexing off one another.

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

fldStIt->m_cell[tableRowIndex].result = 0.0;
fldSt.m_cell[tableRowIndex].indexesForKeyVar = (foundKeyIndex >= 0) ? fldSt.m_indexesForKeyVar[foundKeyIndex] : -1;
// Initialize result based on aggregation kind
switch (fldSt.m_aggregate) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I applied switch/case where it made sense. All these if-else blocks based on enums seem prime for this pattern.

Comment on lines 69 to 70
constexpr Real64 veryLarge = 1.0E280;
constexpr Real64 verySmall = -1.0E280;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe I shouldn't move these to the header?

static Real64 const storedMaxVal(std::numeric_limits<Real64>::max());
static Real64 const storedMinVal(std::numeric_limits<Real64>::lowest());
static constexpr Real64 storedMaxVal(std::numeric_limits<Real64>::max());
static constexpr Real64 storedMinVal(std::numeric_limits<Real64>::lowest());
Copy link
Collaborator Author

@mitchute mitchute Feb 13, 2026

Choose a reason for hiding this comment

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

Is there any reason not to reuse these? Or even replace veryLarge and verySmall with these numeric_limits ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think these are only used to avoid writing to the tables when there is no updated minVal/maxVal values. i.e., so it doesn't matter what these initializations are, just that they are larger or smaller than expected results.

                    minVal = storedMaxVal;
                    maxVal = storedMinVal;

                    if (curVal > maxVal) maxVal = curVal;
                    if (curVal < minVal) minVal = curVal;

                    if (minVal != storedMaxVal) {
                        tableBody(columnRecount, 15) = RealToStr(minVal, digitsShown);
                    }
                    if (maxVal != storedMinVal) {
                        tableBody(columnRecount, 16) = RealToStr(maxVal, digitsShown);
                    }

Comment on lines +228 to +232
fldSt.m_cell[tableRowIndex].result = -9.9e99;
break;
case AnnualFieldSet::AggregationKind::minimum:
case AnnualFieldSet::AggregationKind::minimumDuringHoursShown:
fldSt.m_cell[tableRowIndex].result = 9.9e99;
Copy link
Collaborator Author

@mitchute mitchute Feb 13, 2026

Choose a reason for hiding this comment

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

Same question for these? Replace with veryLarge or numeric_limits ?

Copy link
Collaborator

@rraustad rraustad Feb 13, 2026

Choose a reason for hiding this comment

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

These are strange values to use for a table cell initialization. I'd have to see how these look in a table before I could suggest an alternative. I do think the use of "99999" data in cells means no data but using "99000" style seems different and I don't recall ever seeing that value in tables. Certainly there could be valid cell data larger than 99999.

Real64 realValue = -99999.0;

return -99999.0;

Copy link
Contributor

Choose a reason for hiding this comment

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

They could just be veryLarge and verySmall

}
fldStIt->m_cell[row].deferredElapsed.push_back(elapsedTime); // save the amount of time for this particular value
newDuration = oldDuration + elapsedTime;
// newDuration = oldDuration + elapsedTime;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was unused. I Just commented it out for now.

Comment on lines +594 to +598
cell.result = -9.9e99;
break;
case AnnualFieldSet::AggregationKind::minimum:
case AnnualFieldSet::AggregationKind::minimumDuringHoursShown:
cell.result = 9.9e99;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

veryLarge / numeric_limits

@mitchute
Copy link
Collaborator Author

The only regression file I found that exercised this is PurchAir_wAnnual, if you don't force design days. Running regressions on that file (and the entire suite) passed locally with no diffs.

@mitchute
Copy link
Collaborator Author

mitchute commented Feb 13, 2026

I forced annual simulations on the entire test suite and ran regressions locally on 69778ff. No diffs. This is ready to go, unless there are questions or comments.

@JasonGlazer
Copy link
Contributor

@mitchute let me take a quick look, since I was the original author.

@mitchute
Copy link
Collaborator Author

No worries. Take your time.

Copy link
Contributor

@JasonGlazer JasonGlazer left a comment

Choose a reason for hiding this comment

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

Looks good, sorry I didn't look at these changes sooner.

fldStIt->getVariableKeysFromFldSt(state, typeVar, keyCount, fldStIt->m_namesOfKeys, fldStIt->m_indexesForKeyVar);
for (std::string nm : fldStIt->m_namesOfKeys) {
// Gather key lists for each field set and build the union of all keys (optionally filtered)
for (auto &fldSt : m_annualFields) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

Comment on lines +228 to +232
fldSt.m_cell[tableRowIndex].result = -9.9e99;
break;
case AnnualFieldSet::AggregationKind::minimum:
case AnnualFieldSet::AggregationKind::minimumDuringHoursShown:
fldSt.m_cell[tableRowIndex].result = 9.9e99;
Copy link
Contributor

Choose a reason for hiding this comment

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

They could just be veryLarge and verySmall

if ((fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::maximum) ||
(fldStIt->m_aggregate == AnnualFieldSet::AggregationKind::minimum)) {
for (auto const &fldSt : m_annualFields) {
switch (fldSt.m_aggregate) {
Copy link
Contributor

Choose a reason for hiding this comment

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

much better

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Refactoring Includes code changes that don't change the functionality of the program, just perform refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants