Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
0c7e084
Initial NFP draft for new ScheduleRuleset.
joseph-robertson May 4, 2026
81a5e03
Update idd with new ScheduleRuleset and ScheduleRule entries.
joseph-robertson May 4, 2026
b708761
Update ScheduleManager for handling new ScheduleRuleset.
joseph-robertson May 4, 2026
1fa5c38
Introduce new ScheduleRuleset testfile with transcribed but equivalen…
joseph-robertson May 4, 2026
dcc9080
Merge branch 'develop' into sch-ruleset
joseph-robertson May 4, 2026
5047ef4
Updates for handling Feb 29 when schedule rules do not cover.
joseph-robertson May 4, 2026
c414117
Update code and testfile for actuating Schedule:Ruleset.
joseph-robertson May 4, 2026
9e4fd07
Add error checking on ScheduleRuleset day schedules.
joseph-robertson May 4, 2026
a2d25aa
Add support and testing for specific dates.
joseph-robertson May 4, 2026
39b1578
Add ScheduleRuleset unit test for checking rule priority.
joseph-robertson May 5, 2026
7aa8ef0
Convert remaining Schedule:Year to Schedule:Ruleset in new testfile.
joseph-robertson May 5, 2026
dab40f4
Add new test file to cmakelists.
joseph-robertson May 5, 2026
fe98f95
Merge branch 'develop' into sch-ruleset
joseph-robertson May 12, 2026
7c4e0e3
Merge branch 'develop' into sch-ruleset
joseph-robertson May 18, 2026
6a3722d
Update the schedule ruleset NFP.
joseph-robertson May 20, 2026
42eeef4
Merge branch 'develop' into sch-ruleset
joseph-robertson May 20, 2026
93e6ddf
Get a jump on adding ruleset documentation to the IO Ref.
joseph-robertson May 20, 2026
a2a53a5
Updates to new schedule manager around design days and validation.
joseph-robertson May 21, 2026
d6db254
Add a bunch of schedule ruleset unit tests.
joseph-robertson May 21, 2026
35be07c
Update new schedule ruleset test file with init program.
joseph-robertson May 21, 2026
71a0726
Use better int type.
joseph-robertson May 21, 2026
ab8851f
Add a schedule ruleset unit test for specific dates.
joseph-robertson May 26, 2026
6b71703
Add support and unit test for date range with wrap around.
joseph-robertson May 26, 2026
5bff4a3
Formatting.
joseph-robertson May 26, 2026
1fa3bd4
Update and add notes in idd.
joseph-robertson May 28, 2026
2e0ab9e
More updates for new io ref.
joseph-robertson May 28, 2026
6b456ed
Add NFP for ScheduleRuleset
Jun 1, 2026
b90137b
Merge branch 'develop' into sch-ruleset
joseph-robertson Jun 15, 2026
bcc43d3
Remove a couple of irrelevant items.
joseph-robertson Jun 15, 2026
1118479
Remove the bit about non-intuitive schedules.
joseph-robertson Jun 15, 2026
0efa192
List all the existing schedule types.
joseph-robertson Jun 15, 2026
288362f
Rename Schedule:Ruleset to Schedule:Year:Rules.
joseph-robertson Jun 15, 2026
ce75ebf
Clean up language around new schedule type.
joseph-robertson Jun 15, 2026
66bf9b7
Change field name Rule Order to Rule Priority Order.
joseph-robertson Jun 15, 2026
25a7dbf
Remove specific date fields and instead have extensible date ranges.
joseph-robertson Jun 15, 2026
fc55def
Rename Schedule:Rule to Schedule:Week:Rule.
joseph-robertson Jun 15, 2026
7b683e4
Remove bits about adding a new example file.
joseph-robertson Jun 15, 2026
95b1b98
Clean up language around the why.
joseph-robertson Jun 15, 2026
3caaf83
Merge branch 'sch-ruleset' into NFP-ScheduleRuleset-nfp-only
joseph-robertson Jun 15, 2026
c2417a0
Make changes per review, including object and field name changes, ext…
joseph-robertson Jun 16, 2026
3866bc7
Merge branch 'develop' into sch-ruleset
joseph-robertson Jun 18, 2026
912461d
Update to use std::format.
joseph-robertson Jun 18, 2026
fbee718
Merge branch 'develop' into sch-ruleset
joseph-robertson Jun 18, 2026
323e599
Merge branch 'develop' into sch-ruleset
joseph-robertson Jun 22, 2026
bb4d94b
Update docs for rule priority order uniqueness.
joseph-robertson Jun 22, 2026
7379eac
Throw severe error instead of warning for duplicate rule priority ord…
joseph-robertson Jun 22, 2026
d65afb5
Update duplicate rule priority test expected message.
joseph-robertson Jun 22, 2026
1974d60
Merge pull request #11612 from NatLabRockies/NFP-ScheduleRuleset-nfp-…
mitchute Jul 15, 2026
c2fe11b
Merge branch 'develop' into sch-ruleset
joseph-robertson Jul 15, 2026
d9eb14e
Delete the modified and now outdated ScheduleRuleset NFP.
joseph-robertson Jul 15, 2026
f8a5e59
Formatting.
joseph-robertson Jul 16, 2026
c836eb3
Update extensible comment in idd.
joseph-robertson Jul 16, 2026
96ec5bd
Update bad reference in tex file.
joseph-robertson Jul 16, 2026
c6716a7
Modify method for returning sorted rules instead of highest priority.
joseph-robertson Jul 16, 2026
a8115cf
New unit test for overlapping days with different weekdays applied.
joseph-robertson Jul 16, 2026
17dc5d1
Formatting and cleanup.
joseph-robertson Jul 17, 2026
b7903bd
Merge branch 'develop' into sch-ruleset
joseph-robertson Jul 17, 2026
64d40bb
Remove the temporary ruleset example file.
joseph-robertson Jul 17, 2026
9f19a72
Update duplicate priority severe message to error.
joseph-robertson Jul 17, 2026
7cae007
Formatting.
joseph-robertson Jul 24, 2026
7f7343e
Merge branch 'develop' into sch-ruleset
joseph-robertson Jul 24, 2026
2433b7f
Mark functions override in new WeekRuleSchedule struct.
joseph-robertson Jul 24, 2026
01e8a30
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 3, 2026
c2f477b
Merge branch 'develop', commit '01e8a301604dc441b5e37d06e539552c6e79e…
mitchute Aug 7, 2026
332d79f
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 10, 2026
deb0d80
Replace Schedule:Year with Schedule:Year:Rules for some schedules in …
joseph-robertson Aug 10, 2026
1612f42
Remove extensible fields from Schedule:Week:Rule in example file to d…
joseph-robertson Aug 10, 2026
4fc085b
Update docs around applicability of defaults in extensible groups.
joseph-robertson Aug 10, 2026
e13985e
Improve error checking in the extensible numeric parsing loop.
joseph-robertson Aug 10, 2026
ac9baad
Formatting.
joseph-robertson Aug 10, 2026
f836c00
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 11, 2026
6a007ca
Update example file to use correct field names.
joseph-robertson Aug 11, 2026
7893a54
Fix storing/comparing not both UC in map keys across schedule object …
joseph-robertson Aug 11, 2026
ca90a77
Refactor the inner Get/Add WeekSchedule loop, use a const on specDays…
joseph-robertson Aug 11, 2026
7dab4ee
Formatting.
joseph-robertson Aug 11, 2026
4b2c988
Merge branch 'sch-ruleset' of github.com:NatLabRockies/EnergyPlus int…
mitchute Aug 12, 2026
1673987
More updates and tests related to possible week schedule collision, c…
joseph-robertson Aug 12, 2026
49c061c
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 12, 2026
8c2e0d8
Formatting.
joseph-robertson Aug 13, 2026
33ef5c7
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 13, 2026
2e8cb01
Merge branch 'sch-ruleset' of github.com:NatLabRockies/EnergyPlus int…
mitchute Aug 17, 2026
8015c74
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 17, 2026
19bb327
Update idd and doc for exception around Feb 29 inheriting Feb 28.
joseph-robertson Aug 17, 2026
e9e2798
Update source and tests around internal week schedule map and orphane…
joseph-robertson Aug 17, 2026
dff3516
More ScheduleManager adjustments per review, and add field names to n…
joseph-robertson Aug 18, 2026
1956f38
More updates for case insensitive duplication.
joseph-robertson Aug 18, 2026
482d73a
Remove Sched::InitConstantScheduleData from new unit test since it's …
joseph-robertson Aug 18, 2026
f25ed9e
Merge branch 'develop' into sch-ruleset
mitchute Aug 19, 2026
f449dc5
A few final docs cleanups.
joseph-robertson Aug 19, 2026
66d50c8
Merge branch 'develop' into sch-ruleset
joseph-robertson Aug 19, 2026
34630da
Revert a bunch of unnecessary Util::makeUPPER.
joseph-robertson Aug 19, 2026
5ae7ac0
Update case unit test as a result of removing Util::makeUPPER.
joseph-robertson Aug 19, 2026
7fc980c
Formatting.
joseph-robertson Aug 19, 2026
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
293 changes: 293 additions & 0 deletions design/FY2026/NFP-ScheduleYearRules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
Schedule Year Rules
===================

