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

Add new people schedule columns to EIO/initialization summary to address #10314 #10437

Merged
merged 25 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a673de6
Add new function for min max by daytype and new EIO/initialization re…
JasonGlazer Mar 13, 2024
60fe6f9
Add unit test
JasonGlazer Mar 14, 2024
26f96b0
Add support for other internal load equipment.
JasonGlazer Mar 14, 2024
ed9c634
Update output-details-and-examples for People
JasonGlazer Mar 18, 2024
8955374
Add new EIO outputs for remaining changes to output-details-and-examples
JasonGlazer Mar 18, 2024
f4280d1
Merge branch 'develop' into Fix10314-AddingScheduleColumns
JasonGlazer Apr 9, 2024
5957438
Using constexpr for dayfilters
JasonGlazer Apr 9, 2024
f32e3c7
clean ups
JasonGlazer Apr 9, 2024
5f0010a
clang format (although not actually better)
JasonGlazer Apr 9, 2024
af8fde5
Incorporate suggested code changes
JasonGlazer Apr 9, 2024
e437006
Store the min and max to speed up multiple calls for same schedule. C…
JasonGlazer Apr 10, 2024
bced9e7
format
JasonGlazer Apr 10, 2024
c4fe92c
Clang, clang, clang
JasonGlazer Apr 11, 2024
c0db5b7
Separate columns on design day to be separate for summer and winter d…
JasonGlazer Apr 11, 2024
eb855df
Merge branch 'develop' into Fix10314-AddingScheduleColumns
JasonGlazer Apr 11, 2024
f9e2315
Update output-details-and-examples/src/output-files/eplusout-eio.tex …
JasonGlazer Apr 11, 2024
a70fe0a
Fix typo
JasonGlazer Apr 11, 2024
90bf684
Trying to outwit clang-format which I cannot replicate locally.
JasonGlazer Apr 12, 2024
7f6925c
Retype code changes [decent_ci_skip]
JasonGlazer Apr 12, 2024
9c6a8e7
Move initialization out of constructor to make clang format happy (I …
JasonGlazer Apr 12, 2024
b912be3
Merge branch 'develop' into Fix10314-AddingScheduleColumns
JasonGlazer Apr 12, 2024
50b7a43
Add OutputChanges24-1-0-to-24-2-0.md [decent_ci_skip] [actions skip]
JasonGlazer Apr 12, 2024
77ed130
Merge branch 'develop' into Fix10314-AddingScheduleColumns
JasonGlazer Apr 25, 2024
b8d9928
Utilize SetScheduleMinMax and optimize loop
JasonGlazer Apr 25, 2024
8475b71
Don't iterate through duplicate week schedules when finding min and max.
JasonGlazer Apr 25, 2024
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
242 changes: 205 additions & 37 deletions doc/output-details-and-examples/src/output-files/eplusout-eio.tex

Large diffs are not rendered by default.

246 changes: 227 additions & 19 deletions src/EnergyPlus/InternalHeatGains.cc

Large diffs are not rendered by default.

136 changes: 104 additions & 32 deletions src/EnergyPlus/ScheduleManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2691,9 +2691,9 @@ namespace ScheduleManager {
// na

// Checking if valid index is passed is necessary
if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
return 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
return 0.0;
} else if (!state.dataScheduleMgr->Schedule(ScheduleIndex).EMSActuatedOn) {
return state.dataScheduleMgr->Schedule(ScheduleIndex)
Expand Down Expand Up @@ -2771,9 +2771,9 @@ namespace ScheduleManager {
// Return value
Real64 scheduleValue(0.0);

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
return 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
return 0.0;
}

Expand Down Expand Up @@ -2990,10 +2990,10 @@ namespace ScheduleManager {
state.dataScheduleMgr->ScheduleInputProcessed = true;
}

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = 1.0;
return;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
DayValues({1, state.dataGlobal->NumOfTimeStepInHour}, {1, 24}) = 0.0;
return;
}
Expand Down Expand Up @@ -3744,10 +3744,10 @@ namespace ScheduleManager {
Real64 MinValue(0.0); // For total minimum
Real64 MaxValue(0.0); // For total maximum

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
MaxValue = 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
MaxValue = 0.0;
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
Expand Down Expand Up @@ -3810,11 +3810,11 @@ namespace ScheduleManager {
bool MinValueOk = true;
bool MaxValueOk = true;

if (schedNum == -1) {
if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
assert(clusiveMin == Clusivity::Inclusive && clusiveMax == Clusivity::Inclusive);
MinValueOk = (Minimum == 1.0);
MaxValueOk = (Maximum == 1.0);
} else if (schedNum == 0) {
} else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
assert(clusiveMin == Clusivity::Inclusive && clusiveMax == Clusivity::Inclusive);
MinValueOk = (Minimum == 0.0);
MaxValueOk = (Maximum == 0.0);
Expand Down Expand Up @@ -3853,9 +3853,9 @@ namespace ScheduleManager {

Real64 MinValue(0.0); // For total minimum

if (schedNum == -1) {
if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
} else if (schedNum == 0) {
} else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
} else if (schedNum > 0 && schedNum > state.dataScheduleMgr->NumSchedules) {
if (!state.dataScheduleMgr->Schedule(schedNum).MaxMinSet) { // Set Minimum/Maximums for this schedule
Expand Down Expand Up @@ -3893,10 +3893,10 @@ namespace ScheduleManager {
bool MinValueOk;
bool MaxValueOk;

if (schedNum == -1) {
if (schedNum == ScheduleManager::ScheduleAlwaysOn) {
MinValueOk = (Minimum == 1.0);
MaxValueOk = (Maximum == 1.0);
} else if (schedNum == 0) {
} else if (schedNum == ScheduleManager::ScheduleAlwaysOff) {
MinValueOk = (Minimum == 0.0);
MaxValueOk = (Maximum == 0.0);
} else if (schedNum > 0 && schedNum <= state.dataScheduleMgr->NumSchedules) {
Expand Down Expand Up @@ -3962,9 +3962,9 @@ namespace ScheduleManager {

CheckScheduleValue = false;

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
CheckScheduleValue = (Value == 1.0);
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
CheckScheduleValue = (Value == 0.0);
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "CheckScheduleValue called with ScheduleIndex out of range");
Expand Down Expand Up @@ -4034,9 +4034,9 @@ namespace ScheduleManager {
int WkSch; // Pointer for WeekSchedule value

CheckScheduleValue = false;
if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
CheckScheduleValue = (Value == 1);
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
CheckScheduleValue = (Value == 0);
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "CheckScheduleValue called with ScheduleIndex out of range");
Expand Down Expand Up @@ -4109,10 +4109,10 @@ namespace ScheduleManager {
bool MinValueOk;
bool MaxValueOk;

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
MaxValue = 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
MaxValue = 0.0;
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumDaySchedules) {
Expand Down Expand Up @@ -4191,9 +4191,9 @@ namespace ScheduleManager {
Real64 MinValue(0.0); // For total minimum
bool MinValueOk;

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumDaySchedules) {
ShowFatalError(state, "CheckDayScheduleValueMinMax called with ScheduleIndex out of range");
Expand Down Expand Up @@ -4260,7 +4260,7 @@ namespace ScheduleManager {
int Hour;
int TStep;

if (ScheduleIndex == -1 || ScheduleIndex == 0) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn || ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {

} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "HasFractionalScheduleValue called with ScheduleIndex out of range");
Expand Down Expand Up @@ -4351,10 +4351,10 @@ namespace ScheduleManager {
int DayT;
int Loop;

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
MaxValue = 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
MaxValue = 0.0;
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
Expand Down Expand Up @@ -4442,10 +4442,10 @@ namespace ScheduleManager {
int DayT;
int Loop;

if (ScheduleIndex == -1) {
if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
MaxValue = 1.0;
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
MaxValue = 0.0;
} else if (ScheduleIndex < 1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
Expand Down Expand Up @@ -4491,6 +4491,78 @@ namespace ScheduleManager {
return MaximumValue;
}

std::pair<Real64, Real64> getScheduleMinMaxByDayType(EnergyPlusData &state, int const ScheduleIndex, DayTypeGroup const days)
{
// J. Glazer - March 2024
// finds the minimum and maximum for a specific set of day types for a given schedule
Real64 MinValue = Constant::BigNumber;
Real64 MaxValue = -Constant::BigNumber;
// Sun Mon Tues Wed Thur Fri Sat Hol Summer Winter Cust1 Cust2
constexpr std::array<bool, maxDayTypes> dayTypeFilterWkDy = {false, true, true, true, true, true, false, false, false, false, false, false};
constexpr std::array<bool, maxDayTypes> dayTypeFilterWeHo = {true, false, false, false, false, false, true, true, false, false, false, false};
// Sun Mon Tues Wed Thur Fri Sat Hol Summer Winter Cust1 Cust2
constexpr std::array<bool, maxDayTypes> dayTypeFilterSumDsDy = {
false, false, false, false, false, false, false, false, true, false, false, false};
constexpr std::array<bool, maxDayTypes> dayTypeFilterWinDsDy = {
false, false, false, false, false, false, false, false, false, true, false, false};
constexpr std::array<bool, maxDayTypes> dayTypeFilterNone = {
false, false, false, false, false, false, false, false, false, false, false, false};
if (ScheduleIndex > 0 && ScheduleIndex <= state.dataScheduleMgr->NumSchedules) {
Copy link
Contributor

@rraustad rraustad Apr 15, 2024

Choose a reason for hiding this comment

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

I am trying to convince myself that it is even possible for ScheduleIndex > NumSchedules. Not all functions in ScheduleManager use this check (i.e., ScheduleIndex <= NumSchedules). The only way to get an index is to call GetScheduleIndex, which uses FindItemInList and will either return a valid index or 0. I'm not convinced yet so nothing to do here. While investigating this I noticed in GetScheduleIndex that WeekSchedule(Schedule().WeekSchedulePointer()).Used and WeekSchedule(Schedule().WeekSchedulePointer()).DaySchedulePointer().Used are set but never used anywhere.

Copy link
Member

Choose a reason for hiding this comment

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

Used variables are never used. Alanis would be proud of that irony.

int curDayTypeGroup = static_cast<int>(days);
auto &curSch = state.dataScheduleMgr->Schedule(ScheduleIndex);
if (!curSch.MaxMinByDayTypeSet[curDayTypeGroup]) {
std::array<bool, maxDayTypes> dayTypeFilter;
switch (days) {
case DayTypeGroup::Weekday:
dayTypeFilter = dayTypeFilterWkDy;
break;
case DayTypeGroup::WeekEndHoliday:
dayTypeFilter = dayTypeFilterWeHo;
break;
case DayTypeGroup::SummerDesignDay:
dayTypeFilter = dayTypeFilterSumDsDy;
break;
case DayTypeGroup::WinterDesignDay:
dayTypeFilter = dayTypeFilterWinDsDy;
break;
default:
dayTypeFilter = dayTypeFilterNone;
break;
}
for (int iDayOfYear = 1; iDayOfYear <= 366; ++iDayOfYear) {
int WkSch = curSch.WeekSchedulePointer(iDayOfYear);
auto &weekSch = state.dataScheduleMgr->WeekSchedule(WkSch);
for (int jType = 1; jType <= maxDayTypes; ++jType) {
if (dayTypeFilter[jType - 1]) {
auto &daySch = state.dataScheduleMgr->DaySchedule(weekSch.DaySchedulePointer(jType));
MinValue = min(MinValue, minval(daySch.TSValue));
MaxValue = max(MaxValue, maxval(daySch.TSValue));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than cycle through the entire schedule for every daytype group, why not cycle through once and store the max/min for each day type first? Then cycle through those to sort into the DayTypeGroups.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mjwitte I did some optimization of this loop that should greatly improve it's performance although it is not exactly using the approach you suggested.

}
}
if (MinValue == Constant::BigNumber) MinValue = 0;
if (MaxValue == -Constant::BigNumber) MaxValue = 0;
// store for the next call of the same schedule
curSch.MaxByDayType[curDayTypeGroup] = MaxValue;
curSch.MinByDayType[curDayTypeGroup] = MinValue;
curSch.MaxMinByDayTypeSet[curDayTypeGroup] = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

There is another loop over people schedules in DetermineSystemPopulationDiversity. Not sure if this could help there or if when checking those people schedules these 3 values could be set to save even more simulation time.

} else {
// retrieve previously found min and max by day type
MaxValue = curSch.MaxByDayType[curDayTypeGroup];
MinValue = curSch.MinByDayType[curDayTypeGroup];
}
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
MinValue = 1.0;
MaxValue = 1.0;
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
MinValue = 0.0;
MaxValue = 0.0;
} else {
ShowFatalError(state, "getScheduleMinMaxByDayType called with ScheduleIndex out of range");
}
return std::make_pair(MinValue, MaxValue);
}

std::string GetScheduleName(EnergyPlusData &state, int const ScheduleIndex)
{
// FUNCTION INFORMATION:
Expand Down Expand Up @@ -4536,9 +4608,9 @@ namespace ScheduleManager {

if (ScheduleIndex > 0) {
ScheduleName = state.dataScheduleMgr->Schedule(ScheduleIndex).Name;
} else if (ScheduleIndex == -1) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOn) {
ScheduleName = "Constant-1.0";
} else if (ScheduleIndex == 0) {
} else if (ScheduleIndex == ScheduleManager::ScheduleAlwaysOff) {
ScheduleName = "Constant-0.0";
} else {
ScheduleName = "N/A-Invalid";
Expand Down Expand Up @@ -4694,7 +4766,7 @@ namespace ScheduleManager {
DaysInYear = 365;
}

if (ScheduleIndex < -1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "ScheduleAnnualFullLoadHours called with ScheduleIndex out of range");
}

Expand Down Expand Up @@ -4741,7 +4813,7 @@ namespace ScheduleManager {
WeeksInYear = 365.0 / 7.0;
}

if (ScheduleIndex < -1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "ScheduleAverageHoursPerWeek called with ScheduleIndex out of range");
}

Expand All @@ -4768,7 +4840,7 @@ namespace ScheduleManager {
DaysInYear = 365;
}

if (ScheduleIndex < -1 || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
if (ScheduleIndex < ScheduleManager::ScheduleAlwaysOn || ScheduleIndex > state.dataScheduleMgr->NumSchedules) {
ShowFatalError(state, "ScheduleHoursGT1perc called with ScheduleIndex out of range");
}

Expand Down
25 changes: 21 additions & 4 deletions src/EnergyPlus/ScheduleManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ struct EnergyPlusData;
namespace ScheduleManager {

constexpr int ScheduleAlwaysOn = -1;
constexpr int ScheduleAlwaysOff = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Much better than a magic number used everywhere, nice.


enum class DayType
{
Expand All @@ -93,6 +94,16 @@ namespace ScheduleManager {
extern const std::array<std::string_view, static_cast<int>(DayType::Num)> dayTypeNames;
extern const std::array<std::string_view, static_cast<int>(DayType::Num)> dayTypeNamesUC;

enum class DayTypeGroup
{
Invalid = -1,
Weekday = 1,
WeekEndHoliday,
SummerDesignDay,
WinterDesignDay,
Num
};

enum class SchedType : int
{
Invalid = -1,
Expand Down Expand Up @@ -186,10 +197,14 @@ namespace ScheduleManager {
bool MaxMinSet; // Max/min values have been stored for this schedule
Real64 MaxValue; // Maximum value for this schedule
Real64 MinValue; // Minimum value for this schedule
Real64 CurrentValue; // For Reporting
bool EMSActuatedOn; // indicates if EMS computed
Real64 EMSValue; // EMS value
bool UseDaylightSaving; // Toggles between daylight saving option to be inclused as "No" or "Yes" (default)
std::array<bool, static_cast<int>(DayType::Num)> MaxMinByDayTypeSet{
false}; // minimum and maximum values by daytype have been stored for this schedule
std::array<Real64, static_cast<int>(DayType::Num)> MinByDayType{0.0}; // minimum values by daytype for this schedule
std::array<Real64, static_cast<int>(DayType::Num)> MaxByDayType{0.0}; // maximum values by daytype for this schedule
Copy link
Member

Choose a reason for hiding this comment

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

Multiple arrays allocated to the same size hints that they may be nicer as a single struct. Not a big deal since there are just 3 arrays, but if it grew to more, it might be worthwhile.

Real64 CurrentValue; // For Reporting
bool EMSActuatedOn; // indicates if EMS computed
Real64 EMSValue; // EMS value
bool UseDaylightSaving; // Toggles between daylight saving option to be inclused as "No" or "Yes" (default)

// Default Constructor
ScheduleData()
Expand Down Expand Up @@ -339,6 +354,8 @@ namespace ScheduleManager {

Real64 GetScheduleMaxValue(EnergyPlusData &state, int const ScheduleIndex); // Which Schedule being tested

std::pair<Real64, Real64> getScheduleMinMaxByDayType(EnergyPlusData &state, int const ScheduleIndex, DayTypeGroup const days);

std::string GetScheduleName(EnergyPlusData &state, int const ScheduleIndex);

void ReportScheduleValues(EnergyPlusData &state);
Expand Down
40 changes: 40 additions & 0 deletions src/Transition/OutputRulesFiles/OutputChanges24-1-0-to-24-2-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Output Changes
==============

This file documents the structural changes on the output of EnergyPlus that could affect interfaces, etc.

### Description

This will eventually become a more structured file, but currently it isn't clear what format is best. As an intermediate solution, and to allow the form to be formed organically, this plain text file is being used. Entries should be clearly delimited. It isn't expected that there will be but maybe a couple each release at most. Entries should also include some reference back to the repo. At least a PR number or whatever.

### EIO Internal Gains and Initialization report

For the EIO lines for:

- People Internal Gains Nominal
- Lights Internal Gains Nominal
- ElectricEquipment Internal Gains Nominal
- GasEquipment Internal Gains Nominal
- HotWaterEquipment Internal Gains Nominal
- SteamEquipment Internal Gains Nominal
- OtherEquipment Internal Gains Nominal

replaced the colums:

- Nominal Minimum
- Nominal Maximum

with

- Minimum for All Day Types
- Maximum for All Day Types
- Minimum for Weekdays
- Maximum for Weekdays
- Minimum for Weekends/Holidays
- Maximum for Weekends/Holidays
- Minimum for Summer Design Days
- Maximum for Summer Design Days
- Minimum for Winter Design Days
- Maximum for Winter Design Days

These changes will also make corresponding changes in the HTML Intialization Summary report
Loading