**Joe Robertson, National Laboratory of the Rockies**

- May 1, 2026 - Initial Draft
- June 15, 2026 - Revised Draft

## Justification for New Feature ##

EnergyPlus currently requires users to decompose a yearly schedule into a hierarchy of objects: `Schedule:Day:*` → `Schedule:Week:*` → `Schedule:Year`.
This is expressive but verbose: a typical weekday/weekend/holiday schedule that a user might describe in a few sentences requires many objects and careful date-range bookkeeping.
The existing schedule types are:
- `Schedule:Year`
- `Schedule:Compact`
- `Schedule:Constant`
- `Schedule:File`
- `Schedule:File:Shading`

The OpenStudio SDK has long offered `OS:Schedule:Ruleset` as a higher-level, rule-based abstraction: the user defines a default day schedule and a prioritized list of override rules, each specifying which days of the week and which date range (or specific dates) the rule applies to.
Special design day schedules (summer, winter, holiday, custom) are also first-class fields.
This model is perhaps closer to how schedules are actually specified in building standards, energy codes, and operator manuals.

Today, the OpenStudio ForwardTranslator expands `OS:Schedule:Ruleset` into the `Schedule:Year` + `Schedule:Week:Daily` + `Schedule:Day:Interval` hierarchy before writing an IDF.
Adding `Schedule:Year:Rules` natively to EnergyPlus would allow users who author IDF/epJSON files directly to use this intuitive representation, and would eventually allow the OpenStudio ForwardTranslator to emit the compact ruleset form instead of the expanded one.

## E-mail and Conference Call Conclusions ##

Our generalized set of options for OS <-> E+ Alignment:
- Option 1 - Reverse translate from IDF to OSM (one time up front), and then forward translate from OSM to IDF (one time back end)
- Option 2 - Develop and push new objects into E+
- Option 3 - Drop support for an OS model object API; measures need to deal with the deprecation
- Option 4 - Data is backed; RT/FT on the fly (probably very expensive)

For handling `Schedule:Year:Rules`, we ultimately arrived at Option 2 (develop and push new objects into EnergyPlus).
The schedule we propose to add is convenient and easily extensible (i.e., an attractive schedule type).

## Overview ##

Add a new detailed schedule type.
The new schedule type is an alternative to, e.g., `Schedule:Year` and `Schedule:Compact`, for describing detailed schedules.
The new schedule type involves a parent "rules" object along with 1 to many "rule" objects.

The parent `Schedule:Year:Rules` object:
- Requires references to schedule type limits and a default day schedule
- Optionally references summer, winter, holiday, custom 1, and custom 2 design day schedules

The child(ren) `Schedule:Week:Rule` object(s):
- Requires reference to the parent `Schedule:Year:Rules` object
- Requires an "order" be specified for determining rule index amongst other rules
- Requires reference to a day schedule
- Specifies which day(s) of the week for which the rule applies
- Specifies the start month/day and end month/day (date ranges) for which the rule applies

During input processing, EnergyPlus will resolve the parent rules object into the same internal `ScheduleDetailed` structure used by `Schedule:Year` and `Schedule:Compact`.
No downstream code changes are required; the new objects are transparent to all schedule consumers.

## Approach ##

For the most part, follows the logic and implementation in OS.

Add new `Schedule:Year:Rules` and `Schedule:Week:Rule` objects to the IDD.

Make updates and additions to ScheduleManager.hh and ScheduleManager.cc:
- Get all `Schedule:Week:Rule` objects up front; move field values into structs
- Loop through each `Schedule:Year:Rules` object
- Call `AddScheduleDetailed` for creating a new detailed schedule
- For every day of the year:
- Get the "priority" schedule rule, i.e., the one whose (A) applicable dates contain the day and (B) has the least rule order value (0 = highest priority)
- Either get an existing, or add a new, week schedule
- Update the (12) day schedules according to the parent rule's special day schedules and rule's properties
- Assign the week schedule to the week schedule's array for the year

It is not required that a day has a rule defined for it (i.e., a `Schedule:Year:Rules` may have no attached `Schedule:Week:Rule` objects).
In this case, either:
- The day is Feb 29 and is just made equal to Feb 28, or
- The day falls back to the default day schedule as defined by the parent rules object.

Special design day slots (summer, winter, holiday, custom 1, custom 2) are set on all `WeekSchedule` objects.
If a special day schedule is not provided, the default day schedule is used as fallback for that slot.

Allow `Schedule:Year:Rules` objects to be actuated by adding the following at the end of the `CurrentModuleObject = "Schedule:Year:Rules";` block:
```
if (s_glob->AnyEnergyManagementSystemInModel) { // setup constant schedules as actuators
SetupEMSActuator(state, "Schedule:Year:Rules", sched->Name, "Schedule Value", "[ ]", sched->EMSActuatedOn, sched->EMSVal);
}
```

Downstream `GetSchedule` will find the detailed schedules created from `Schedule:Year:Rules` and `Schedule:Week:Rule`.

No new data structures are needed in `ScheduleManager.hh`.
The resolution is purely a parse-time operation that flattens the parent rules into the existing `ScheduleDetailed.weekScheds[367]` array.

No existing objects are changed.
No transition is required.

## Testing/Validation/Data Sources ##

Several new unit tests in `tst/EnergyPlus/unit/ScheduleManager.unit.cc` covering:

- A parent rules object with two rules demonstrating priority (lower `Rule Priority Order` wins when date ranges overlap).
- Date range specification: correct day assignment across a date range, including wrap-around (e.g., Nov 1 – Jan 31).
- Fallback to default day schedule when no rule matches.
- Summer/winter/holiday design day overrides; fallback to default day schedule when not specified.
- Validation errors: unknown `Day Schedule Name`, duplicate `Rule Order` values within a parent rules object (warning), missing Default Day Schedule.

## Input Output Reference Documentation ##

Update `doc/input-output-reference/src/overview/group-schedules.tex` with new `Schedule:Year:Rules` and `Schedule:Week:Rule` subsections placed directly following `Schedule:Year` and `Schedule:Compact`.
Key points to document:

- The priority model: rules are evaluated in ascending `Rule Priority Order`; the first matching rule wins.
- The special-day schedule fields and their fallback behavior.
- The relationship between `Schedule:Year:Rules`, `Schedule:Week:Rule`, and `Schedule:Day:*` objects.

## Input Description ##

IDD:

```
Schedule:Year:Rules,
\memo A Schedule:Year:Rules defines a yearly schedule using a default day profile and
\memo a prioritized list of override rules (Schedule:Week:Rule objects). Rules are evaluated
\memo in ascending Rule Order; the first matching rule for a given day is used.
\memo If no rule matches, the Default Day Schedule is used.
\min-fields 3
A1 , \field Name
\type alpha
\required-field
\reference ScheduleNames
\reference ScheduleYearRulesNames
A2 , \field Schedule Type Limits Name
\type object-list
\object-list ScheduleTypeLimitsNames
A3 , \field Default Day Schedule Name
\required-field
\type object-list
\object-list DayScheduleNames
A4 , \field Summer Design Day Schedule Name
\note If blank, the Default Day Schedule is used for Summer Design Days.
\type object-list
\object-list DayScheduleNames
A5 , \field Winter Design Day Schedule Name
\note If blank, the Default Day Schedule is used for Winter Design Days.
\type object-list
\object-list DayScheduleNames
A6 , \field Holiday Schedule Name
\note If blank, the Default Day Schedule is used for Holidays.
\type object-list
\object-list DayScheduleNames
A7 , \field Custom Day 1 Schedule Name
\note If blank, the Default Day Schedule is used for Custom Day 1.
\type object-list
\object-list DayScheduleNames
A8 ; \field Custom Day 2 Schedule Name
\note If blank, the Default Day Schedule is used for Custom Day 2.
\type object-list
\object-list DayScheduleNames

Schedule:Week:Rule,
\memo A Schedule:Week:Rule defines one override rule for a Schedule:Year:Rules.
\memo Rules are evaluated in ascending Rule Priority Order; the first matching rule wins.
\memo A rule matches a day if: (a) the day falls within the specified date ranges,
\memo AND (b) the corresponding Apply <DayOfWeek> field is Yes.
\extensible:4 - repeat last four fields (Start Month, Start Day, End Month, End Day)
\min-fields 11
A1 , \field Name
\type alpha
\required-field
\reference ScheduleRuleNames
A2 , \field Schedule Year Rules Name
\required-field
\type object-list
\object-list ScheduleYearRulesNames
N1 , \field Rule Priority Order
\note Lower values have higher priority. Must be unique within a Schedule:Year:Rules.
\type integer
\required-field
\minimum 0
A3 , \field Day Schedule Name
\required-field
\type object-list
\object-list DayScheduleNames
A4 , \field Apply Sunday
\type choice
\default No
\key Yes
\key No
A5 , \field Apply Monday
\type choice
\default No
\key Yes
\key No
A6 , \field Apply Tuesday
\type choice
\default No
\key Yes
\key No
A7 , \field Apply Wednesday
\type choice
\default No
\key Yes
\key No
A8 , \field Apply Thursday
\type choice
\default No
\key Yes
\key No
A9 , \field Apply Friday
\type choice
\default No
\key Yes
\key No
A10, \field Apply Saturday
\type choice
\default No
\key Yes
\key No
N2 , \field Start Month
\begin-extensible
\type integer
\minimum 1
\maximum 12
\default 1
N3 , \field Start Day
\type integer
\minimum 1
\maximum 31
\default 1
N4 , \field End Month
\type integer
\minimum 1
\maximum 12
\default 12
N5 ; \field End Day
\type integer
\minimum 1
\maximum 31
\default 31
```

Example IDF snippet:

```
Schedule:Year:Rules,
occupants schedule year rules, !- Name
Fractional, !- Schedule Type Limits Name
occupants schedule default day, !- Default Day Schedule Name
occupants schedule default day, !- Summer Design Day Schedule Name
occupants schedule default day, !- Winter Design Day Schedule Name
occupants schedule default day, !- Holiday Schedule Name
occupants schedule default day, !- Custom Day 1 Schedule Name
occupants schedule default day; !- Custom Day 2 Schedule Name

Schedule:Week:Rule,
occupants schedule week rule, !- Name
occupants schedule year rules, !- Schedule Year Rules Name
0, !- Rule Order
occupants schedule day, !- Day Schedule Name
No, !- Apply Sunday
Yes, !- Apply Monday
No, !- Apply Tuesday
Yes, !- Apply Wednesday
No, !- Apply Thursday
Yes, !- Apply Friday
No, !- Apply Saturday
1, !- Start Month
1, !- Start Day
12, !- End Month
31; !- End Day
```

## Outputs Description ##

No new output variables are added.
`Schedule:Year:Rules` objects will appear in existing schedule reporting (e.g., `Output:Schedules`) under their name, identical to `Schedule:Year`.

## Engineering Reference ##

No changes to the Engineering Reference are required.
The rule-resolution algorithm is a straightforward date and day-of-week lookup with no new physics.

## Example File and Transition Changes ##

No new example files are added; feature is purely additive so there is no need to demonstrate parity on an ongoing basis.

No transition rules are required; this is a purely additive feature.

## References ##

- OpenStudio Model API - `OS:Schedule:Ruleset` / `OS:Schedule:Rule`
- OpenStudio ForwardTranslator — current expansion to `Schedule:Year`: `ForwardTranslateScheduleRuleset.cpp`
- EnergyPlus Engineering Reference, Schedules chapter
Loading
Loading