diff --git a/BuildResidentialHPXML/README.md b/BuildResidentialHPXML/README.md
index ac08fb9b90..66fca73cce 100644
--- a/BuildResidentialHPXML/README.md
+++ b/BuildResidentialHPXML/README.md
@@ -23,7 +23,6 @@ Absolute/relative path of the HPXML file.
- **Default:** `hpxml.xml`
-
**Simulation Control: Timestep**
@@ -39,7 +38,6 @@ The timestep for the simulation; defaults to hourly calculations for fastest run
- **Default:** `60`
-
**Simulation Control: Run Period**
@@ -53,7 +51,6 @@ Enter a date range like 'Mar 1 - May 31'. Defaults to the entire year.
- **Default:** `Jan 1 - Dec 31`
-
**Location: Zip Code**
@@ -65,7 +62,6 @@ Zip code of the home address. Either this or the EnergyPlus Weather (EPW) File P
- **Required:** ``false``
-
**Location: EnergyPlus Weather (EPW) File Path**
@@ -77,7 +73,6 @@ Path to the EPW file. Either this or the Zip Code input above must be provided.
- **Required:** ``false``
-
**Location: Site Type**
@@ -93,7 +88,6 @@ The terrain/shielding of the home, for the infiltration model. Defaults to 'Subu
- **Default:** `Default`
-
**Location: Soil Type**
@@ -109,7 +103,6 @@ The soil and moisture type.
- **Default:** `Unknown`
-
**Building Construction: Year Built**
@@ -123,7 +116,6 @@ The year the building was built.
- **Default:** `2026`
-
**Geometry: Unit Type**
@@ -139,7 +131,6 @@ The type of dwelling unit and number of stories. Includes conditioned attics and
- **Default:** `Single-Family Detached, 2 Stories`
-
**Geometry: Unit Attached Walls**
@@ -155,7 +146,6 @@ For single-family attached and apartment units, the location(s) of the attached
- **Default:** `None`
-
**Geometry: Unit Conditioned Floor Area**
@@ -171,7 +161,6 @@ The total floor area of the unit's conditioned space (including any conditioned
- **Default:** `2000.0`
-
**Geometry: Unit Aspect Ratio**
@@ -187,7 +176,6 @@ The ratio of front/back wall length to left/right wall length for the unit, excl
- **Default:** `2.0`
-
**Geometry: Unit Direction**
@@ -203,7 +191,6 @@ Direction of the front of the unit.
- **Default:** `South`
-
**Geometry: Unit Number of Bedrooms**
@@ -219,7 +206,6 @@ The number of bedrooms in the unit.
- **Default:** `3`
-
**Geometry: Unit Number of Bathrooms**
@@ -235,7 +221,6 @@ The number of bathrooms in the unit. Defaults to NumberofBedrooms/2 + 0.5.
- **Default:** `Default`
-
**Geometry: Unit Number of Occupants**
@@ -251,7 +236,6 @@ The number of occupants in the unit. Defaults to an *asset* calculation assuming
- **Default:** `Default`
-
**Geometry: Ceiling Height**
@@ -267,7 +251,6 @@ Average distance from the floor to the ceiling.
- **Default:** `8.0 ft`
-
**Geometry: Attached Garage**
@@ -283,7 +266,6 @@ The type of attached garage. Only applies to single-family detached units.
- **Default:** `None`
-
**Geometry: Foundation Type**
@@ -299,7 +281,6 @@ The foundation type of the building. Garages are assumed to be over slab-on-grad
- **Default:** `Crawlspace, Vented`
-
**Geometry: Attic Type**
@@ -315,7 +296,6 @@ The attic/roof type of the building.
- **Default:** `Attic, Vented, Gable`
-
**Geometry: Roof Pitch**
@@ -331,7 +311,6 @@ The roof pitch of the attic. Ignored if the building has a flat roof.
- **Default:** `6:12`
-
**Geometry: Eaves**
@@ -347,7 +326,6 @@ The type of eaves extending from the roof.
- **Default:** `2 ft`
-
**Geometry: Neighbor Buildings**
@@ -363,7 +341,6 @@ The presence and geometry of neighboring buildings, for shading purposes.
- **Default:** `None`
-
**Geometry: Window Areas or WWRs**
@@ -377,7 +354,6 @@ The amount of window area on the unit's front/back/left/right facades. Use a com
- **Default:** `0.15, 0.15, 0.15, 0.15`
-
**Geometry: Skylight Areas**
@@ -391,7 +367,6 @@ The amount of skylight area on the unit's front/back/left/right roofs. Use a com
- **Default:** `0, 0, 0, 0`
-
**Geometry: Doors Area**
@@ -407,7 +382,6 @@ The area of the opaque door(s). Any door glazing (e.g., sliding glass doors) sho
- **Default:** `20.0`
-
**Enclosure: Floor Over Foundation**
@@ -423,7 +397,6 @@ The type and insulation level of the floor over the foundation (e.g., crawlspace
- **Default:** `Wood Frame, Uninsulated`
-
**Enclosure: Floor Over Garage**
@@ -439,7 +412,6 @@ The type and insulation level of the floor over the garage.
- **Default:** `Wood Frame, Uninsulated`
-
**Enclosure: Foundation Wall**
@@ -455,7 +427,6 @@ The type and insulation level of the foundation walls.
- **Default:** `Solid Concrete, Uninsulated`
-
**Enclosure: Rim Joists**
@@ -471,7 +442,6 @@ The type and insulation level of the rim joists.
- **Default:** `Uninsulated`
-
**Enclosure: Slab**
@@ -487,7 +457,6 @@ The type and insulation level of the slab. Applies to slab-on-grade as well as b
- **Default:** `Uninsulated`
-
**Enclosure: Carpet**
@@ -503,7 +472,6 @@ The amount of carpet. Applies to floors/slabs adjacent to conditioned space. The
- **Default:** `80% Carpet`
-
**Enclosure: Ceiling**
@@ -519,7 +487,6 @@ The type and insulation level of the ceiling (attic floor).
- **Default:** `R-30`
-
**Enclosure: Roof**
@@ -535,7 +502,6 @@ The type and insulation level of the roof.
- **Default:** `Uninsulated`
-
**Enclosure: Roof Material**
@@ -551,7 +517,6 @@ The material type and color of the roof.
- **Default:** `Asphalt/Fiberglass Shingles, Medium`
-
**Enclosure: Radiant Barrier**
@@ -567,7 +532,6 @@ The type of radiant barrier in the attic.
- **Default:** `None`
-
**Enclosure: Walls**
@@ -583,7 +547,6 @@ The type and insulation level of the walls.
- **Default:** `Wood Stud, R-13`
-
**Enclosure: Wall Continuous Insulation**
@@ -599,7 +562,6 @@ The insulation level of the wall continuous insulation. The R-value of the conti
- **Default:** `Uninsulated`
-
**Enclosure: Wall Siding**
@@ -615,7 +577,6 @@ The type, color, and insulation level of the wall siding. The R-value of the sid
- **Default:** `Wood, Medium`
-
**Enclosure: Windows**
@@ -631,7 +592,6 @@ The type of windows.
- **Default:** `Double, Clear, Metal, Air`
-
**Enclosure: Window Natural Ventilation**
@@ -647,7 +607,6 @@ The amount of natural ventilation from occupants opening operable windows when o
- **Default:** `67% Operable Windows`
-
**Enclosure: Window Interior Shading**
@@ -663,7 +622,6 @@ The type of window interior shading. If shading coefficients are selected, note
- **Default:** `Curtains, Light`
-
**Enclosure: Window Exterior Shading**
@@ -679,7 +637,6 @@ The type of window exterior shading. If shading coefficients are selected, note
- **Default:** `None`
-
**Enclosure: Window Insect Screens**
@@ -695,7 +652,6 @@ The type of window insect screens.
- **Default:** `None`
-
**Enclosure: Window Storm**
@@ -711,7 +667,6 @@ The type of storm window.
- **Default:** `None`
-
**Enclosure: Window Overhangs**
@@ -727,7 +682,6 @@ The type of window overhangs.
- **Default:** `None`
-
**Enclosure: Skylights**
@@ -743,7 +697,6 @@ The type of skylights.
- **Default:** `Single, Clear, Metal`
-
**Enclosure: Doors**
@@ -759,7 +712,6 @@ The type of doors.
- **Default:** `Solid Wood, R-2`
-
**Enclosure: Air Leakage**
@@ -775,7 +727,6 @@ The amount of air leakage coming from outside. If a qualitative leakiness descri
- **Default:** `Average`
-
**HVAC: Heating System**
@@ -791,7 +742,6 @@ The type and efficiency of the heating system. Use 'None' if there is no heating
- **Default:** `Central Furnace, 78% AFUE`
-
**HVAC: Heating System Fuel Type**
@@ -807,7 +757,6 @@ The fuel type of the heating system. Ignored for ElectricResistance.
- **Default:** `Natural Gas`
-
**HVAC: Heating System Capacity**
@@ -823,7 +772,6 @@ The output capacity of the heating system.
- **Default:** `Autosize`
-
**HVAC: Heating System Fraction Heat Load Served**
@@ -839,7 +787,6 @@ The fraction of the heating load served by the heating system.
- **Default:** `100%`
-
**HVAC: Cooling System**
@@ -855,7 +802,6 @@ The type and efficiency of the cooling system. Use 'None' if there is no cooling
- **Default:** `Central AC, SEER2 13.4`
-
**HVAC: Cooling System Capacity**
@@ -871,7 +817,6 @@ The output capacity of the cooling system.
- **Default:** `Autosize`
-
**HVAC: Cooling System Fraction Cool Load Served**
@@ -887,7 +832,6 @@ The fraction of the cooling load served by the cooling system.
- **Default:** `100%`
-
**HVAC: Heat Pump**
@@ -903,7 +847,6 @@ The type and efficiency of the heat pump.
- **Default:** `None`
-
**HVAC: Heat Pump Capacity**
@@ -919,7 +862,6 @@ The output capacity of the heat pump.
- **Default:** `Autosize`
-
**HVAC: Heat Pump Fraction Heat Load Served**
@@ -935,7 +877,6 @@ The fraction of the heating load served by the heat pump.
- **Default:** `100%`
-
**HVAC: Heat Pump Fraction Cool Load Served**
@@ -951,7 +892,6 @@ The fraction of the cooling load served by the heat pump.
- **Default:** `100%`
-
**HVAC: Heat Pump Temperatures**
@@ -967,7 +907,6 @@ Specifies the minimum compressor temperature and/or maximum HP backup temperatur
- **Default:** `Default`
-
**HVAC: Heat Pump Backup Type**
@@ -983,7 +922,6 @@ The type and efficiency of the heat pump backup. Use 'None' if there is no backu
- **Default:** `Integrated, Electricity, 100% Efficiency`
-
**HVAC: Heat Pump Backup Capacity**
@@ -999,7 +937,6 @@ The output capacity of the heat pump backup if there is integrated backup heatin
- **Default:** `Autosize`
-
**HVAC: Geothermal Loop**
@@ -1015,7 +952,6 @@ The geothermal loop configuration if there's a ground-to-air heat pump.
- **Default:** `Default`
-
**HVAC: Heating System 2**
@@ -1031,7 +967,6 @@ The type and efficiency of the second heating system. If a heat pump is specifie
- **Default:** `None`
-
**HVAC: Heating System 2 Fuel Type**
@@ -1047,7 +982,6 @@ The fuel type of the second heating system. Ignored for ElectricResistance.
- **Default:** `Electricity`
-
**HVAC: Heating System 2 Capacity**
@@ -1063,7 +997,6 @@ The output capacity of the second heating system.
- **Default:** `Autosize`
-
**HVAC: Heating System 2 Fraction Heat Load Served**
@@ -1079,7 +1012,6 @@ The fraction of the heating load served by the second heating system.
- **Default:** `25%`
-
**HVAC Control: Heating Weekday Setpoint Schedule**
@@ -1093,7 +1025,6 @@ Specify the constant or 24-hour comma-separated weekday heating setpoint schedul
- **Default:** `68`
-
**HVAC Control: Heating Weekend Setpoint Schedule**
@@ -1107,7 +1038,6 @@ Specify the constant or 24-hour comma-separated weekend heating setpoint schedul
- **Default:** `68`
-
**HVAC Control: Cooling Weekday Setpoint Schedule**
@@ -1121,7 +1051,6 @@ Specify the constant or 24-hour comma-separated weekday cooling setpoint schedul
- **Default:** `78`
-
**HVAC Control: Cooling Weekend Setpoint Schedule**
@@ -1135,7 +1064,6 @@ Specify the constant or 24-hour comma-separated weekend cooling setpoint schedul
- **Default:** `78`
-
**HVAC Control: Heating Season Period**
@@ -1149,7 +1077,6 @@ Enter a date range like 'Nov 1 - Jun 30'. Defaults to year-round heating availab
- **Default:** `Jan 1 - Dec 31`
-
**HVAC Control: Cooling Season Period**
@@ -1163,7 +1090,6 @@ Enter a date range like 'Jun 1 - Oct 31'. Defaults to year-round cooling availab
- **Default:** `Jan 1 - Dec 31`
-
**HVAC Ducts**
@@ -1179,7 +1105,6 @@ The leakage to outside and insulation level of the ducts.
- **Default:** `15% Leakage, Uninsulated`
-
**HVAC Ducts: Supply Location**
@@ -1195,7 +1120,6 @@ The primary location of the supply ducts. The remainder of the supply ducts are
- **Default:** `Default`
-
**HVAC Ducts: Return Location**
@@ -1211,7 +1135,6 @@ The primary location of the return ducts. The remainder of the return ducts are
- **Default:** `Default`
-
**Ventilation Fans: Mechanical Ventilation**
@@ -1227,7 +1150,6 @@ The type of mechanical ventilation system used for whole building ventilation.
- **Default:** `None`
-
**Ventilation Fans: Kitchen Exhaust Fan**
@@ -1243,7 +1165,6 @@ The type of kitchen exhaust fan used for local ventilation.
- **Default:** `None`
-
**Ventilation Fans: Bathroom Exhaust Fans**
@@ -1259,7 +1180,6 @@ The type of bathroom exhaust fans used for local ventilation.
- **Default:** `None`
-
**Ventilation Fans: Whole House Fan**
@@ -1275,7 +1195,6 @@ The type of whole house fans used for seasonal cooling load reduction.
- **Default:** `None`
-
**DHW: Water Heater**
@@ -1291,7 +1210,6 @@ The type and efficiency of the water heater.
- **Default:** `Electricity, Tank, UEF 0.92`
-
**DHW: Water Heater Location**
@@ -1307,7 +1225,6 @@ The location of the water heater. Defaults based on the foundation/garage type.
- **Default:** `Default`
-
**DHW: Hot Water Distribution**
@@ -1323,7 +1240,6 @@ The type of domestic hot water distrubtion.
- **Default:** `Uninsulated, Standard`
-
**DHW: Hot Water Fixtures**
@@ -1339,7 +1255,6 @@ The type and usage of domestic hot water fixtures.
- **Default:** `Standard, 100% Usage`
-
**DHW: Drain Water Heat Reovery**
@@ -1355,7 +1270,6 @@ The type of drain water heater recovery.
- **Default:** `None`
-
**DHW: Solar Thermal**
@@ -1371,7 +1285,6 @@ The size and type of the solar thermal system for domestic hot water.
- **Default:** `None`
-
**DHW: Solar Thermal Direction**
@@ -1387,7 +1300,6 @@ The azimuth and tilt of the solar thermal system collectors.
- **Default:** `Roof Pitch, South`
-
**PV: System**
@@ -1403,7 +1315,6 @@ The size and type of the PV system.
- **Default:** `None`
-
**PV: System Direction**
@@ -1419,7 +1330,6 @@ The azimuth and tilt of the PV system array.
- **Default:** `Roof Pitch, South`
-
**PV: System 2**
@@ -1435,7 +1345,6 @@ The size and type of the second PV system.
- **Default:** `None`
-
**PV: System 2 Direction**
@@ -1451,7 +1360,6 @@ The azimuth and tilt of the second PV system array.
- **Default:** `Roof Pitch, South`
-
**Battery**
@@ -1467,7 +1375,6 @@ The size and type of battery storage.
- **Default:** `None`
-
**Electric Vehicle**
@@ -1483,7 +1390,6 @@ The type of battery electric vehicle.
- **Default:** `None`
-
**Electric Vehicle: Charger**
@@ -1499,7 +1405,6 @@ The type and usage of electric vehicle charger.
- **Default:** `None`
-
**Appliances: Clothes Washer**
@@ -1515,7 +1420,6 @@ The type and usage of clothes washer.
- **Default:** `Standard, 2008-2017, 100% Usage`
-
**Appliances: Clothes Dryer**
@@ -1531,7 +1435,6 @@ The type and usage of clothes dryer.
- **Default:** `Electricity, Standard, 100% Usage`
-
**Appliances: Dishwasher**
@@ -1547,7 +1450,6 @@ The type and usage of dishwasher.
- **Default:** `Federal Minimum, Standard, 100% Usage`
-
**Appliances: Refrigerator**
@@ -1563,7 +1465,6 @@ The type and usage of refrigerator.
- **Default:** `434 kWh/yr, 100% Usage`
-
**Appliances: Extra Refrigerator**
@@ -1579,7 +1480,6 @@ The type and usage of extra refrigerator.
- **Default:** `None`
-
**Appliances: Freezer**
@@ -1595,7 +1495,6 @@ The type and usage of freezer.
- **Default:** `None`
-
**Appliances: Cooking Range/Oven**
@@ -1611,7 +1510,6 @@ The type and usage of cooking range/oven.
- **Default:** `Electricity, Standard, Non-Convection, 100% Usage`
-
**Appliances: Dehumidifier**
@@ -1627,7 +1525,6 @@ The type of dehumidifier.
- **Default:** `None`
-
**Appliances: Dehumidifier Setpoint**
@@ -1643,7 +1540,6 @@ The dehumidifier's relative humidity (RH) setpoint.
- **Default:** `50% RH`
-
**Lighting**
@@ -1659,7 +1555,6 @@ The type and usage of interior, exterior, and garage lighting.
- **Default:** `50% LED, 100% Usage`
-
**Ceiling Fans**
@@ -1675,7 +1570,6 @@ The type of ceiling fans.
- **Default:** `None`
-
**Misc: Television**
@@ -1691,7 +1585,6 @@ The amount of television usage, relative to the national average.
- **Default:** `100% Usage`
-
**Misc: Plug Loads**
@@ -1707,7 +1600,6 @@ The amount of additional plug load usage, relative to the national average.
- **Default:** `100% Usage`
-
**Misc: Well Pump**
@@ -1723,7 +1615,6 @@ The amount of well pump usage, relative to the national average.
- **Default:** `None`
-
**Misc: Electric Vehicle Charging**
@@ -1739,7 +1630,6 @@ The amount of EV charging usage, relative to the national average. Only use this
- **Default:** `None`
-
**Misc: Gas Grill**
@@ -1755,7 +1645,6 @@ The amount of outdoor gas grill usage, relative to the national average.
- **Default:** `None`
-
**Misc: Gas Lighting**
@@ -1771,7 +1660,6 @@ The amount of gas lighting usage, relative to the national average.
- **Default:** `None`
-
**Misc: Fireplace**
@@ -1787,7 +1675,6 @@ The amount of fireplace usage, relative to the national average. Fireplaces can
- **Default:** `None`
-
**Misc: Pool**
@@ -1803,7 +1690,6 @@ The type of pool (pump & heater).
- **Default:** `None`
-
**Misc: Permanent Spa**
@@ -1819,7 +1705,6 @@ The type of permanent spa (pump & heater).
- **Default:** `None`
-
**Schedules: CSV File Paths**
@@ -1831,7 +1716,6 @@ Absolute/relative paths of csv files containing user-specified detailed schedule
- **Required:** ``false``
-
**Advanced Feature**
@@ -1847,7 +1731,6 @@ Select an advanced research feature to use in the model, if desired.
- **Default:** `None`
-
**Advanced Feature 2**
@@ -1863,7 +1746,6 @@ Select a second advanced research feature to use in the model, if desired.
- **Default:** `None`
-
**Utility Bill Scenario**
@@ -1879,7 +1761,6 @@ The type of utility bill calculations to perform.
- **Default:** `Default (EIA Average Rates)`
-
**Utility Bill Scenario 2**
@@ -1895,7 +1776,6 @@ The second type of utility bill calculations to perform, if desired.
- **Default:** `None`
-
**Utility Bill Scenario 3**
@@ -1911,7 +1791,6 @@ The third type of utility bill calculations to perform, if desired.
- **Default:** `None`
-
**Additional Properties**
@@ -1923,7 +1802,6 @@ Additional properties specified as key-value pairs (i.e., key=value). If multipl
- **Required:** ``false``
-
**Whole SFA/MF Building Simulation?**
@@ -1935,7 +1813,8 @@ Set true if creating an HPXML file to simulate a whole single-family attached or
- **Required:** ``false``
-
+- **Default:** `false`
+
**Combine like surfaces?**
@@ -1947,7 +1826,8 @@ If true, combines like surfaces to simplify the HPXML file generated.
- **Required:** ``false``
-
+- **Default:** `false`
+
**Apply Default Values?**
@@ -1959,7 +1839,8 @@ If true, applies OS-HPXML default values to the HPXML output file. Setting to tr
- **Required:** ``false``
-
+- **Default:** `false`
+
**Apply Validation?**
@@ -1971,7 +1852,8 @@ If true, validates the HPXML output file. Set to false for faster performance. N
- **Required:** ``false``
-
+- **Default:** `false`
+
diff --git a/BuildResidentialHPXML/README.md.erb b/BuildResidentialHPXML/README.md.erb
index 9ed4acb24b..2c10598744 100644
--- a/BuildResidentialHPXML/README.md.erb
+++ b/BuildResidentialHPXML/README.md.erb
@@ -24,10 +24,9 @@
<% if argument[:type] == "Choice" %>
- **Choices:**
- `<%= argument[:choice_values].join("`
- `") %>`
<% end %>
-<% if argument[:default_value] %>
+<% if argument[:default_value] or argument[:default_value] == false %>
- **Default:** `<%= argument[:default_value] %>`
<% end %>
-
<% end %>
<% if arguments.size == 0 %>
diff --git a/BuildResidentialHPXML/measure.xml b/BuildResidentialHPXML/measure.xml
index a6a0828507..d761a5d60e 100644
--- a/BuildResidentialHPXML/measure.xml
+++ b/BuildResidentialHPXML/measure.xml
@@ -3,8 +3,8 @@
3.1
build_residential_hpxml
a13a8983-2b01-4930-8af2-42030b6e4233
- 8503d96a-f627-408e-87fe-5e35f9d14712
- 2026-01-07T01:56:28Z
+ 7bc6e3a7-7e6e-4897-b356-ad9f193af60f
+ 2026-02-12T20:36:47Z
2C38F48B
BuildResidentialHPXML
HPXML Builder
@@ -11389,13 +11389,13 @@
README.md
md
readme
- A3747D4E
+ 1DCD6ACC
README.md.erb
erb
readmeerb
- FBCE3CFF
+ 5238CEA2
diff --git a/BuildResidentialScheduleFile/README.md b/BuildResidentialScheduleFile/README.md
index 30c3d1c28c..899164a5d1 100644
--- a/BuildResidentialScheduleFile/README.md
+++ b/BuildResidentialScheduleFile/README.md
@@ -20,7 +20,7 @@ Absolute/relative path of the HPXML file.
- **Required:** ``true``
-
+
**Schedules: Column Names**
@@ -31,7 +31,7 @@ A comma-separated list of the column names to generate. If not provided, default
- **Required:** ``false``
-
+
**Schedules: Random Seed**
@@ -44,7 +44,7 @@ This numeric field is the seed for the random number generator.
- **Required:** ``false``
-
+
**Schedules: Output CSV Path**
@@ -55,7 +55,7 @@ Absolute/relative path of the CSV file containing occupancy schedules. Relative
- **Required:** ``true``
-
+
**HPXML Output File Path**
@@ -66,7 +66,7 @@ Absolute/relative output path of the HPXML file. This HPXML file will include th
- **Required:** ``true``
-
+
**Append Output?**
@@ -77,7 +77,9 @@ If true and the output CSV file already exists, appends columns to the file rath
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Debug Mode?**
@@ -88,7 +90,9 @@ If true, writes extra column(s) for informational purposes.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**BuildingID**
@@ -99,7 +103,7 @@ The ID of the HPXML Building. Only required if there are multiple Building eleme
- **Required:** ``false``
-
+
diff --git a/BuildResidentialScheduleFile/README.md.erb b/BuildResidentialScheduleFile/README.md.erb
index 0e9bc87d3e..2c10598744 100644
--- a/BuildResidentialScheduleFile/README.md.erb
+++ b/BuildResidentialScheduleFile/README.md.erb
@@ -22,9 +22,11 @@
<% end %>
- **Required:** ``<%= argument[:required] %>``
<% if argument[:type] == "Choice" %>
-- **Choices:** `<%= argument[:choice_values].join("`, `") %>`
+- **Choices:**
- `<%= argument[:choice_values].join("`
- `") %>`
+<% end %>
+<% if argument[:default_value] or argument[:default_value] == false %>
+- **Default:** `<%= argument[:default_value] %>`
<% end %>
-
<% end %>
<% if arguments.size == 0 %>
diff --git a/BuildResidentialScheduleFile/measure.xml b/BuildResidentialScheduleFile/measure.xml
index 4e47398bf7..e9719fcaff 100644
--- a/BuildResidentialScheduleFile/measure.xml
+++ b/BuildResidentialScheduleFile/measure.xml
@@ -3,8 +3,8 @@
3.1
build_residential_schedule_file
f770b2db-1a9f-4e99-99a7-7f3161a594b1
- f6dd34d9-aee7-4f48-bb18-50b66ec581d3
- 2026-01-28T18:33:10Z
+ a794739a-f354-4670-8457-1d52216ff5dd
+ 2026-02-12T20:36:49Z
03F02484
BuildResidentialScheduleFile
Schedule File Builder
@@ -116,13 +116,13 @@
README.md
md
readme
- 04BFD8B8
+ DE433EFB
README.md.erb
erb
readmeerb
- 513F28E9
+ 5238CEA2
diff --git a/Changelog.md b/Changelog.md
index 4d148c246c..d54b7b3dfb 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -6,6 +6,7 @@ __New Features__
- Improves handling of duct leakage specified using cfm25/cfm50.
- Output updates:
- **Breaking change**: Replaces "UnitX" prefixes with Building IDs in whole SFA/MF building timeseries outputs.
+ - For whole SFA/MF building simulations, adds energy/fuel use outputs reported by dwelling unit (i.e., "Dwelling Unit Energy Use: *" and "Dwelling Unit Fuel Use: *").
- Adds a `run_simulation.rb --ems-debug` argument to generate the EnergyPlus EDD file for debugging EMS programs.
__Bugfixes__
diff --git a/HPXMLtoOpenStudio/README.md b/HPXMLtoOpenStudio/README.md
index 8f8a248cdb..ef2f83dddc 100644
--- a/HPXMLtoOpenStudio/README.md
+++ b/HPXMLtoOpenStudio/README.md
@@ -20,7 +20,7 @@ Absolute/relative path of the HPXML file.
- **Required:** ``true``
-
+
**Directory for Output Files**
@@ -31,7 +31,7 @@ Absolute/relative path for the output files directory.
- **Required:** ``true``
-
+
**Output Format**
@@ -42,9 +42,11 @@ The file format of the HVAC design load details output.
- **Required:** ``false``
-- **Choices:** `csv`, `json`, `msgpack`
+- **Choices:**
- `csv`
- `json`
- `msgpack`
+
+
+- **Default:** `csv`
-
**Annual Output File Name**
@@ -55,7 +57,9 @@ The name of the file w/ HVAC design loads and capacities. If not provided, defau
- **Required:** ``false``
-
+
+- **Default:** `results_annual`
+
**Electric Panel Output File Name**
@@ -66,7 +70,9 @@ The name of the file w/ electric panel outputs. If not provided, defaults to 're
- **Required:** ``false``
-
+
+- **Default:** `results_panel`
+
**Design Load Details Output File Name**
@@ -77,7 +83,9 @@ The name of the file w/ additional HVAC design load details. If not provided, de
- **Required:** ``false``
-
+
+- **Default:** `results_design_load_details`
+
**Add component loads?**
@@ -88,7 +96,9 @@ If true, adds the calculation of heating/cooling component loads (not enabled by
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**BuildingID**
@@ -99,7 +109,7 @@ The ID of the HPXML Building. Only required if the HPXML has multiple Building e
- **Required:** ``false``
-
+
**Skip Validation?**
@@ -110,7 +120,9 @@ If true, bypasses HPXML input validation for faster performance. WARNING: This s
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Debug Mode?**
@@ -121,7 +133,9 @@ If true: 1) Writes in.osm file, 2) Generates additional log output, and 3) Creat
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**EMS Debug Mode?**
@@ -132,7 +146,9 @@ If true, writes the EnergyPlus EDD file with timeseries debug output for each EM
- **Required:** ``false``
-
+
+- **Default:** `false`
+
diff --git a/HPXMLtoOpenStudio/README.md.erb b/HPXMLtoOpenStudio/README.md.erb
index 0e9bc87d3e..2c10598744 100644
--- a/HPXMLtoOpenStudio/README.md.erb
+++ b/HPXMLtoOpenStudio/README.md.erb
@@ -22,9 +22,11 @@
<% end %>
- **Required:** ``<%= argument[:required] %>``
<% if argument[:type] == "Choice" %>
-- **Choices:** `<%= argument[:choice_values].join("`, `") %>`
+- **Choices:**
- `<%= argument[:choice_values].join("`
- `") %>`
+<% end %>
+<% if argument[:default_value] or argument[:default_value] == false %>
+- **Default:** `<%= argument[:default_value] %>`
<% end %>
-
<% end %>
<% if arguments.size == 0 %>
diff --git a/HPXMLtoOpenStudio/measure.rb b/HPXMLtoOpenStudio/measure.rb
index b4c5c22b81..80430bddb2 100644
--- a/HPXMLtoOpenStudio/measure.rb
+++ b/HPXMLtoOpenStudio/measure.rb
@@ -162,7 +162,7 @@ def run(model, runner, user_arguments)
Outputs.apply_ems_programs(model, hpxml_osm_map, hpxml.header, args[:add_component_loads])
Outputs.apply_output_file_controls(model, args[:debug])
Outputs.apply_additional_properties(model, hpxml, hpxml_osm_map, args[:hpxml_path], args[:building_id], args[:hpxml_defaults_path])
- Outputs.create_custom_meters(model)
+ Outputs.create_custom_electricity_meters(model)
if args[:ems_debug]
Outputs.apply_ems_debug_output(model)
end
@@ -398,6 +398,9 @@ def create_unit_model(hpxml, hpxml_bldg, runner, model, weather, schedules_file)
Generator.apply(model, hpxml_bldg)
Battery.apply(runner, model, spaces, hpxml_bldg, schedules_file)
Vehicle.apply(runner, model, spaces, hpxml_bldg, hpxml.header, schedules_file)
+
+ # Unit Meters
+ Outputs.create_custom_unit_meters(model, hpxml)
end
# Miscellaneous logic that needs to occur upfront.
diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml
index 9e69bb3417..a75450bbcc 100644
--- a/HPXMLtoOpenStudio/measure.xml
+++ b/HPXMLtoOpenStudio/measure.xml
@@ -3,8 +3,8 @@
3.1
hpxm_lto_openstudio
b1543b30-9465-45ff-ba04-1d1f85e763bc
- f10d160e-01f4-4406-9b7f-8b0242583c06
- 2026-02-23T17:34:34Z
+ c72cbbd9-f0ea-4a57-a126-51d6cdca89d7
+ 2026-02-23T19:42:44Z
D8922A73
HPXMLtoOpenStudio
HPXML to OpenStudio Translator
@@ -194,13 +194,13 @@
README.md
md
readme
- 1C614A83
+ 5A03B464
README.md.erb
erb
readmeerb
- 513F28E9
+ 5238CEA2
@@ -211,7 +211,7 @@
measure.rb
rb
script
- DF6F2409
+ 5A6F94D4
airflow.rb
@@ -493,13 +493,13 @@
model.rb
rb
resource
- 51B1D207
+ 2B9008EA
output.rb
rb
resource
- 27CD133C
+ 61919957
psychrometrics.rb
diff --git a/HPXMLtoOpenStudio/resources/model.rb b/HPXMLtoOpenStudio/resources/model.rb
index d6580860ee..1a6346952d 100644
--- a/HPXMLtoOpenStudio/resources/model.rb
+++ b/HPXMLtoOpenStudio/resources/model.rb
@@ -1202,6 +1202,32 @@ def self.make_variable_name(obj_name, unit_number)
return new_name
end
+ # Key/variable groups for custom meters don't get updated automatically.
+ # Keys that aren't nil or EMS get updated.
+ # Variables that are ":Zone:XXX" meters get the XXX zone names updated (e.g.,
+ # cooking range:InteriorEquipment:Electricity:Zone:CONDITIONED SPACE to
+ # cooking range:InteriorEquipment:Electricity:Zone:unit1_CONDITIONED_SPACE).
+ # Additionally, variables with the EMS key get updated.
+ #
+ # @param key_var_group
+ # @param unit_number [Integer] index number corresponding to an HPXML Building object
+ # @return [String, String] The key and variable updated with prefixes and friendly strings.
+ def self.update_key_variable_group(key_var_group, unit_number)
+ key, var = key_var_group
+ if (not key.empty?) && (key != 'EMS')
+ key = make_variable_name(key, unit_number)
+ end
+ if var.include?(':Zone:')
+ var = var.split(':')
+ prefix = var[0..-2].join(':')
+ zone_name = make_variable_name(var[-1], unit_number)
+ var = "#{prefix}:#{zone_name}"
+ elsif key == 'EMS'
+ var = make_variable_name(var, unit_number)
+ end
+ return key, var
+ end
+
# Prefix all object names using using a provided unit number.
#
# @param unit_model [OpenStudio::Model::Model] OpenStudio Model object (corresponding to one of multiple dwelling units)
@@ -1210,6 +1236,22 @@ def self.make_variable_name(obj_name, unit_number)
def self.prefix_object_names(unit_model, unit_number)
# FUTURE: Create objects with unique names up front so we don't have to do this
+ # Custom meter objects
+ (unit_model.getMeterCustoms + unit_model.getMeterCustomDecrements).each do |meter|
+ if meter.is_a? OpenStudio::Model::MeterCustomDecrement
+ source_meter_name = meter.sourceMeterName
+ source_meter_name = make_variable_name(source_meter_name, unit_number)
+ meter.setSourceMeterName(source_meter_name)
+ end
+
+ key_var_groups = meter.keyVarGroups
+ meter.removeAllKeyVarGroups
+ key_var_groups.each do |key_var_group|
+ key, var = update_key_variable_group(key_var_group, unit_number)
+ meter.addKeyVarGroup(key, var)
+ end
+ end
+
# EMS objects
ems_map = {}
@@ -1243,7 +1285,7 @@ def self.prefix_object_names(unit_model, unit_number)
ems_map[subroutine.name.to_s] = make_variable_name(subroutine.name, unit_number)
end
- # variables in program lines don't get updated automatically
+ # Variables in program lines don't get updated automatically
lhs_characters = [' ', ',', '(', ')', '+', '-', '*', '/', ';']
rhs_characters = [''] + lhs_characters
(unit_model.getEnergyManagementSystemPrograms + unit_model.getEnergyManagementSystemSubroutines).each do |program|
diff --git a/HPXMLtoOpenStudio/resources/output.rb b/HPXMLtoOpenStudio/resources/output.rb
index ba7ff3ebd9..7c51107fbc 100644
--- a/HPXMLtoOpenStudio/resources/output.rb
+++ b/HPXMLtoOpenStudio/resources/output.rb
@@ -996,6 +996,7 @@ def self.apply_additional_properties(model, hpxml, hpxml_osm_map, hpxml_path, bu
additionalProperties = model.getBuilding.additionalProperties
additionalProperties.setFeature('hpxml_path', hpxml_path)
additionalProperties.setFeature('hpxml_defaults_path', hpxml_defaults_path)
+ additionalProperties.setFeature('hpxml_bldgs_size', hpxml.buildings.size)
additionalProperties.setFeature('building_id', building_id.to_s)
additionalProperties.setFeature('emissions_scenario_names', hpxml.header.emissions_scenarios.map { |s| s.name }.to_s)
additionalProperties.setFeature('emissions_scenario_types', hpxml.header.emissions_scenarios.map { |s| s.emissions_type }.to_s)
@@ -1446,8 +1447,9 @@ def self.register_results_out_to_runner(runner, results_out)
# Creates custom output meters that are used across reporting measures.
#
# @param model [OpenStudio::Model::Model] OpenStudio Model object
+ # @param custom_unit_meter [OpenStudio::Model::MeterCustom] optional OpenStudio custom meter object
# @return [nil]
- def self.create_custom_meters(model)
+ def self.create_custom_electricity_meters(model, custom_unit_meter = nil)
# Create custom meters:
# - Total Electricity (Electricity:Facility plus EV charging, batteries, generators)
# - Net Electricity (above plus PV)
@@ -1477,9 +1479,15 @@ def self.create_custom_meters(model)
elcd.generators.each do |generator|
next unless generator.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypePhotovoltaics
- net_key_vars << ['', 'Photovoltaic:ElectricityProduced']
- pv_key_vars << net_key_vars[-1]
- net_key_vars << ['', 'PowerConversion:ElectricityProduced']
+ if generator.to_GeneratorPVWatts.is_initialized
+ net_key_vars << [generator.name.to_s.upcase, 'Generator Produced DC Electricity Energy']
+ pv_key_vars << net_key_vars[-1]
+ end
+ end
+
+ if elcd.inverter.is_initialized
+ inv = elcd.inverter.get
+ net_key_vars << [inv.name.to_s.upcase, 'Inverter Conversion Loss Decrement Energy']
pv_key_vars << net_key_vars[-1]
end
@@ -1487,7 +1495,9 @@ def self.create_custom_meters(model)
elcd.generators.each do |generator|
next unless generator.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypeGenerator
- net_key_vars << ['', 'Cogeneration:ElectricityProduced']
+ next unless generator.to_GeneratorMicroTurbine.is_initialized
+
+ net_key_vars << [generator.name.to_s, 'Generator Produced AC Electricity Energy']
total_key_vars << net_key_vars[-1]
gen_key_vars << net_key_vars[-1]
end
@@ -1499,7 +1509,14 @@ def self.create_custom_meters(model)
MeterCustomElectricityCritical => pv_key_vars + gen_key_vars }.each do |meter_name, key_vars|
if key_vars.empty?
# Avoid OpenStudio warnings if nothing to decrement
- key_vars << ['', 'Electricity:Facility']
+ if custom_unit_meter.nil?
+ key_vars << ['', 'Electricity:Facility']
+ else
+ # Meter:Custom cannot reference another Meter:Custom,
+ # so we pass key/variable groups from one to the other.
+ # https://github.com/NatLabRockies/EnergyPlus/issues/11400
+ key_vars = custom_unit_meter.keyVarGroups
+ end
Model.add_meter_custom(
model,
name: meter_name,
@@ -1527,4 +1544,385 @@ def self.create_custom_meters(model)
)
end
end
+
+ # Create custom meters with fuel usage *for each unit*.
+ #
+ # @param model [OpenStudio::Model::Model] OpenStudio Model object
+ # @param hpxml [HPXML] HPXML object
+ # @return [nil]
+ def self.create_custom_unit_meters(model, hpxml)
+ return if hpxml.buildings.size == 1
+
+ to_eplus = { FT::Elec => EPlus::FuelTypeElectricity,
+ FT::Gas => EPlus::FuelTypeNaturalGas,
+ FT::Oil => EPlus::FuelTypeOil,
+ FT::Propane => EPlus::FuelTypePropane,
+ FT::WoodCord => EPlus::FuelTypeWoodCord,
+ FT::WoodPellets => EPlus::FuelTypeWoodPellets,
+ FT::Coal => EPlus::FuelTypeCoal }
+
+ to_eplus.values.each do |fuel_type|
+ key_vars = []
+ model.getModelObjects.sort.each do |object|
+ next if object.to_AdditionalProperties.is_initialized
+
+ vars_by_key = get_object_outputs_by_key(model, object, EUT)
+ vars_by_key.each do |key, output_vars|
+ ft, eut = key
+
+ next if to_eplus[ft] != fuel_type
+
+ if fuel_type == EPlus::FuelTypeElectricity
+ next if [EUT::PV, EUT::Generator, EUT::Vehicle, EUT::Battery].include?(eut) &&
+ !output_vars.any? { |x| x.include?(Constants::ObjectTypeBatteryLossesAdjustment) || x.include?(Constants::ObjectTypeMiscElectricVehicleCharging) }
+ end
+
+ output_vars.each do |output_var|
+ if object.to_EnergyManagementSystemOutputVariable.is_initialized
+ varkey = 'EMS'
+ else
+ varkey = object.name.to_s.upcase
+ varkey = '' if output_var.include?(':') # Avoid the "Output Variable or Meter Name="x:y:z" referenced multiple times warning by just not including key names for meters
+ end
+
+ key_vars << [varkey, output_var]
+ end
+ end
+ end
+
+ next if key_vars.empty?
+
+ custom_unit_meter = Model.add_meter_custom(
+ model,
+ name: "#{fuel_type}:Facility",
+ fuel_type: fuel_type,
+ key_var_pairs: key_vars
+ )
+
+ # We're in the fuel types loop so that we can pass in custom_unit_meter from above.
+ # But we don't want to call create_custom_electricity_meters multiple times.
+ if fuel_type == EPlus::FuelTypeElectricity
+ create_custom_electricity_meters(model, custom_unit_meter)
+ end
+ end
+ end
+
+ # For a given object, returns the Output:Variables or Output:Meters to be requested,
+ # and associates them with the appropriate keys (e.g., [FT::Elec, EUT::Heating]).
+ #
+ # @param model [OpenStudio::Model::Model] OpenStudio Model object
+ # @param object [OpenStudio::Model::Foo] A given object in the OpenStudio Model
+ # @param class_type [Module] The output class type
+ # @return [Hash] Map of output key => array of EnergyPlus output variable/meter names
+ def self.get_object_outputs_by_key(model, object, class_type)
+ object_type = object.additionalProperties.getFeatureAsString('ObjectType')
+ object_type = object_type.get if object_type.is_initialized
+
+ to_ft = { EPlus::FuelTypeElectricity => FT::Elec,
+ EPlus::FuelTypeNaturalGas => FT::Gas,
+ EPlus::FuelTypeOil => FT::Oil,
+ EPlus::FuelTypePropane => FT::Propane,
+ EPlus::FuelTypeWoodCord => FT::WoodCord,
+ EPlus::FuelTypeWoodPellets => FT::WoodPellets,
+ EPlus::FuelTypeCoal => FT::Coal }
+
+ if class_type == EUT
+
+ # End uses
+
+ if object.to_CoilHeatingDXSingleSpeed.is_initialized || object.to_CoilHeatingDXMultiSpeed.is_initialized
+ vars = { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy', 'Heating Coil Defrost Electricity Energy'] }
+ if object.additionalProperties.getFeatureAsDouble('FractionHeatLoadServed').is_initialized && object.additionalProperties.getFeatureAsDouble('FractionHeatLoadServed').get <= 0
+ # HP only provides cooling, allocate crankcase to cooling end use
+ vars[[FT::Elec, EUT::Cooling]] = ['Heating Coil Crankcase Heater Electricity Energy']
+ else
+ # Allocate crankcase to heating end use
+ vars[[FT::Elec, EUT::Heating]] << 'Heating Coil Crankcase Heater Electricity Energy'
+ end
+ return vars
+
+ elsif object.to_CoilHeatingElectric.is_initialized || object.to_CoilHeatingElectricMultiStage.is_initialized
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { [FT::Elec, EUT::HeatingHeatPumpBackup] => ['Heating Coil Electricity Energy'] }
+ else
+ return { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy'] }
+ end
+
+ elsif object.to_CoilHeatingGas.is_initialized
+ fuel = object.to_CoilHeatingGas.get.fuelType
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { [to_ft[fuel], EUT::HeatingHeatPumpBackup] => ["Heating Coil #{fuel} Energy", "Heating Coil Ancillary #{fuel} Energy"] }
+ else
+ return { [to_ft[fuel], EUT::Heating] => ["Heating Coil #{fuel} Energy", "Heating Coil Ancillary #{fuel} Energy"] }
+ end
+
+ elsif object.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
+ return { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy'] }
+
+ elsif object.to_ZoneHVACBaseboardConvectiveElectric.is_initialized
+ object = object.to_ZoneHVACBaseboardConvectiveElectric.get
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { [FT::Elec, EUT::HeatingHeatPumpBackup] => ['Baseboard Electricity Energy'] }
+ else
+ return { [FT::Elec, EUT::Heating] => ['Baseboard Electricity Energy'] }
+ end
+
+ elsif object.to_BoilerHotWater.is_initialized
+ is_combi_boiler = false
+ if object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').is_initialized
+ is_combi_boiler = object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').get
+ end
+ if not is_combi_boiler # Exclude combi boiler, whose heating & dhw energy is handled separately via EMS
+ fuel = object.to_BoilerHotWater.get.fuelType
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { [to_ft[fuel], EUT::HeatingHeatPumpBackup] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
+ else
+ return { [to_ft[fuel], EUT::Heating] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
+ end
+ else
+ fuel = object.to_BoilerHotWater.get.fuelType
+ return { [to_ft[fuel], EUT::HotWater] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
+ end
+
+ elsif object.to_CoilCoolingDXSingleSpeed.is_initialized || object.to_CoilCoolingDXMultiSpeed.is_initialized
+ vars = { [FT::Elec, EUT::Cooling] => ['Cooling Coil Electricity Energy'] }
+ parent = model.getAirLoopHVACUnitarySystems.select { |u| u.coolingCoil.is_initialized && u.coolingCoil.get.handle.to_s == object.handle.to_s }
+ if (not parent.empty?) && parent[0].heatingCoil.is_initialized
+ htg_coil = parent[0].heatingCoil.get
+ end
+ if parent.empty?
+ parent = model.getZoneHVACPackagedTerminalAirConditioners.select { |u| u.coolingCoil.handle.to_s == object.handle.to_s }
+ if not parent.empty?
+ htg_coil = parent[0].heatingCoil
+ end
+ end
+ if parent.empty?
+ fail 'Could not find parent object.'
+ end
+
+ if htg_coil.nil? || (not (htg_coil.to_CoilHeatingDXSingleSpeed.is_initialized || htg_coil.to_CoilHeatingDXMultiSpeed.is_initialized))
+ # Crankcase variable only available if no DX heating coil on parent
+ vars[[FT::Elec, EUT::Cooling]] << 'Cooling Coil Crankcase Heater Electricity Energy'
+ end
+ return vars
+
+ elsif object.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
+ return { [FT::Elec, EUT::Cooling] => ['Cooling Coil Electricity Energy'] }
+
+ elsif object.to_EvaporativeCoolerDirectResearchSpecial.is_initialized
+ return { [FT::Elec, EUT::Cooling] => ['Evaporative Cooler Electricity Energy'] }
+
+ elsif object.to_CoilWaterHeatingAirToWaterHeatPumpWrapped.is_initialized
+ return { [FT::Elec, EUT::HotWater] => ['Cooling Coil Water Heating Electricity Energy'] }
+
+ elsif object.to_FanSystemModel.is_initialized
+ if object_type == Constants::ObjectTypeWaterHeater
+ return { [FT::Elec, EUT::HotWater] => ['Fan Electricity Energy'] }
+ end
+
+ elsif object.to_PumpConstantSpeed.is_initialized
+ if object_type == Constants::ObjectTypeSolarHotWater
+ return { [FT::Elec, EUT::HotWaterSolarThermalPump] => ['Pump Electricity Energy'] }
+ end
+
+ elsif object.to_WaterHeaterMixed.is_initialized
+ fuel = object.to_WaterHeaterMixed.get.heaterFuelType
+ return { [to_ft[fuel], EUT::HotWater] => ["Water Heater #{fuel} Energy", 'Water Heater Off Cycle Parasitic Electricity Energy', 'Water Heater On Cycle Parasitic Electricity Energy'] }
+
+ elsif object.to_WaterHeaterStratified.is_initialized
+ fuel = object.to_WaterHeaterStratified.get.heaterFuelType
+ return { [to_ft[fuel], EUT::HotWater] => ["Water Heater #{fuel} Energy", 'Water Heater Off Cycle Parasitic Electricity Energy', 'Water Heater On Cycle Parasitic Electricity Energy'] }
+
+ elsif object.to_Lights.is_initialized
+ object = object.to_Lights.get
+ subcategory = object.endUseSubcategory
+ end_use = { Constants::ObjectTypeLightingInterior => EUT::LightsInterior,
+ Constants::ObjectTypeLightingGarage => EUT::LightsGarage }[subcategory]
+ fail 'Unexpected error: InteriorLights:Electricity without a space.' unless object.space.is_initialized
+
+ zone_name = object.space.get.thermalZone.get.name.to_s.upcase
+ return { [FT::Elec, end_use] => ["#{subcategory}:InteriorLights:Electricity:Zone:#{zone_name}"] }
+
+ elsif object.to_ElectricLoadCenterInverterPVWatts.is_initialized
+ return { [FT::Elec, EUT::PV] => ['Inverter Conversion Loss Decrement Energy'] }
+
+ elsif object.to_GeneratorPVWatts.is_initialized
+ return { [FT::Elec, EUT::PV] => ['Generator Produced DC Electricity Energy'] }
+
+ elsif object.to_GeneratorMicroTurbine.is_initialized
+ fuel = object.to_GeneratorMicroTurbine.get.fuelType
+ return { [FT::Elec, EUT::Generator] => ['Generator Produced AC Electricity Energy'],
+ [to_ft[fuel], EUT::Generator] => ["Generator #{fuel} HHV Basis Energy"] }
+
+ elsif object.to_ElectricLoadCenterStorageLiIonNMCBattery.is_initialized
+ if object_type == Constants::ObjectTypeVehicle
+ return { [FT::Elec, EUT::Vehicle] => ['Electric Storage Charge Energy'] }
+ elsif object_type == Constants::ObjectTypeBattery
+ return { [FT::Elec, EUT::Battery] => ['Electric Storage Production Decrement Energy', 'Electric Storage Discharge Energy'] }
+ else
+ fail "Unexpected elcs: #{object.name}"
+ end
+
+ elsif object.to_ElectricEquipment.is_initialized
+ object = object.to_ElectricEquipment.get
+ subcategory = object.endUseSubcategory
+ end_use = nil
+ { Constants::ObjectTypeHotWaterRecircPump => EUT::HotWaterRecircPump,
+ Constants::ObjectTypeClothesWasher => EUT::ClothesWasher,
+ Constants::ObjectTypeClothesDryer => EUT::ClothesDryer,
+ Constants::ObjectTypeDishwasher => EUT::Dishwasher,
+ Constants::ObjectTypeRefrigerator => EUT::Refrigerator,
+ Constants::ObjectTypeFreezer => EUT::Freezer,
+ Constants::ObjectTypeCookingRange => EUT::RangeOven,
+ Constants::ObjectTypeCeilingFan => EUT::CeilingFan,
+ Constants::ObjectTypeWholeHouseFan => EUT::WholeHouseFan,
+ Constants::ObjectTypeMechanicalVentilation => EUT::MechVent,
+ Constants::ObjectTypeMiscPlugLoads => EUT::PlugLoads,
+ Constants::ObjectTypeMiscTelevision => EUT::Television,
+ Constants::ObjectTypeMiscPoolHeater => EUT::PoolHeater,
+ Constants::ObjectTypeMiscPoolPump => EUT::PoolPump,
+ Constants::ObjectTypeMiscPermanentSpaHeater => EUT::PermanentSpaHeater,
+ Constants::ObjectTypeMiscPermanentSpaPump => EUT::PermanentSpaPump,
+ Constants::ObjectTypeMiscElectricVehicleCharging => EUT::Vehicle,
+ Constants::ObjectTypeMiscWellPump => EUT::WellPump,
+ Constants::ObjectTypeLightingExterior => EUT::LightsExterior,
+ Constants::ObjectTypeLightingExteriorHoliday => EUT::LightsExterior }.each do |obj_name, eut|
+ next unless subcategory.start_with? obj_name
+ fail 'Unexpected error: multiple matches.' unless end_use.nil?
+
+ end_use = eut
+ end
+
+ if not end_use.nil?
+ # Use Output:Meter instead of Output:Variable because they incorporate thermal zone multipliers
+ fail 'Unexpected error: InteriorEquipment:Electricity without a space.' unless object.space.is_initialized
+
+ zone_name = object.space.get.thermalZone.get.name.to_s.upcase
+ return { [FT::Elec, end_use] => ["#{subcategory}:InteriorEquipment:Electricity:Zone:#{zone_name}"] }
+ end
+
+ elsif object.to_OtherEquipment.is_initialized
+ object = object.to_OtherEquipment.get
+ subcategory = object.endUseSubcategory
+ fuel = object.fuelType
+ end_use = nil
+ { Constants::ObjectTypeClothesDryer => EUT::ClothesDryer,
+ Constants::ObjectTypeCookingRange => EUT::RangeOven,
+ Constants::ObjectTypeMiscGrill => EUT::Grill,
+ Constants::ObjectTypeMiscLighting => EUT::Lighting,
+ Constants::ObjectTypeMiscFireplace => EUT::Fireplace,
+ Constants::ObjectTypeMiscPoolHeater => EUT::PoolHeater,
+ Constants::ObjectTypeMiscPermanentSpaHeater => EUT::PermanentSpaHeater,
+ Constants::ObjectTypeMechanicalVentilationPreheating => EUT::MechVentPreheat,
+ Constants::ObjectTypeMechanicalVentilationPrecooling => EUT::MechVentPrecool,
+ Constants::ObjectTypeHPDefrostSupplHeat => EUT::HeatingHeatPumpBackup,
+ Constants::ObjectTypePanHeater => EUT::Heating,
+ Constants::ObjectTypeWaterHeaterAdjustment => EUT::HotWater,
+ Constants::ObjectTypeBatteryLossesAdjustment => EUT::Battery }.each do |obj_name, eut|
+ next unless subcategory.start_with? obj_name
+ fail 'Unexpected error: multiple matches.' unless end_use.nil?
+
+ end_use = eut
+ end
+
+ if not end_use.nil?
+ # Use Output:Meter instead of Output:Variable because they incorporate thermal zone multipliers
+ fail "Unexpected error: InteriorEquipment:#{fuel} without a space." unless object.space.is_initialized
+
+ zone_name = object.space.get.thermalZone.get.name.to_s.upcase
+ return { [to_ft[fuel], end_use] => ["#{subcategory}:InteriorEquipment:#{fuel}:Zone:#{zone_name}"] }
+ end
+
+ elsif object.to_ZoneHVACDehumidifierDX.is_initialized
+ return { [FT::Elec, EUT::Dehumidifier] => ['Zone Dehumidifier Electricity Energy'] }
+
+ elsif object.to_EnergyManagementSystemOutputVariable.is_initialized
+ if object_type == Constants::ObjectTypeFanPumpDisaggregatePrimaryHeat
+ return { [FT::Elec, EUT::HeatingFanPump] => [object.name.to_s] }
+ elsif object_type == Constants::ObjectTypeFanPumpDisaggregateBackupHeat
+ return { [FT::Elec, EUT::HeatingHeatPumpBackupFanPump] => [object.name.to_s] }
+ elsif object_type == Constants::ObjectTypeFanPumpDisaggregateCool
+ return { [FT::Elec, EUT::CoolingFanPump] => [object.name.to_s] }
+ else
+ return { ems: [object.name.to_s] }
+ end
+
+ end
+
+ elsif class_type == HWT
+
+ # Hot Water Use
+
+ if object.to_WaterUseEquipment.is_initialized
+ hot_water_use = { Constants::ObjectTypeFixtures => HWT::Fixtures,
+ Constants::ObjectTypeDistributionWaste => HWT::DistributionWaste,
+ Constants::ObjectTypeClothesWasher => HWT::ClothesWasher,
+ Constants::ObjectTypeDishwasher => HWT::Dishwasher }[object.to_WaterUseEquipment.get.waterUseEquipmentDefinition.endUseSubcategory]
+ return { hot_water_use => ['Water Use Equipment Hot Water Volume'] }
+
+ end
+
+ elsif class_type == LT
+
+ # Load
+
+ if object.to_WaterHeaterMixed.is_initialized || object.to_WaterHeaterStratified.is_initialized
+ if object.to_WaterHeaterMixed.is_initialized
+ capacity = object.to_WaterHeaterMixed.get.heaterMaximumCapacity.get
+ object_type = object.to_WaterHeaterMixed.get.additionalProperties.getFeatureAsString('ObjectType')
+ else
+ capacity = object.to_WaterHeaterStratified.get.heater1Capacity.get
+ object_type = object.to_WaterHeaterStratified.get.additionalProperties.getFeatureAsString('ObjectType')
+ end
+ object_type = object_type.get if object_type.is_initialized
+ is_combi_boiler = false
+ if object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').is_initialized
+ is_combi_boiler = object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').get
+ end
+ if capacity == 0 && object_type == Constants::ObjectTypeSolarHotWater
+ return { LT::HotWaterSolarThermal => ['Water Heater Use Side Heat Transfer Energy'] }
+ elsif capacity > 0 || is_combi_boiler # Active water heater only (e.g., exclude desuperheater and solar thermal storage tanks)
+ return { LT::HotWaterTankLosses => ['Water Heater Heat Loss Energy'] }
+ end
+
+ elsif object.to_WaterUseConnections.is_initialized
+ return { LT::HotWaterDelivered => ['Water Use Connections Plant Hot Water Energy'] }
+
+ elsif object.to_CoilWaterHeatingDesuperheater.is_initialized
+ return { LT::HotWaterDesuperheater => ['Water Heater Heating Energy'] }
+
+ elsif object.to_CoilHeatingGas.is_initialized || object.to_CoilHeatingElectric.is_initialized
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { LT::HeatingHeatPumpBackup => ['Heating Coil Heating Energy'] }
+ end
+
+ elsif object.to_ZoneHVACBaseboardConvectiveElectric.is_initialized || object.to_ZoneHVACBaseboardConvectiveWater.is_initialized
+ if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
+ return { LT::HeatingHeatPumpBackup => ['Baseboard Total Heating Energy'] }
+ end
+
+ elsif object.to_EnergyManagementSystemOutputVariable.is_initialized
+ object_type = object.to_EnergyManagementSystemOutputVariable.get.additionalProperties.getFeatureAsString('ObjectType')
+ object_type = object_type.get if object_type.is_initialized
+ if object_type == Constants::ObjectTypeFanPumpDisaggregateBackupHeat
+ # Fan/pump energy is contributing to the load
+ return { LT::HeatingHeatPumpBackup => [object.name.to_s] }
+ end
+
+ end
+
+ elsif class_type == RT
+
+ # Resilience
+
+ if object.to_ElectricLoadCenterStorageLiIonNMCBattery.is_initialized
+ if object.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypeBattery
+ return { RT::Battery => ['Electric Storage Charge Fraction'] }
+ end
+
+ end
+ end
+
+ return {}
+ end
end
diff --git a/ReportSimulationOutput/README.md b/ReportSimulationOutput/README.md
index d103c3e0da..8d4765d2c4 100644
--- a/ReportSimulationOutput/README.md
+++ b/ReportSimulationOutput/README.md
@@ -20,9 +20,11 @@ The file format of the annual (and timeseries, if requested) outputs. If 'csv_dv
- **Required:** ``false``
-- **Choices:** `csv`, `json`, `msgpack`, `csv_dview`
+- **Choices:**
- `csv`
- `json`
- `msgpack`
- `csv_dview`
+
+
+- **Default:** `csv`
-
**Generate Annual Output: Total Consumptions**
@@ -33,7 +35,9 @@ Generates annual energy consumptions for the total building.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Fuel Consumptions**
@@ -44,7 +48,9 @@ Generates annual energy consumptions for each fuel type.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: End Use Consumptions**
@@ -55,7 +61,9 @@ Generates annual energy consumptions for each end use.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: System Use Consumptions**
@@ -66,7 +74,9 @@ Generates annual energy consumptions for each end use of each HVAC and water hea
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Emissions**
@@ -77,7 +87,9 @@ Generates annual emissions. Requires the appropriate HPXML inputs to be specifie
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Emission Fuel Uses**
@@ -88,7 +100,9 @@ Generates annual emissions for each fuel type. Requires the appropriate HPXML in
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Emission End Uses**
@@ -99,7 +113,9 @@ Generates annual emissions for each end use. Requires the appropriate HPXML inpu
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Total Loads**
@@ -110,7 +126,9 @@ Generates annual heating, cooling, and hot water loads.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Unmet Hours**
@@ -121,7 +139,9 @@ Generates annual unmet hours for heating, cooling, and EV driving.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Peak Fuels**
@@ -132,7 +152,9 @@ Generates annual/summer/winter electricity peaks.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Peak Loads**
@@ -143,7 +165,9 @@ Generates annual peak loads for heating/cooling.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Component Loads**
@@ -154,7 +178,9 @@ Generates annual heating and cooling loads disaggregated by component type.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Hot Water Uses**
@@ -165,7 +191,9 @@ Generates annual hot water usages for each end use.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: HVAC Summary**
@@ -176,7 +204,9 @@ Generates HVAC capacities, design temperatures, and design loads.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Annual Output: Resilience**
@@ -187,7 +217,22 @@ Generates annual resilience outputs.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
+
+**Generate Annual Output: By Dwelling Unit**
+
+Generates annual outputs by dwelling unit for whole SFA/MF building simulations.
+
+- **Name:** ``include_annual_dwelling_unit_outputs``
+- **Type:** ``Boolean``
+
+- **Required:** ``false``
+
+
+- **Default:** `true`
+
**Timeseries Reporting Frequency**
@@ -198,9 +243,11 @@ The frequency at which to report timeseries output data. Using 'none' will disab
- **Required:** ``false``
-- **Choices:** `none`, `timestep`, `hourly`, `daily`, `monthly`
+- **Choices:**
- `none`
- `timestep`
- `hourly`
- `daily`
- `monthly`
+
+
+- **Default:** `none`
-
**Generate Timeseries Output: Total Consumptions**
@@ -211,7 +258,9 @@ Generates timeseries energy consumptions for the total building.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Fuel Consumptions**
@@ -222,7 +271,9 @@ Generates timeseries energy consumptions for each fuel type.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: End Use Consumptions**
@@ -233,7 +284,9 @@ Generates timeseries energy consumptions for each end use.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: System Use Consumptions**
@@ -244,7 +297,9 @@ Generates timeseries energy consumptions for each end use of each HVAC and water
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Emissions**
@@ -255,7 +310,9 @@ Generates timeseries emissions. Requires the appropriate HPXML inputs to be spec
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Emission Fuel Uses**
@@ -266,7 +323,9 @@ Generates timeseries emissions for each fuel type. Requires the appropriate HPXM
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Emission End Uses**
@@ -277,7 +336,9 @@ Generates timeseries emissions for each end use. Requires the appropriate HPXML
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Hot Water Uses**
@@ -288,7 +349,9 @@ Generates timeseries hot water usages for each end use.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Total Loads**
@@ -299,7 +362,9 @@ Generates timeseries heating, cooling, and hot water loads.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Component Loads**
@@ -310,7 +375,9 @@ Generates timeseries heating and cooling loads disaggregated by component type.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Unmet Hours**
@@ -321,7 +388,9 @@ Generates timeseries unmet hours for heating, cooling, and EV driving.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Zone Temperatures**
@@ -332,7 +401,9 @@ Generates timeseries temperatures for each thermal zone.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Zone Conditions**
@@ -343,7 +414,9 @@ Generates timeseries temperatures and humidities for each thermal zone.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Airflows**
@@ -354,7 +427,9 @@ Generates timeseries airflows.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Weather**
@@ -365,7 +440,9 @@ Generates timeseries weather data.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Resilience**
@@ -376,7 +453,22 @@ Generates timeseries resilience outputs.
- **Required:** ``false``
-
+
+- **Default:** `false`
+
+
+**Generate Timeseries Output: By Dwelling Unit**
+
+Generates timeseries outputs by dwelling unit for whole SFA/MF building simulations.
+
+- **Name:** ``include_timeseries_dwelling_unit_outputs``
+- **Type:** ``Boolean``
+
+- **Required:** ``false``
+
+
+- **Default:** `false`
+
**Generate Timeseries Output: Timestamp Convention**
@@ -387,9 +479,11 @@ Determines whether timeseries timestamps use the start-of-period or end-of-perio
- **Required:** ``false``
-- **Choices:** `start`, `end`
+- **Choices:**
- `start`
- `end`
+
+
+- **Default:** `start`
-
**Generate Timeseries Output: Number of Decimal Places**
@@ -400,7 +494,7 @@ Allows overriding the default number of decimal places for timeseries outputs.
- **Required:** ``false``
-
+
**Generate Timeseries Output: Add TimeDST Column**
@@ -411,7 +505,9 @@ Optionally add, in addition to the default local standard Time column, a local c
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: Add TimeUTC Column**
@@ -422,7 +518,9 @@ Optionally add, in addition to the default local standard Time column, a local c
- **Required:** ``false``
-
+
+- **Default:** `false`
+
**Generate Timeseries Output: EnergyPlus Output Variables**
@@ -433,7 +531,7 @@ Optionally generates timeseries EnergyPlus output variables. If multiple output
- **Required:** ``false``
-
+
**Generate Timeseries Output: EnergyPlus Output Meters**
@@ -444,7 +542,7 @@ Optionally generates timeseries EnergyPlus output meters. If multiple output met
- **Required:** ``false``
-
+
**Annual Output File Name**
@@ -455,7 +553,7 @@ If not provided, defaults to 'results_annual.csv' (or 'results_annual.json' or '
- **Required:** ``false``
-
+
**Timeseries Output File Name**
@@ -466,7 +564,7 @@ If not provided, defaults to 'results_timeseries.csv' (or 'results_timeseries.js
- **Required:** ``false``
-
+
diff --git a/ReportSimulationOutput/README.md.erb b/ReportSimulationOutput/README.md.erb
index 0e9bc87d3e..2c10598744 100644
--- a/ReportSimulationOutput/README.md.erb
+++ b/ReportSimulationOutput/README.md.erb
@@ -22,9 +22,11 @@
<% end %>
- **Required:** ``<%= argument[:required] %>``
<% if argument[:type] == "Choice" %>
-- **Choices:** `<%= argument[:choice_values].join("`, `") %>`
+- **Choices:**
- `<%= argument[:choice_values].join("`
- `") %>`
+<% end %>
+<% if argument[:default_value] or argument[:default_value] == false %>
+- **Default:** `<%= argument[:default_value] %>`
<% end %>
-
<% end %>
<% if arguments.size == 0 %>
diff --git a/ReportSimulationOutput/measure.rb b/ReportSimulationOutput/measure.rb
index 6a1ba67ea5..119c0fdbbe 100644
--- a/ReportSimulationOutput/measure.rb
+++ b/ReportSimulationOutput/measure.rb
@@ -137,12 +137,19 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg.setDefaultValue(true)
args << arg
+ arg = OpenStudio::Measure::OSArgument.makeBoolArgument('include_annual_dwelling_unit_outputs', false)
+ arg.setDisplayName('Generate Annual Output: By Dwelling Unit')
+ arg.setDescription('Generates annual outputs by dwelling unit for whole SFA/MF building simulations.')
+ arg.setDefaultValue(true)
+ args << arg
+
timeseries_frequency_chs = OpenStudio::StringVector.new
timeseries_frequency_chs << EPlus::TimeseriesFrequencyNone
timeseries_frequency_chs << EPlus::TimeseriesFrequencyTimestep
timeseries_frequency_chs << EPlus::TimeseriesFrequencyHourly
timeseries_frequency_chs << EPlus::TimeseriesFrequencyDaily
timeseries_frequency_chs << EPlus::TimeseriesFrequencyMonthly
+
arg = OpenStudio::Measure::OSArgument.makeChoiceArgument('timeseries_frequency', timeseries_frequency_chs, false)
arg.setDisplayName('Timeseries Reporting Frequency')
arg.setDescription("The frequency at which to report timeseries output data. Using '#{EPlus::TimeseriesFrequencyNone}' will disable timeseries outputs.")
@@ -245,9 +252,16 @@ def arguments(model) # rubocop:disable Lint/UnusedMethodArgument
arg.setDefaultValue(false)
args << arg
+ arg = OpenStudio::Measure::OSArgument.makeBoolArgument('include_timeseries_dwelling_unit_outputs', false)
+ arg.setDisplayName('Generate Timeseries Output: By Dwelling Unit')
+ arg.setDescription('Generates timeseries outputs by dwelling unit for whole SFA/MF building simulations.')
+ arg.setDefaultValue(false)
+ args << arg
+
timestamp_chs = OpenStudio::StringVector.new
timestamp_chs << 'start'
timestamp_chs << 'end'
+
arg = OpenStudio::Measure::OSArgument.makeChoiceArgument('timeseries_timestamp_convention', timestamp_chs, false)
arg.setDisplayName('Generate Timeseries Output: Timestamp Convention')
arg.setDescription("Determines whether timeseries timestamps use the start-of-period or end-of-period convention. Doesn't apply if the output format is 'csv_dview'.")
@@ -383,6 +397,7 @@ def modelOutputRequests(model, runner, user_arguments)
end
# Fuel outputs
+ hpxml_bldgs_size = @model.getBuilding.additionalProperties.getFeatureAsInteger('hpxml_bldgs_size').get
@fuels.each do |(_fuel_type, _total_or_net), fuel|
next if fuel.meter.nil?
@@ -390,6 +405,15 @@ def modelOutputRequests(model, runner, user_arguments)
if args[:include_timeseries_fuel_consumptions]
Model.add_output_meter(model, meter_name: fuel.meter, reporting_frequency: args[:timeseries_frequency])
end
+
+ next unless hpxml_bldgs_size > 1
+
+ (1..hpxml_bldgs_size).each do |unit_num|
+ Model.add_output_meter(model, meter_name: "unit#{unit_num}_#{fuel.meter.gsub(':', '_')}", reporting_frequency: 'runperiod')
+ if args[:include_timeseries_fuel_consumptions] && args[:include_timeseries_dwelling_unit_outputs]
+ Model.add_output_meter(model, meter_name: "unit#{unit_num}_#{fuel.meter.gsub(':', '_')}", reporting_frequency: args[:timeseries_frequency])
+ end
+ end
end
if has_electricity_production || has_electricity_storage
@@ -782,9 +806,21 @@ def get_outputs(runner, args)
# Fuel Uses
@fuels.each do |(_fuel_type, _total_or_net), fuel|
fuel.annual_output = get_report_meter_data_annual([fuel.meter])
- next unless args[:include_timeseries_fuel_consumptions]
- fuel.timeseries_output = get_report_meter_data_timeseries([fuel.meter], UnitConversions.convert(1.0, 'J', fuel.timeseries_units), 0, args[:timeseries_frequency])
+ if args[:include_timeseries_fuel_consumptions]
+ fuel.timeseries_output = get_report_meter_data_timeseries([fuel.meter], UnitConversions.convert(1.0, 'J', fuel.timeseries_units), 0, args[:timeseries_frequency])
+ end
+
+ next unless @hpxml_bldgs.size > 1
+
+ @hpxml_bldgs.each do |hpxml_bldg|
+ unit_num = @hpxml_bldgs.index(hpxml_bldg) + 1
+ fuel_meter = fuel.meter.nil? ? nil : fuel.meter.gsub(':', '_')
+ fuel.annual_output_by_unit[hpxml_bldg.building_id] = get_report_meter_data_annual(["unit#{unit_num}_#{fuel_meter}".upcase])
+ if args[:include_timeseries_fuel_consumptions] && args[:include_timeseries_dwelling_unit_outputs]
+ fuel.timeseries_output_by_unit[hpxml_bldg.building_id] = get_report_meter_data_timeseries(["unit#{unit_num}_#{fuel_meter}".upcase], UnitConversions.convert(1.0, 'J', fuel.timeseries_units), 0, args[:timeseries_frequency])
+ end
+ end
end
# Peak Electricity Consumption
@@ -923,7 +959,7 @@ def get_outputs(runner, args)
next if end_use.annual_output_by_system[htg_system.id].nil?
fuels = @fuels.select { |k, _v| k[0] == fuel_type }.values
- apply_multiplier_to_output(end_use, fuels, htg_system.id, 1.0 / dse)
+ apply_multiplier_to_output(end_use, fuels, htg_system.id, hpxml_bldg.building_id, 1.0 / dse)
end
end
end
@@ -941,7 +977,7 @@ def get_outputs(runner, args)
next if end_use.annual_output_by_system[clg_system.id].nil?
fuels = @fuels.select { |k, _v| k[0] == fuel_type }.values
- apply_multiplier_to_output(end_use, fuels, clg_system.id, 1.0 / dse)
+ apply_multiplier_to_output(end_use, fuels, clg_system.id, hpxml_bldg.building_id, 1.0 / dse)
end
end
end
@@ -959,7 +995,7 @@ def get_outputs(runner, args)
dhw_ids = hpxml_bldg.water_heating_systems.map { |dhw| dhw.id }
end
dhw_ids.each do |dhw_id|
- apply_multiplier_to_output(@loads[LT::HotWaterDelivered], [@loads[LT::HotWaterSolarThermal]], dhw_id, 1.0 / (1.0 - solar_system.solar_fraction))
+ apply_multiplier_to_output(@loads[LT::HotWaterDelivered], [@loads[LT::HotWaterSolarThermal]], dhw_id, nil, 1.0 / (1.0 - solar_system.solar_fraction))
end
end
end
@@ -1023,12 +1059,28 @@ def get_outputs(runner, args)
te_types.each do |te_type|
@totals[te_type].annual_output += fuel.annual_output
end
- next unless args[:include_timeseries_total_consumptions] && fuel.timeseries_output.sum != 0.0
+ if args[:include_timeseries_total_consumptions] && fuel.timeseries_output.sum != 0.0
+ te_types.each do |te_type|
+ @totals[te_type].timeseries_output = [0.0] * @timestamps.size if @totals[te_type].timeseries_output.empty?
+ unit_conv = UnitConversions.convert(1.0, fuel.timeseries_units, @totals[te_type].timeseries_units)
+ @totals[te_type].timeseries_output = @totals[te_type].timeseries_output.zip(fuel.timeseries_output).map { |x, y| x + y * unit_conv }
+ end
+ end
- te_types.each do |te_type|
- @totals[te_type].timeseries_output = [0.0] * @timestamps.size if @totals[te_type].timeseries_output.empty?
- unit_conv = UnitConversions.convert(1.0, fuel.timeseries_units, @totals[te_type].timeseries_units)
- @totals[te_type].timeseries_output = @totals[te_type].timeseries_output.zip(fuel.timeseries_output).map { |x, y| x + y * unit_conv }
+ next unless @hpxml_bldgs.size > 1
+
+ @hpxml_bldgs.each do |hpxml_bldg|
+ te_types.each do |te_type|
+ @totals[te_type].annual_output_by_unit[hpxml_bldg.building_id] = 0.0 unless @totals[te_type].annual_output_by_unit.keys.include?(hpxml_bldg.building_id)
+ @totals[te_type].annual_output_by_unit[hpxml_bldg.building_id] += fuel.annual_output_by_unit[hpxml_bldg.building_id]
+ end
+ next unless args[:include_timeseries_total_consumptions] && fuel.timeseries_output.sum != 0.0 && args[:include_timeseries_dwelling_unit_outputs]
+
+ te_types.each do |te_type|
+ @totals[te_type].timeseries_output_by_unit[hpxml_bldg.building_id] = [0.0] * @timestamps.size unless @totals[te_type].timeseries_output_by_unit.keys.include?(hpxml_bldg.building_id)
+ unit_conv = UnitConversions.convert(1.0, fuel.timeseries_units, @totals[te_type].timeseries_units)
+ @totals[te_type].timeseries_output_by_unit[hpxml_bldg.building_id] = @totals[te_type].timeseries_output_by_unit[hpxml_bldg.building_id].zip(fuel.timeseries_output_by_unit[hpxml_bldg.building_id]).map { |x, y| x + y * unit_conv }
+ end
end
end
@@ -1535,6 +1587,29 @@ def check_for_errors(runner)
end
end
+ # Check sum of custom unit meters match facility
+ if @hpxml_bldgs.size > 1
+ @totals.each do |energy_type, total_energy|
+ total_meter = total_energy.annual_output
+ sum_meters = total_energy.annual_output_by_unit.values.sum
+
+ if (sum_meters - total_meter).abs > tol
+ runner.registerError("Sum of Dwelling Unit Energy Use: *: #{energy_type} (#{sum_meters.round(3)}) does not equal Energy Use: #{energy_type} (#{total_meter.round(3)}).")
+ return false
+ end
+ end
+
+ @fuels.each do |(fuel_type, total_or_net), fuel|
+ total_meter = fuel.annual_output
+ sum_meters = fuel.annual_output_by_unit.values.sum
+
+ if (sum_meters - total_meter).abs > tol
+ runner.registerError("Sum of Dwelling Unit Fuel Use: *: #{fuel_type}: #{total_or_net} (#{sum_meters.round(3)}) does not equal Fuel Use: #{fuel_type}: #{total_or_net} (#{total_meter.round(3)}).")
+ return false
+ end
+ end
+ end
+
return true
end
@@ -1690,6 +1765,30 @@ def report_runperiod_output_results(runner, args, annual_output_path)
# Sizing data
if args[:include_annual_hvac_summary]
results_out = Outputs.append_sizing_results(@hpxml_bldgs, results_out)
+ results_out << [line_break]
+ end
+
+ # By dwelling unit
+ if args[:include_annual_dwelling_unit_outputs] && (@hpxml_bldgs.size > 1)
+ # Totals
+ if args[:include_annual_total_consumptions]
+ @totals.each do |energy_type, total_energy|
+ total_energy.annual_output_by_unit.each do |unit_id, annual_output|
+ results_out << ["Dwelling Unit Energy Use: #{unit_id}: #{energy_type} (#{total_energy.annual_units})", annual_output.to_f.round(n_digits)]
+ end
+ end
+ results_out << [line_break]
+ end
+
+ # Fuels
+ if args[:include_annual_fuel_consumptions]
+ @fuels.each do |(fuel_type, total_or_net), fuel|
+ fuel.annual_output_by_unit.each do |unit_id, annual_output|
+ results_out << ["Dwelling Unit Fuel Use: #{unit_id}: #{fuel_type}: #{total_or_net} (#{fuel.annual_units})", annual_output.to_f.round(n_digits)]
+ end
+ end
+ end
+ results_out << [line_break]
end
# Check for duplicate results
@@ -1749,6 +1848,7 @@ def report_timeseries_output_results(runner, timeseries_output_path, args)
hot_water_use_data, total_loads_data, comp_loads_data, unmet_hours_data = [], [], [], []
zone_temps_data, zone_conds_data, airflows_data, weather_data, resilience_data = [], [], [], [], []
output_variables_data, output_meters_data = [], []
+ unit_total_energy_data, unit_fuel_data = [], []
# Totals
if args[:include_timeseries_total_consumptions]
@@ -1864,9 +1964,35 @@ def report_timeseries_output_results(runner, timeseries_output_path, args)
output_meters_data = @output_meters.values.map { |x| [x.name, x.timeseries_units] + x.timeseries_output }
end
+ # By dwelling unit
+ if args[:include_timeseries_dwelling_unit_outputs] && (@hpxml_bldgs.size > 1)
+ # Totals
+ if args[:include_timeseries_total_consumptions]
+ [TE::Total, TE::Net].each do |energy_type|
+ @totals[energy_type].timeseries_output_by_unit.each do |unit_id, timeseries_output|
+ next if timeseries_output.empty?
+
+ unit_total_energy_data << ["Dwelling Unit Energy Use: #{unit_id}: #{energy_type}", @totals[energy_type].timeseries_units] + timeseries_output.map { |v| v.round(n_digits) }
+ end
+ end
+ end
+
+ # Fuels
+ if args[:include_timeseries_fuel_consumptions]
+ @fuels.each do |(fuel_type, total_or_net), fuel|
+ fuel.timeseries_output_by_unit.each do |unit_id, timeseries_output|
+ next if timeseries_output.sum(0.0) == 0
+
+ unit_fuel_data << ["Dwelling Unit Fuel Use: #{unit_id}: #{fuel_type}: #{total_or_net}", fuel.timeseries_units] + timeseries_output.map { |v| v.round(n_digits) }
+ end
+ end
+ end
+ end
+
return if (total_energy_data.size + fuel_data.size + end_use_data.size + system_use_data.size + emissions_data.size + emission_fuel_data.size +
emission_end_use_data.size + hot_water_use_data.size + total_loads_data.size + comp_loads_data.size + unmet_hours_data.size +
- zone_temps_data.size + zone_conds_data.size + airflows_data.size + weather_data.size + resilience_data.size + output_variables_data.size + output_meters_data.size) == 0
+ zone_temps_data.size + zone_conds_data.size + airflows_data.size + weather_data.size + resilience_data.size + output_variables_data.size + output_meters_data.size +
+ unit_total_energy_data.size + unit_fuel_data.size) == 0
fail 'Unable to obtain timestamps.' if @timestamps.empty?
@@ -1874,7 +2000,8 @@ def report_timeseries_output_results(runner, timeseries_output_path, args)
# Assemble data
data = data.zip(*timestamps2, *timestamps3, *total_energy_data, *fuel_data, *end_use_data, *system_use_data, *emissions_data,
*emission_fuel_data, *emission_end_use_data, *hot_water_use_data, *total_loads_data, *comp_loads_data, *unmet_hours_data,
- *zone_temps_data, *zone_conds_data, *airflows_data, *weather_data, *resilience_data, *output_variables_data, *output_meters_data)
+ *zone_temps_data, *zone_conds_data, *airflows_data, *weather_data, *resilience_data, *output_variables_data, *output_meters_data,
+ *unit_total_energy_data, *unit_fuel_data)
# Error-check
n_elements = []
@@ -1945,7 +2072,8 @@ def report_timeseries_output_results(runner, timeseries_output_path, args)
[total_energy_data, fuel_data, end_use_data, system_use_data, emissions_data, emission_fuel_data,
emission_end_use_data, hot_water_use_data, total_loads_data, comp_loads_data, unmet_hours_data,
- zone_temps_data, zone_conds_data, airflows_data, weather_data, resilience_data, output_variables_data, output_meters_data].each do |d|
+ zone_temps_data, zone_conds_data, airflows_data, weather_data, resilience_data, output_variables_data, output_meters_data,
+ unit_total_energy_data, unit_fuel_data].each do |d|
d.each do |o|
grp, name = o[0].split(':', 2)
h[grp] = {} if h[grp].nil?
@@ -2256,14 +2384,18 @@ def get_tabular_data_value(report_name, report_for_string, table_name, row_names
# @param obj [EndUse or Load] The output object of interest
# @param sync_objs [Fuel or Load] Additional outputs that need to be kept in sync
# @param sys_id [String] The related HPXML object's System Identifier
+ # @param building_id [String or nil] HPXML Building ID
# @param mult [Double] The multiplier value to apply
# @return [nil]
- def apply_multiplier_to_output(obj, sync_objs, sys_id, mult)
+ def apply_multiplier_to_output(obj, sync_objs, sys_id, building_id, mult)
# Annual
orig_value = obj.annual_output_by_system[sys_id]
obj.annual_output_by_system[sys_id] = orig_value * mult
sync_objs.each do |sync_obj|
sync_obj.annual_output += (orig_value * mult - orig_value)
+ if (not building_id.nil?) && sync_obj.annual_output_by_unit.keys.include?(building_id)
+ sync_obj.annual_output_by_unit[building_id] += (orig_value * mult - orig_value) unless building_id.nil?
+ end
end
# Timeseries
@@ -2296,7 +2428,7 @@ def create_all_object_outputs_by_key
next if object.to_AdditionalProperties.is_initialized
[EUT, HWT, LT, RT].each do |class_type|
- vars_by_key = get_object_outputs_by_key(@model, object, class_type)
+ vars_by_key = Outputs.get_object_outputs_by_key(@model, object, class_type)
next if vars_by_key.size == 0
sys_id = object.additionalProperties.getFeatureAsString('HPXML_ID')
@@ -2337,8 +2469,10 @@ def get_object_outputs(class_type, key)
class BaseOutput
def initialize()
@timeseries_output = []
+ @annual_output_by_unit = {}
+ @timeseries_output_by_unit = {}
end
- attr_accessor(:name, :annual_output, :timeseries_output, :annual_units, :timeseries_units)
+ attr_accessor(:name, :annual_output, :annual_output_by_unit, :timeseries_output, :timeseries_output_by_unit, :annual_units, :timeseries_units)
end
# Structure to store EnergyPlus total (and net) energy outputs.
@@ -2901,319 +3035,6 @@ def get_hpxml_system_ids
end
return system_ids
end
-
- # For a given object, returns the Output:Variables or Output:Meters to be requested,
- # and associates them with the appropriate keys (e.g., [FT::Elec, EUT::Heating]).
- #
- # @param model [OpenStudio::Model::Model] OpenStudio Model object
- # @param object [OpenStudio::Model::Foo] A given object in the OpenStudio Model
- # @param class_type [Module] The output class type
- # @return [Hash] Map of output key => array of EnergyPlus output variable/meter names
- def get_object_outputs_by_key(model, object, class_type)
- object_type = object.additionalProperties.getFeatureAsString('ObjectType')
- object_type = object_type.get if object_type.is_initialized
-
- to_ft = { EPlus::FuelTypeElectricity => FT::Elec,
- EPlus::FuelTypeNaturalGas => FT::Gas,
- EPlus::FuelTypeOil => FT::Oil,
- EPlus::FuelTypePropane => FT::Propane,
- EPlus::FuelTypeWoodCord => FT::WoodCord,
- EPlus::FuelTypeWoodPellets => FT::WoodPellets,
- EPlus::FuelTypeCoal => FT::Coal }
-
- if class_type == EUT
-
- # End uses
-
- if object.to_CoilHeatingDXSingleSpeed.is_initialized || object.to_CoilHeatingDXMultiSpeed.is_initialized
- vars = { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy', 'Heating Coil Defrost Electricity Energy'] }
- if object.additionalProperties.getFeatureAsDouble('FractionHeatLoadServed').is_initialized && object.additionalProperties.getFeatureAsDouble('FractionHeatLoadServed').get <= 0
- # HP only provides cooling, allocate crankcase to cooling end use
- vars[[FT::Elec, EUT::Cooling]] = ['Heating Coil Crankcase Heater Electricity Energy']
- else
- # Allocate crankcase to heating end use
- vars[[FT::Elec, EUT::Heating]] << 'Heating Coil Crankcase Heater Electricity Energy'
- end
- return vars
-
- elsif object.to_CoilHeatingElectric.is_initialized || object.to_CoilHeatingElectricMultiStage.is_initialized
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { [FT::Elec, EUT::HeatingHeatPumpBackup] => ['Heating Coil Electricity Energy'] }
- else
- return { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy'] }
- end
-
- elsif object.to_CoilHeatingGas.is_initialized
- fuel = object.to_CoilHeatingGas.get.fuelType
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { [to_ft[fuel], EUT::HeatingHeatPumpBackup] => ["Heating Coil #{fuel} Energy", "Heating Coil Ancillary #{fuel} Energy"] }
- else
- return { [to_ft[fuel], EUT::Heating] => ["Heating Coil #{fuel} Energy", "Heating Coil Ancillary #{fuel} Energy"] }
- end
-
- elsif object.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilHeatingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
- return { [FT::Elec, EUT::Heating] => ['Heating Coil Electricity Energy'] }
-
- elsif object.to_ZoneHVACBaseboardConvectiveElectric.is_initialized
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { [FT::Elec, EUT::HeatingHeatPumpBackup] => ['Baseboard Electricity Energy'] }
- else
- return { [FT::Elec, EUT::Heating] => ['Baseboard Electricity Energy'] }
- end
-
- elsif object.to_BoilerHotWater.is_initialized
- is_combi_boiler = false
- if object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').is_initialized
- is_combi_boiler = object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').get
- end
- if not is_combi_boiler # Exclude combi boiler, whose heating & dhw energy is handled separately via EMS
- fuel = object.to_BoilerHotWater.get.fuelType
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { [to_ft[fuel], EUT::HeatingHeatPumpBackup] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
- else
- return { [to_ft[fuel], EUT::Heating] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
- end
- else
- fuel = object.to_BoilerHotWater.get.fuelType
- return { [to_ft[fuel], EUT::HotWater] => ["Boiler #{fuel} Energy", "Boiler Ancillary #{fuel} Energy"] }
- end
-
- elsif object.to_CoilCoolingDXSingleSpeed.is_initialized || object.to_CoilCoolingDXMultiSpeed.is_initialized
- vars = { [FT::Elec, EUT::Cooling] => ['Cooling Coil Electricity Energy'] }
- parent = model.getAirLoopHVACUnitarySystems.select { |u| u.coolingCoil.is_initialized && u.coolingCoil.get.handle.to_s == object.handle.to_s }
- if (not parent.empty?) && parent[0].heatingCoil.is_initialized
- htg_coil = parent[0].heatingCoil.get
- end
- if parent.empty?
- parent = model.getZoneHVACPackagedTerminalAirConditioners.select { |u| u.coolingCoil.handle.to_s == object.handle.to_s }
- if not parent.empty?
- htg_coil = parent[0].heatingCoil
- end
- end
- if parent.empty?
- fail 'Could not find parent object.'
- end
-
- if htg_coil.nil? || (not (htg_coil.to_CoilHeatingDXSingleSpeed.is_initialized || htg_coil.to_CoilHeatingDXMultiSpeed.is_initialized))
- # Crankcase variable only available if no DX heating coil on parent
- vars[[FT::Elec, EUT::Cooling]] << 'Cooling Coil Crankcase Heater Electricity Energy'
- end
- return vars
-
- elsif object.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized || object.to_CoilCoolingWaterToAirHeatPumpVariableSpeedEquationFit.is_initialized
- return { [FT::Elec, EUT::Cooling] => ['Cooling Coil Electricity Energy'] }
-
- elsif object.to_EvaporativeCoolerDirectResearchSpecial.is_initialized
- return { [FT::Elec, EUT::Cooling] => ['Evaporative Cooler Electricity Energy'] }
-
- elsif object.to_CoilWaterHeatingAirToWaterHeatPumpWrapped.is_initialized
- return { [FT::Elec, EUT::HotWater] => ['Cooling Coil Water Heating Electricity Energy'] }
-
- elsif object.to_FanSystemModel.is_initialized
- if object_type == Constants::ObjectTypeWaterHeater
- return { [FT::Elec, EUT::HotWater] => ['Fan Electricity Energy'] }
- end
-
- elsif object.to_PumpConstantSpeed.is_initialized
- if object_type == Constants::ObjectTypeSolarHotWater
- return { [FT::Elec, EUT::HotWaterSolarThermalPump] => ['Pump Electricity Energy'] }
- end
-
- elsif object.to_WaterHeaterMixed.is_initialized
- fuel = object.to_WaterHeaterMixed.get.heaterFuelType
- return { [to_ft[fuel], EUT::HotWater] => ["Water Heater #{fuel} Energy", 'Water Heater Off Cycle Parasitic Electricity Energy', 'Water Heater On Cycle Parasitic Electricity Energy'] }
-
- elsif object.to_WaterHeaterStratified.is_initialized
- fuel = object.to_WaterHeaterStratified.get.heaterFuelType
- return { [to_ft[fuel], EUT::HotWater] => ["Water Heater #{fuel} Energy", 'Water Heater Off Cycle Parasitic Electricity Energy', 'Water Heater On Cycle Parasitic Electricity Energy'] }
-
- elsif object.to_Lights.is_initialized
- object = object.to_Lights.get
- subcategory = object.endUseSubcategory
- end_use = { Constants::ObjectTypeLightingInterior => EUT::LightsInterior,
- Constants::ObjectTypeLightingGarage => EUT::LightsGarage }[subcategory]
- fail 'Unexpected error: InteriorLights:Electricity without a space.' unless object.space.is_initialized
-
- zone_name = object.space.get.thermalZone.get.name.to_s.upcase
- return { [FT::Elec, end_use] => ["#{subcategory}:InteriorLights:Electricity:Zone:#{zone_name}"] }
-
- elsif object.to_ElectricLoadCenterInverterPVWatts.is_initialized
- return { [FT::Elec, EUT::PV] => ['Inverter Conversion Loss Decrement Energy'] }
-
- elsif object.to_GeneratorPVWatts.is_initialized
- return { [FT::Elec, EUT::PV] => ['Generator Produced DC Electricity Energy'] }
-
- elsif object.to_GeneratorMicroTurbine.is_initialized
- fuel = object.to_GeneratorMicroTurbine.get.fuelType
- return { [FT::Elec, EUT::Generator] => ['Generator Produced AC Electricity Energy'],
- [to_ft[fuel], EUT::Generator] => ["Generator #{fuel} HHV Basis Energy"] }
-
- elsif object.to_ElectricLoadCenterStorageLiIonNMCBattery.is_initialized
- if object.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypeVehicle
- return { [FT::Elec, EUT::Vehicle] => ['Electric Storage Charge Energy'] }
- elsif object.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypeBattery
- return { [FT::Elec, EUT::Battery] => ['Electric Storage Production Decrement Energy', 'Electric Storage Discharge Energy'] }
- else
- fail "Unexpected elcs: #{object.name}"
- end
-
- elsif object.to_ElectricEquipment.is_initialized
- object = object.to_ElectricEquipment.get
- subcategory = object.endUseSubcategory
- end_use = nil
- { Constants::ObjectTypeHotWaterRecircPump => EUT::HotWaterRecircPump,
- Constants::ObjectTypeClothesWasher => EUT::ClothesWasher,
- Constants::ObjectTypeClothesDryer => EUT::ClothesDryer,
- Constants::ObjectTypeDishwasher => EUT::Dishwasher,
- Constants::ObjectTypeRefrigerator => EUT::Refrigerator,
- Constants::ObjectTypeFreezer => EUT::Freezer,
- Constants::ObjectTypeCookingRange => EUT::RangeOven,
- Constants::ObjectTypeCeilingFan => EUT::CeilingFan,
- Constants::ObjectTypeWholeHouseFan => EUT::WholeHouseFan,
- Constants::ObjectTypeMechanicalVentilation => EUT::MechVent,
- Constants::ObjectTypeMiscPlugLoads => EUT::PlugLoads,
- Constants::ObjectTypeMiscTelevision => EUT::Television,
- Constants::ObjectTypeMiscPoolHeater => EUT::PoolHeater,
- Constants::ObjectTypeMiscPoolPump => EUT::PoolPump,
- Constants::ObjectTypeMiscPermanentSpaHeater => EUT::PermanentSpaHeater,
- Constants::ObjectTypeMiscPermanentSpaPump => EUT::PermanentSpaPump,
- Constants::ObjectTypeMiscElectricVehicleCharging => EUT::Vehicle,
- Constants::ObjectTypeMiscWellPump => EUT::WellPump,
- Constants::ObjectTypeLightingExterior => EUT::LightsExterior,
- Constants::ObjectTypeLightingExteriorHoliday => EUT::LightsExterior }.each do |obj_name, eut|
- next unless subcategory.start_with? obj_name
- fail 'Unexpected error: multiple matches.' unless end_use.nil?
-
- end_use = eut
- end
-
- if not end_use.nil?
- # Use Output:Meter instead of Output:Variable because they incorporate thermal zone multipliers
- fail 'Unexpected error: InteriorEquipment:Electricity without a space.' unless object.space.is_initialized
-
- zone_name = object.space.get.thermalZone.get.name.to_s.upcase
- return { [FT::Elec, end_use] => ["#{subcategory}:InteriorEquipment:Electricity:Zone:#{zone_name}"] }
- end
-
- elsif object.to_OtherEquipment.is_initialized
- object = object.to_OtherEquipment.get
- subcategory = object.endUseSubcategory
- fuel = object.fuelType
- end_use = nil
- { Constants::ObjectTypeClothesDryer => EUT::ClothesDryer,
- Constants::ObjectTypeCookingRange => EUT::RangeOven,
- Constants::ObjectTypeMiscGrill => EUT::Grill,
- Constants::ObjectTypeMiscLighting => EUT::Lighting,
- Constants::ObjectTypeMiscFireplace => EUT::Fireplace,
- Constants::ObjectTypeMiscPoolHeater => EUT::PoolHeater,
- Constants::ObjectTypeMiscPermanentSpaHeater => EUT::PermanentSpaHeater,
- Constants::ObjectTypeMechanicalVentilationPreheating => EUT::MechVentPreheat,
- Constants::ObjectTypeMechanicalVentilationPrecooling => EUT::MechVentPrecool,
- Constants::ObjectTypeHPDefrostSupplHeat => EUT::HeatingHeatPumpBackup,
- Constants::ObjectTypePanHeater => EUT::Heating,
- Constants::ObjectTypeWaterHeaterAdjustment => EUT::HotWater,
- Constants::ObjectTypeBatteryLossesAdjustment => EUT::Battery }.each do |obj_name, eut|
- next unless subcategory.start_with? obj_name
- fail 'Unexpected error: multiple matches.' unless end_use.nil?
-
- end_use = eut
- end
-
- if not end_use.nil?
- # Use Output:Meter instead of Output:Variable because they incorporate thermal zone multipliers
- fail "Unexpected error: InteriorEquipment:#{fuel} without a space." unless object.space.is_initialized
-
- zone_name = object.space.get.thermalZone.get.name.to_s.upcase
- return { [to_ft[fuel], end_use] => ["#{subcategory}:InteriorEquipment:#{fuel}:Zone:#{zone_name}"] }
- end
-
- elsif object.to_ZoneHVACDehumidifierDX.is_initialized
- return { [FT::Elec, EUT::Dehumidifier] => ['Zone Dehumidifier Electricity Energy'] }
-
- elsif object.to_EnergyManagementSystemOutputVariable.is_initialized
- if object_type == Constants::ObjectTypeFanPumpDisaggregatePrimaryHeat
- return { [FT::Elec, EUT::HeatingFanPump] => [object.name.to_s] }
- elsif object_type == Constants::ObjectTypeFanPumpDisaggregateBackupHeat
- return { [FT::Elec, EUT::HeatingHeatPumpBackupFanPump] => [object.name.to_s] }
- elsif object_type == Constants::ObjectTypeFanPumpDisaggregateCool
- return { [FT::Elec, EUT::CoolingFanPump] => [object.name.to_s] }
- else
- return { ems: [object.name.to_s] }
- end
-
- end
-
- elsif class_type == HWT
-
- # Hot Water Use
-
- if object.to_WaterUseEquipment.is_initialized
- hot_water_use = { Constants::ObjectTypeFixtures => HWT::Fixtures,
- Constants::ObjectTypeDistributionWaste => HWT::DistributionWaste,
- Constants::ObjectTypeClothesWasher => HWT::ClothesWasher,
- Constants::ObjectTypeDishwasher => HWT::Dishwasher }[object.to_WaterUseEquipment.get.waterUseEquipmentDefinition.endUseSubcategory]
- return { hot_water_use => ['Water Use Equipment Hot Water Volume'] }
-
- end
-
- elsif class_type == LT
-
- # Load
-
- if object.to_WaterHeaterMixed.is_initialized || object.to_WaterHeaterStratified.is_initialized
- if object.to_WaterHeaterMixed.is_initialized
- capacity = object.to_WaterHeaterMixed.get.heaterMaximumCapacity.get
- else
- capacity = object.to_WaterHeaterStratified.get.heater1Capacity.get
- end
- is_combi_boiler = false
- if object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').is_initialized
- is_combi_boiler = object.additionalProperties.getFeatureAsBoolean('IsCombiBoiler').get
- end
- if capacity == 0 && object_type == Constants::ObjectTypeSolarHotWater
- return { LT::HotWaterSolarThermal => ['Water Heater Use Side Heat Transfer Energy'] }
- elsif capacity > 0 || is_combi_boiler # Active water heater only (e.g., exclude desuperheater and solar thermal storage tanks)
- return { LT::HotWaterTankLosses => ['Water Heater Heat Loss Energy'] }
- end
-
- elsif object.to_WaterUseConnections.is_initialized
- return { LT::HotWaterDelivered => ['Water Use Connections Plant Hot Water Energy'] }
-
- elsif object.to_CoilWaterHeatingDesuperheater.is_initialized
- return { LT::HotWaterDesuperheater => ['Water Heater Heating Energy'] }
-
- elsif object.to_CoilHeatingGas.is_initialized || object.to_CoilHeatingElectric.is_initialized
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { LT::HeatingHeatPumpBackup => ['Heating Coil Heating Energy'] }
- end
-
- elsif object.to_ZoneHVACBaseboardConvectiveElectric.is_initialized || object.to_ZoneHVACBaseboardConvectiveWater.is_initialized
- if object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').is_initialized && object.additionalProperties.getFeatureAsBoolean('IsHeatPumpBackup').get
- return { LT::HeatingHeatPumpBackup => ['Baseboard Total Heating Energy'] }
- end
-
- elsif object.to_EnergyManagementSystemOutputVariable.is_initialized
- if object_type == Constants::ObjectTypeFanPumpDisaggregateBackupHeat
- # Fan/pump energy is contributing to the load
- return { LT::HeatingHeatPumpBackup => [object.name.to_s] }
- end
-
- end
-
- elsif class_type == RT
-
- # Resilience
-
- if object.to_ElectricLoadCenterStorageLiIonNMCBattery.is_initialized
- if object.additionalProperties.getFeatureAsString('ObjectType').to_s == Constants::ObjectTypeBattery
- return { RT::Battery => ['Electric Storage Charge Fraction'] }
- end
-
- end
- end
-
- return {}
- end
end
# register the measure to be used by the application
diff --git a/ReportSimulationOutput/measure.xml b/ReportSimulationOutput/measure.xml
index e33aaf9ac3..89224d7cde 100644
--- a/ReportSimulationOutput/measure.xml
+++ b/ReportSimulationOutput/measure.xml
@@ -3,8 +3,8 @@
3.1
report_simulation_output
df9d170c-c21a-4130-866d-0d46b06073fd
- 6fd7c052-cf6c-4e9a-ab39-130c58f76864
- 2026-02-16T17:51:26Z
+ 25e2be37-47bd-4140-9bea-7380d68d9b5b
+ 2026-02-16T17:53:24Z
9BF1E6AC
ReportSimulationOutput
HPXML Simulation Output Report
@@ -323,6 +323,25 @@
+
+ include_annual_dwelling_unit_outputs
+ Generate Annual Output: By Dwelling Unit
+ Generates annual outputs by dwelling unit for whole SFA/MF building simulations.
+ Boolean
+ false
+ false
+ true
+
+
+ true
+ true
+
+
+ false
+ false
+
+
+
timeseries_frequency
Timeseries Reporting Frequency
@@ -658,6 +677,25 @@
+
+ include_timeseries_dwelling_unit_outputs
+ Generate Timeseries Output: By Dwelling Unit
+ Generates timeseries outputs by dwelling unit for whole SFA/MF building simulations.
+ Boolean
+ false
+ false
+ false
+
+
+ true
+ true
+
+
+ false
+ false
+
+
+
timeseries_timestamp_convention
Generate Timeseries Output: Timestamp Convention
@@ -1974,13 +2012,13 @@
README.md
md
readme
- D0A0BB5E
+ F13F5EA4
README.md.erb
erb
readmeerb
- 513F28E9
+ 5238CEA2
@@ -1991,13 +2029,13 @@
measure.rb
rb
script
- 96158F61
+ BD5D6405
test_report_sim_output.rb
rb
test
- D953D5A4
+ 833AF682
diff --git a/ReportSimulationOutput/tests/test_report_sim_output.rb b/ReportSimulationOutput/tests/test_report_sim_output.rb
index 9ec429271e..3cb7909122 100644
--- a/ReportSimulationOutput/tests/test_report_sim_output.rb
+++ b/ReportSimulationOutput/tests/test_report_sim_output.rb
@@ -601,7 +601,33 @@ def emission_end_uses_timeseries_cols
return cols
end
- def pv_battery_timeseries_cols
+ def whole_building_unit_ids
+ return ['MyBuilding',
+ 'MyBuilding_2',
+ 'MyBuilding_3',
+ 'MyBuilding_4',
+ 'MyBuilding_5',
+ 'MyBuilding_6']
+ end
+
+ def dwelling_unit_annual_cols
+ cols = []
+ whole_building_unit_ids.each do |unit_id|
+ cols.concat(["Dwelling Unit Energy Use: #{unit_id}: #{TE::Total} (MBtu)",
+ "Dwelling Unit Energy Use: #{unit_id}: #{TE::Net} (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Elec}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Elec}: Net (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Gas}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Oil}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Propane}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::WoodCord}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::WoodPellets}: Total (MBtu)",
+ "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Coal}: Total (MBtu)"])
+ end
+ return cols
+ end
+
+ def pv_battery_vehicle_timeseries_cols
return ["End Use: #{FT::Elec}: #{EUT::PV}",
"End Use: #{FT::Elec}: #{EUT::Battery}",
"End Use: #{FT::Elec}: #{EUT::Vehicle}"]
@@ -627,7 +653,8 @@ def test_annual_only
'include_timeseries_zone_conditions' => false,
'include_timeseries_airflows' => false,
'include_timeseries_weather' => false,
- 'include_timeseries_resilience' => false }
+ 'include_timeseries_resilience' => false,
+ 'include_timeseries_dwelling_unit_outputs' => false }
annual_csv, timeseries_csv = _test_measure(args_hash)
assert(File.exist?(annual_csv))
assert(!File.exist?(timeseries_csv))
@@ -668,7 +695,8 @@ def test_annual_only2
'include_timeseries_zone_conditions' => true,
'include_timeseries_airflows' => true,
'include_timeseries_weather' => true,
- 'include_timeseries_resilience' => true }
+ 'include_timeseries_resilience' => true,
+ 'include_timeseries_dwelling_unit_outputs' => true }
annual_csv, timeseries_csv = _test_measure(args_hash)
assert(File.exist?(annual_csv))
assert(!File.exist?(timeseries_csv))
@@ -678,6 +706,31 @@ def test_annual_only2
_check_runner_registered_values_and_measure_xml_outputs(actual_annual_rows)
end
+ def test_annual_whole_mf_building
+ args_hash = { 'hpxml_path' => File.join(File.dirname(__FILE__), '../../workflow/sample_files/base-bldgtype-mf-whole-building.xml'),
+ 'skip_validation' => true,
+ 'add_component_loads' => true,
+ 'timeseries_frequency' => 'none' }
+ annual_csv, timeseries_csv = _test_measure(args_hash)
+ assert(File.exist?(annual_csv))
+ assert(!File.exist?(timeseries_csv))
+ expected_annual_rows = AnnualRows + dwelling_unit_annual_cols
+ for i in 2..whole_building_unit_ids.size
+ expected_annual_rows << "System Use: HeatingSystem1_#{i}: #{FT::Elec}: Heating (MBtu)"
+ expected_annual_rows << "System Use: CoolingSystem1_#{i}: #{FT::Elec}: Cooling (MBtu)"
+ expected_annual_rows << "System Use: CoolingSystem1_#{i}: #{FT::Elec}: Cooling Fans/Pumps (MBtu)"
+ expected_annual_rows << "System Use: WaterHeatingSystem1_#{i}: #{FT::Elec}: Hot Water (MBtu)"
+ end
+ # No other fuels because this is an all-electric building.
+ expected_annual_rows.each_with_index do |row, i|
+ expected_annual_rows[i] = expected_annual_rows[i].gsub(EUT::HeatingFanPump, EUT::Heating) if row.include?('System Use')
+ expected_annual_rows.delete(row) if row.include?('System Use') && row.include?(FT::Gas)
+ end
+ actual_annual_rows = _get_annual_values(annual_csv)
+ assert_equal(expected_annual_rows.sort, actual_annual_rows.keys.sort)
+ _check_runner_registered_values_and_measure_xml_outputs(actual_annual_rows)
+ end
+
def test_annual_disabled_outputs
args_hash = { 'hpxml_path' => File.join(File.dirname(__FILE__), '../../workflow/sample_files/base.xml'),
'skip_validation' => true,
@@ -695,7 +748,8 @@ def test_annual_disabled_outputs
'include_annual_component_loads' => false,
'include_annual_hot_water_uses' => false,
'include_annual_hvac_summary' => false,
- 'include_annual_resilience' => false }
+ 'include_annual_resilience' => false,
+ 'include_annual_dwelling_unit_outputs' => false }
annual_csv, timeseries_csv = _test_measure(args_hash)
assert(File.exist?(annual_csv))
assert(!File.exist?(timeseries_csv))
@@ -989,7 +1043,7 @@ def test_timeseries_hourly_zone_temperatures_whole_mf_building
assert(File.exist?(timeseries_csv))
actual_timeseries_cols = File.readlines(timeseries_csv)[0].strip.split(',')
expected_timeseries_cols = ['Time']
- for i in 1..6
+ for i in 1..whole_building_unit_ids.size
i == 1 ? building_id = 'MyBuilding' : building_id = "MyBuilding_#{i}"
expected_timeseries_cols << "Temperature: #{building_id} Conditioned Space"
if i <= 2
@@ -1005,6 +1059,34 @@ def test_timeseries_hourly_zone_temperatures_whole_mf_building
assert_equal(8760, timeseries_rows.size - 2)
end
+ def test_timeseries_hourly_dwelling_unit_outputs_whole_mf_building
+ args_hash = { 'hpxml_path' => File.join(File.dirname(__FILE__), '../../workflow/sample_files/base-bldgtype-mf-whole-building.xml'),
+ 'skip_validation' => true,
+ 'timeseries_frequency' => 'hourly',
+ 'include_timeseries_total_consumptions' => true,
+ 'include_timeseries_fuel_consumptions' => true,
+ 'include_timeseries_dwelling_unit_outputs' => true }
+ annual_csv, timeseries_csv = _test_measure(args_hash)
+ assert(File.exist?(annual_csv))
+ assert(File.exist?(timeseries_csv))
+ actual_timeseries_cols = File.readlines(timeseries_csv)[0].strip.split(',')
+ expected_timeseries_cols = ['Time']
+ expected_timeseries_cols << "Energy Use: #{TE::Total}"
+ expected_timeseries_cols << "Energy Use: #{TE::Net}"
+ expected_timeseries_cols << "Fuel Use: #{FT::Elec}: #{TE::Total}"
+ expected_timeseries_cols << "Fuel Use: #{FT::Elec}: #{TE::Net}"
+ whole_building_unit_ids.each do |unit_id|
+ expected_timeseries_cols << "Dwelling Unit Energy Use: #{unit_id}: #{TE::Total}"
+ expected_timeseries_cols << "Dwelling Unit Energy Use: #{unit_id}: #{TE::Net}"
+ expected_timeseries_cols << "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Elec}: #{TE::Total}"
+ expected_timeseries_cols << "Dwelling Unit Fuel Use: #{unit_id}: #{FT::Elec}: #{TE::Net}"
+ # No other fuels because this is an all-electric building.
+ end
+ assert_equal(expected_timeseries_cols.sort, actual_timeseries_cols.sort)
+ timeseries_rows = CSV.read(timeseries_csv)
+ assert_equal(8760, timeseries_rows.size - 2)
+ end
+
def test_timeseries_hourly_zone_conditions
args_hash = { 'hpxml_path' => File.join(File.dirname(__FILE__), '../../workflow/sample_files/base-hvac-furnace-gas-only.xml'),
'skip_validation' => true,
@@ -1105,7 +1187,7 @@ def test_timeseries_hourly_ALL
emissions_timeseries_cols +
emission_fuels_timeseries_cols +
emission_end_uses_timeseries_cols +
- pv_battery_timeseries_cols +
+ pv_battery_vehicle_timeseries_cols +
BaseHPXMLTimeseriesColsResilience
actual_timeseries_cols = File.readlines(timeseries_csv)[0].strip.split(',')
assert_equal(expected_timeseries_cols.sort, actual_timeseries_cols.sort)
@@ -1149,7 +1231,7 @@ def test_timeseries_daily_ALL
emissions_timeseries_cols +
emission_fuels_timeseries_cols +
emission_end_uses_timeseries_cols +
- pv_battery_timeseries_cols +
+ pv_battery_vehicle_timeseries_cols +
BaseHPXMLTimeseriesColsResilience
actual_timeseries_cols = File.readlines(timeseries_csv)[0].strip.split(',')
assert_equal(expected_timeseries_cols.sort, actual_timeseries_cols.sort)
@@ -1189,7 +1271,7 @@ def test_timeseries_monthly_ALL
emissions_timeseries_cols +
emission_fuels_timeseries_cols +
emission_end_uses_timeseries_cols +
- pv_battery_timeseries_cols +
+ pv_battery_vehicle_timeseries_cols +
BaseHPXMLTimeseriesColsResilience
actual_timeseries_cols = File.readlines(timeseries_csv)[0].strip.split(',')
assert_equal(expected_timeseries_cols.sort, actual_timeseries_cols.sort)
diff --git a/ReportUtilityBills/README.md b/ReportUtilityBills/README.md
index cc85cd90d1..f8190fdf26 100644
--- a/ReportUtilityBills/README.md
+++ b/ReportUtilityBills/README.md
@@ -20,9 +20,11 @@ The file format of the annual (and timeseries, if requested) outputs.
- **Required:** ``false``
-- **Choices:** `csv`, `json`, `msgpack`
+- **Choices:**
- `csv`
- `json`
- `msgpack`
+
+
+- **Default:** `csv`
-
**Generate Annual Utility Bills**
@@ -33,7 +35,9 @@ Generates output file containing annual utility bills.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Monthly Utility Bills**
@@ -44,7 +48,9 @@ Generates output file containing monthly utility bills.
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Generate Monthly Output: Timestamp Convention**
@@ -55,9 +61,11 @@ Determines whether monthly timestamps use the start-of-period or end-of-period c
- **Required:** ``false``
-- **Choices:** `start`, `end`
+- **Choices:**
- `start`
- `end`
+
+
+- **Default:** `start`
-
**Annual Output File Name**
@@ -68,7 +76,7 @@ If not provided, defaults to 'results_bills.csv' (or 'results_bills.json' or 're
- **Required:** ``false``
-
+
**Monthly Output File Name**
@@ -79,7 +87,7 @@ If not provided, defaults to 'results_bills_monthly.csv' (or 'results_bills_mont
- **Required:** ``false``
-
+
**Register Annual Utility Bills**
@@ -90,7 +98,9 @@ Registers annual utility bills with the OpenStudio runner for downstream process
- **Required:** ``false``
-
+
+- **Default:** `true`
+
**Register Monthly Utility Bills**
@@ -101,7 +111,9 @@ Registers monthly utility bills with the OpenStudio runner for downstream proces
- **Required:** ``false``
-
+
+- **Default:** `false`
+
diff --git a/ReportUtilityBills/README.md.erb b/ReportUtilityBills/README.md.erb
index 0e9bc87d3e..2c10598744 100644
--- a/ReportUtilityBills/README.md.erb
+++ b/ReportUtilityBills/README.md.erb
@@ -22,9 +22,11 @@
<% end %>
- **Required:** ``<%= argument[:required] %>``
<% if argument[:type] == "Choice" %>
-- **Choices:** `<%= argument[:choice_values].join("`, `") %>`
+- **Choices:**
- `<%= argument[:choice_values].join("`
- `") %>`
+<% end %>
+<% if argument[:default_value] or argument[:default_value] == false %>
+- **Default:** `<%= argument[:default_value] %>`
<% end %>
-
<% end %>
<% if arguments.size == 0 %>
diff --git a/ReportUtilityBills/measure.xml b/ReportUtilityBills/measure.xml
index 7f1f4f24e1..389e7d1c6f 100644
--- a/ReportUtilityBills/measure.xml
+++ b/ReportUtilityBills/measure.xml
@@ -3,8 +3,8 @@
3.1
report_utility_bills
ca88a425-e59a-4bc4-af51-c7e7d1e960fe
- 208232ac-81ae-472e-866c-34ad5d19dd6e
- 2026-02-04T15:42:33Z
+ 89070ae0-19ff-467a-9610-c3a4f1463591
+ 2026-02-12T20:36:53Z
15BF4E57
ReportUtilityBills
Utility Bills Report
@@ -163,13 +163,13 @@
README.md
md
readme
- 13D965BE
+ 096D2B21
README.md.erb
erb
readmeerb
- 513F28E9
+ 5238CEA2
diff --git a/docs/source/workflow_outputs.rst b/docs/source/workflow_outputs.rst
index 1b86ad0e5c..2e699fa7dc 100644
--- a/docs/source/workflow_outputs.rst
+++ b/docs/source/workflow_outputs.rst
@@ -97,6 +97,8 @@ Annual energy outputs are listed below.
Energy Use: Net (MBtu) Total energy consumption minus power produced by PV
==================================== ===========================
+For whole SFA/MF building simulations, annual energy outputs can also be reported by dwelling unit (e.g., "Dwelling Unit Energy Use: : Total (MBtu)").
+
Annual Energy by Fuel Use
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -115,6 +117,8 @@ Fuel uses are listed below.
Fuel Use: Coal: Total (MBtu) Includes "coal", "anthracite coal", "bituminous coal", and "coke"
==================================== ===========================
+For whole SFA/MF building simulations, fuel uses can also be reported by dwelling unit (e.g., "Dwelling Unit Fuel Use: : Natural Gas: Total (MBtu)").
+
.. _annualenduses:
Annual Energy By End Use
@@ -626,7 +630,6 @@ Outputs for individual geothermal loops can be found in the ``in.xml`` file.
HVAC Geothermal Loop: Borehole/Trench Length (ft) Length (i.e., average depth) of each borehole
===================================================================== ====================
-
.. _timeseries_outputs:
Timeseries Outputs
@@ -660,6 +663,7 @@ Depending on the outputs requested, the file may include:
Airflows ``airflows`` Airflow rates (in cfm) for infiltration, mechanical ventilation (including clothes dryer exhaust), natural ventilation, whole house fans.
Weather ``weather`` Weather file data including outdoor temperatures, relative humidity, wind speed, and solar.
Resilience ``resilience`` Resilience outputs (currently only average resilience hours for battery storage).
+ Dwelling Units ``dwellingunits`` Outputs for each dwelling unit (currently Total/Fuel Consumptions) for whole SFA/MF building simulations.
EnergyPlus Output Variables/Meters Any user-specified EnergyPlus output variables/meters (e.g., 'Zone People Occupant Count', 'MainsWater:Facility').
================================== =================== ==================================================================================================================================
diff --git a/workflow/hpxml_inputs.json b/workflow/hpxml_inputs.json
index 1858b40071..1afa3e1262 100644
--- a/workflow/hpxml_inputs.json
+++ b/workflow/hpxml_inputs.json
@@ -2437,6 +2437,27 @@
"hvac_heating_system_capacity": "10 kBtu/hr",
"appliance_clothes_dryer": "None"
},
+ "sample_files/base-bldgtype-mf-whole-building-fuels.xml": {
+ "parent_hpxml": "sample_files/base.xml",
+ "whole_sfa_or_mf_building_sim": true,
+ "geometry_unit_type": "Apartment Unit, 1 Story",
+ "geometry_attached_walls": "1 Side: Right",
+ "geometry_unit_conditioned_floor_area": "1200",
+ "geometry_unit_aspect_ratio": "0.75",
+ "enclosure_floor_over_foundation": "Wood Frame, R-19",
+ "enclosure_carpet": "80% Carpet",
+ "enclosure_air_leakage": "Detailed Example: 0.375 nACH",
+ "geometry_window_areas_or_wwrs": "0.18, 0.18, 0.18, 0.18",
+ "geometry_door_area": "20",
+ "hvac_heating_system_capacity": "10 kBtu/hr",
+ "hvac_cooling_system_capacity": "1.0 tons",
+ "hvac_ducts": "0 CFM25 per 100ft2, Uninsulated",
+ "hvac_ducts_supply_location": "Conditioned Space",
+ "hvac_ducts_return_location": "Conditioned Space",
+ "appliance_clothes_dryer": "None",
+ "dhw_water_heater": "Propane, Tankless, UEF 0.82",
+ "misc_fireplace": "Detailed Example: Wood, 55 therm/yr"
+ },
"sample_files/base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml": {
"parent_hpxml": "sample_files/base-bldgtype-mf-whole-building.xml",
"hvac_heating_system_capacity": "25 kBtu/hr"
diff --git a/workflow/run_simulation.rb b/workflow/run_simulation.rb
index fd539cf7f0..361fa95795 100644
--- a/workflow/run_simulation.rb
+++ b/workflow/run_simulation.rb
@@ -13,7 +13,8 @@
$timeseries_types = ['ALL', 'total', 'fuels', 'enduses', 'systemuses', 'emissions', 'emissionfuels',
'emissionenduses', 'hotwater', 'loads', 'componentloads',
- 'unmethours', 'temperatures', 'conditions', 'airflows', 'weather', 'resilience']
+ 'unmethours', 'temperatures', 'conditions', 'airflows', 'weather', 'resilience',
+ 'dwellingunits']
def run_workflow(basedir, rundir, hpxml, debug, skip_validation, add_comp_loads,
output_format, building_id, ep_input_format, stochastic_schedules,
@@ -93,6 +94,7 @@ def run_workflow(basedir, rundir, hpxml, debug, skip_validation, add_comp_loads,
args['include_timeseries_airflows'] = timeseries_outputs.include? 'airflows'
args['include_timeseries_weather'] = timeseries_outputs.include? 'weather'
args['include_timeseries_resilience'] = timeseries_outputs.include? 'resilience'
+ args['include_timeseries_dwelling_unit_outputs'] = timeseries_outputs.include? 'dwellingunits'
remaining_outputs = timeseries_outputs - $timeseries_types
output_variables = remaining_outputs.select { |o| !o.include?(':') }
output_meters = remaining_outputs.select { |o| o.include?(':') }
diff --git a/workflow/sample_files/base-bldgtype-mf-whole-building-fuels.xml b/workflow/sample_files/base-bldgtype-mf-whole-building-fuels.xml
new file mode 100644
index 0000000000..9733a4f4d1
--- /dev/null
+++ b/workflow/sample_files/base-bldgtype-mf-whole-building-fuels.xml
@@ -0,0 +1,2727 @@
+
+
+
+ HPXML
+ tasks.rb
+ 2000-01-01T00:00:00-07:00
+ create
+
+
+
+ true
+
+
+ Default
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit above
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 0.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ outside
+ basement - unconditioned
+ 77.1
+ wood siding
+ medium
+
+
+ 13.9
+
+
+
+
+ basement - unconditioned
+ basement - unconditioned
+ 30.8
+
+
+ 4.0
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+
+
+ ground
+ basement - unconditioned
+ solid concrete
+ 8.0
+ 800.0
+ 7.0
+
+
+
+ continuous - exterior
+ 10.0
+
+
+ continuous - interior
+ 0.0
+
+
+
+
+
+ basement - unconditioned
+ basement - unconditioned
+ solid concrete
+ 8.0
+ 320.0
+ 7.0
+
+
+
+ continuous - exterior
+ 0.0
+
+
+ continuous - interior
+ 0.0
+
+
+
+
+
+
+
+ basement - unconditioned
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 22.6
+
+
+
+
+ other housing unit
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 2.1
+
+
+
+
+
+
+ basement - unconditioned
+ 1200.0
+ 100.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit above
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 0.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit_2.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ outside
+ basement - unconditioned
+ 77.1
+ wood siding
+ medium
+
+
+ 13.9
+
+
+
+
+ basement - unconditioned
+ basement - unconditioned
+ 30.8
+
+
+ 4.0
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+
+
+ ground
+ basement - unconditioned
+ solid concrete
+ 8.0
+ 800.0
+ 7.0
+
+
+
+ continuous - exterior
+ 10.0
+
+
+ continuous - interior
+ 0.0
+
+
+
+
+
+ basement - unconditioned
+ basement - unconditioned
+ solid concrete
+ 8.0
+ 320.0
+ 7.0
+
+
+
+ continuous - exterior
+ 0.0
+
+
+ continuous - interior
+ 0.0
+
+
+
+
+
+
+
+ basement - unconditioned
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 22.6
+
+
+
+
+ other housing unit
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 2.1
+
+
+
+
+
+
+ basement - unconditioned
+ 1200.0
+ 100.0
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit above and below
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 10.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit_3.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+
+
+ other housing unit
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 5.3
+
+
+
+
+ other housing unit
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 2.1
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit above and below
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 10.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit_4.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+
+
+ other housing unit
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 5.3
+
+
+
+
+ other housing unit
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 2.1
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit below
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 20.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit_5.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ attic - vented
+ 1341.6
+ asphalt or fiberglass shingles
+ light
+ 6.0
+
+
+ 2.3
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+ outside
+ attic - vented
+ gable
+
+
+
+ 200.0
+ wood siding
+ medium
+
+
+ 4.0
+
+
+
+
+ attic - vented
+ attic - vented
+
+
+
+ 200.0
+
+
+ 4.0
+
+
+
+
+
+
+ other housing unit
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 5.3
+
+
+
+
+ attic - vented
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 39.6
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
+
+
+
+
+ CO
+
+
+
+ proposed workscope
+
+
+
+
+ attached on one side
+ unit below
+ 180
+
+ electricity
+ natural gas
+
+
+
+ apartment unit
+ 20.0
+ 1.0
+ 1.0
+ 8.0
+ 3
+ 2
+ 1200.0
+ 9600.0
+
+
+ ../../HPXMLtoOpenStudio/resources/schedule_files/occupancy-stochastic-mf-unit_6.csv
+
+
+
+
+ 2006
+ 5B
+
+
+
+ USA_CO_Denver.Intl.AP.725650_TMY3
+
+ USA_CO_Denver.Intl.AP.725650_TMY3.epw
+
+
+
+
+
+
+
+ unit exterior only
+
+ ACHnatural
+ 0.375
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ attic - vented
+ 1341.6
+ asphalt or fiberglass shingles
+ light
+ 6.0
+
+
+ 2.3
+
+
+
+
+
+
+ outside
+ conditioned space
+
+
+
+ 800.0
+ wood siding
+ medium
+
+
+ 22.7
+
+
+
+
+ other housing unit
+ conditioned space
+
+
+
+ 320.0
+
+
+ 4.0
+
+
+
+
+ outside
+ attic - vented
+ gable
+
+
+
+ 200.0
+ wood siding
+ medium
+
+
+ 4.0
+
+
+
+
+ attic - vented
+ attic - vented
+
+
+
+ 200.0
+
+
+ 4.0
+
+
+
+
+
+
+ other housing unit
+ conditioned space
+ floor
+
+
+
+ 1200.0
+
+
+ 5.3
+
+
+
+
+ attic - vented
+ conditioned space
+ ceiling
+
+
+
+ 1200.0
+
+
+ 39.6
+
+
+
+
+
+
+ 43.2
+ 0
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 43.2
+ 180
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+ 57.6
+ 270
+ 0.35
+ 0.44
+
+
+ light curtains
+
+ 0.67
+
+
+
+
+
+
+
+ 20.0
+ 180
+ 4.4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ natural gas
+ 10000.0
+
+ AFUE
+ 0.92
+
+ 1.0
+
+
+
+
+ central air conditioner
+ electricity
+ 12000.0
+ single stage
+ 1.0
+
+ SEER2
+ 13.4
+
+
+
+
+
+ 68.0
+ 78.0
+
+
+
+
+
+ regular velocity
+
+ supply
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+ return
+
+ CFM25
+ 0.0
+ to outside
+
+
+
+
+ supply
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ return
+ 0.0
+ conditioned space
+ 1.0
+
+
+
+ 1200.0
+
+
+
+
+
+ propane
+ instantaneous water heater
+ conditioned space
+ 1.0
+ 0.82
+
+
+
+
+
+
+
+ 0.0
+
+
+
+
+ shower head
+ false
+
+
+
+ faucet
+ false
+
+
+
+
+
+
+ 1.21
+ 380.0
+ 0.12
+ 1.09
+ 27.0
+ 6.0
+ 3.2
+
+
+
+ 307.0
+ 12
+ 0.12
+ 1.09
+ 22.32
+ 4.0
+
+
+
+ 650.0
+
+
+
+ electricity
+ false
+
+
+
+ false
+
+
+
+
+
+ interior
+ 0.4
+
+
+
+
+
+
+ interior
+ 0.1
+
+
+
+
+
+
+ interior
+ 0.25
+
+
+
+
+
+
+ exterior
+ 0.4
+
+
+
+
+
+
+ exterior
+ 0.1
+
+
+
+
+
+
+ exterior
+ 0.25
+
+
+
+
+
+
+
+
+ TV other
+
+
+
+ other
+
+
+
+ fireplace
+
+ therm/year
+ 55.0
+
+ wood
+
+
+
+
+
\ No newline at end of file
diff --git a/workflow/template-build-and-run-hpxml-with-stochastic-occupancy.osw b/workflow/template-build-and-run-hpxml-with-stochastic-occupancy.osw
index 606eb4dcd7..b23b23636c 100644
--- a/workflow/template-build-and-run-hpxml-with-stochastic-occupancy.osw
+++ b/workflow/template-build-and-run-hpxml-with-stochastic-occupancy.osw
@@ -81,6 +81,7 @@
"include_annual_hot_water_uses": true,
"include_annual_hvac_summary": true,
"include_annual_resilience": true,
+ "include_annual_dwelling_unit_outputs": true,
"timeseries_frequency": "none",
"include_timeseries_total_consumptions": false,
"include_timeseries_fuel_consumptions": false,
@@ -98,6 +99,7 @@
"include_timeseries_airflows": false,
"include_timeseries_weather": false,
"include_timeseries_resilience": false,
+ "include_timeseries_dwelling_unit_outputs": false,
"timeseries_timestamp_convention": "start",
"add_timeseries_dst_column": false,
"add_timeseries_utc_column": false,
diff --git a/workflow/template-build-and-run-hpxml.osw b/workflow/template-build-and-run-hpxml.osw
index 838e20e894..66e70db312 100644
--- a/workflow/template-build-and-run-hpxml.osw
+++ b/workflow/template-build-and-run-hpxml.osw
@@ -73,6 +73,7 @@
"include_annual_hot_water_uses": true,
"include_annual_hvac_summary": true,
"include_annual_resilience": true,
+ "include_annual_dwelling_unit_outputs": true,
"timeseries_frequency": "none",
"include_timeseries_total_consumptions": false,
"include_timeseries_fuel_consumptions": false,
@@ -90,6 +91,7 @@
"include_timeseries_airflows": false,
"include_timeseries_weather": false,
"include_timeseries_resilience": false,
+ "include_timeseries_dwelling_unit_outputs": false,
"timeseries_timestamp_convention": "start",
"add_timeseries_dst_column": false,
"add_timeseries_utc_column": false,
diff --git a/workflow/template-run-hpxml-with-stochastic-occupancy-subset.osw b/workflow/template-run-hpxml-with-stochastic-occupancy-subset.osw
index 79e505794d..fd388e7b61 100644
--- a/workflow/template-run-hpxml-with-stochastic-occupancy-subset.osw
+++ b/workflow/template-run-hpxml-with-stochastic-occupancy-subset.osw
@@ -42,6 +42,7 @@
"include_annual_hot_water_uses": true,
"include_annual_hvac_summary": true,
"include_annual_resilience": true,
+ "include_annual_dwelling_unit_outputs": true,
"timeseries_frequency": "none",
"include_timeseries_total_consumptions": false,
"include_timeseries_fuel_consumptions": false,
@@ -59,6 +60,7 @@
"include_timeseries_airflows": false,
"include_timeseries_weather": false,
"include_timeseries_resilience": false,
+ "include_timeseries_dwelling_unit_outputs": false,
"timeseries_timestamp_convention": "start",
"add_timeseries_dst_column": false,
"add_timeseries_utc_column": false,
diff --git a/workflow/template-run-hpxml-with-stochastic-occupancy.osw b/workflow/template-run-hpxml-with-stochastic-occupancy.osw
index 3a93d74582..b4870b11bf 100644
--- a/workflow/template-run-hpxml-with-stochastic-occupancy.osw
+++ b/workflow/template-run-hpxml-with-stochastic-occupancy.osw
@@ -41,6 +41,7 @@
"include_annual_hot_water_uses": true,
"include_annual_hvac_summary": true,
"include_annual_resilience": true,
+ "include_annual_dwelling_unit_outputs": true,
"timeseries_frequency": "none",
"include_timeseries_total_consumptions": false,
"include_timeseries_fuel_consumptions": false,
@@ -58,6 +59,7 @@
"include_timeseries_airflows": false,
"include_timeseries_weather": false,
"include_timeseries_resilience": false,
+ "include_timeseries_dwelling_unit_outputs": false,
"timeseries_timestamp_convention": "start",
"add_timeseries_dst_column": false,
"add_timeseries_utc_column": false,
diff --git a/workflow/template-run-hpxml.osw b/workflow/template-run-hpxml.osw
index 92f370ad23..b7f62d9490 100644
--- a/workflow/template-run-hpxml.osw
+++ b/workflow/template-run-hpxml.osw
@@ -34,6 +34,7 @@
"include_annual_hot_water_uses": true,
"include_annual_hvac_summary": true,
"include_annual_resilience": true,
+ "include_annual_dwelling_unit_outputs": true,
"timeseries_frequency": "none",
"include_timeseries_total_consumptions": false,
"include_timeseries_fuel_consumptions": false,
@@ -51,6 +52,7 @@
"include_timeseries_airflows": false,
"include_timeseries_weather": false,
"include_timeseries_resilience": false,
+ "include_timeseries_dwelling_unit_outputs": false,
"timeseries_timestamp_convention": "start",
"add_timeseries_dst_column": false,
"add_timeseries_utc_column": false,
diff --git a/workflow/tests/base_results/results_simulations_bills.csv b/workflow/tests/base_results/results_simulations_bills.csv
index 4353c65591..05b06e4f33 100644
--- a/workflow/tests/base_results/results_simulations_bills.csv
+++ b/workflow/tests/base_results/results_simulations_bills.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,1010.17,144.0,575.16,0.0,719.16,14
base-bldgtype-mf-unit.xml,1286.63,144.0,990.14,0.0,1134.14,144.0,8.49,152.49,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
base-bldgtype-mf-whole-building-common-spaces.xml,8235.59,1152.0,7083.59,0.0,8235.59,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,8529.43,864.0,7665.43,0.0,8529.43,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+base-bldgtype-mf-whole-building-fuels.xml,8126.33,864.0,3481.44,0.0,4345.44,864.0,392.15,1256.15,0.0,0.0,0.0,0.0,1993.44,1993.44,0.0,531.3,531.3,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,7549.75,864.0,6685.75,0.0,7549.75,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,9934.37,864.0,9070.37,0.0,9934.37,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
base-bldgtype-mf-whole-building.xml,8529.43,864.0,7665.43,0.0,8529.43,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
diff --git a/workflow/tests/base_results/results_simulations_energy.csv b/workflow/tests/base_results/results_simulations_energy.csv
index 04ad9b1091..3003c0cd10 100644
--- a/workflow/tests/base_results/results_simulations_energy.csv
+++ b/workflow/tests/base_results/results_simulations_energy.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,30.837,30.837,15.663,15.663,15.175
base-bldgtype-mf-unit.xml,27.839,27.839,26.963,26.963,0.876,0.0,0.0,0.0,0.0,0.0,0.0,0.024,0.0,0.0,2.241,0.544,11.174,0.0,0.0,2.025,0.0,0.206,0.0,0.0,0.0,0.0,2.185,0.0,0.0,0.291,0.357,1.477,1.529,0.0,2.116,2.795,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.876,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-common-spaces.xml,192.899,192.899,192.899,192.899,0.0,0.0,0.0,0.0,0.0,0.0,31.799,0.0,0.0,0.0,11.853,0.0,67.393,0.0,0.0,19.519,0.0,1.819,0.0,0.0,0.0,0.0,12.41,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,208.743,208.743,208.743,208.743,0.0,0.0,0.0,0.0,0.0,0.0,42.292,0.0,0.0,0.0,22.415,0.0,67.306,0.0,0.0,14.641,0.0,1.364,0.0,0.0,0.0,0.0,12.619,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
+base-bldgtype-mf-whole-building-fuels.xml,249.087,249.087,94.806,94.806,40.478,0.0,80.803,33.0,0.0,0.0,0.0,1.101,0.0,0.0,13.75,3.179,0.0,0.0,0.0,14.641,0.0,1.364,0.0,0.0,0.0,0.0,12.664,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,40.478,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,80.803,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,33.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,182.065,182.065,182.065,182.065,0.0,0.0,0.0,0.0,0.0,0.0,25.135,0.0,0.0,0.0,12.923,0.0,67.329,0.0,0.0,14.641,0.0,1.364,0.0,0.0,0.0,0.0,12.566,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,247.002,247.002,247.002,247.002,0.0,0.0,0.0,0.0,0.0,0.0,42.292,0.0,0.0,0.0,22.415,0.0,67.306,0.0,0.0,14.641,0.0,1.364,0.0,0.0,0.0,0.0,12.619,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,38.259,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building.xml,208.743,208.743,208.743,208.743,0.0,0.0,0.0,0.0,0.0,0.0,42.292,0.0,0.0,0.0,22.415,0.0,67.306,0.0,0.0,14.641,0.0,1.364,0.0,0.0,0.0,0.0,12.619,0.0,0.0,1.745,2.141,0.0,9.172,0.0,12.693,22.356,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/workflow/tests/base_results/results_simulations_hvac.csv b/workflow/tests/base_results/results_simulations_hvac.csv
index f13a1ed82d..5b0786c432 100644
--- a/workflow/tests/base_results/results_simulations_hvac.csv
+++ b/workflow/tests/base_results/results_simulations_hvac.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,6.8,91.76,10000.0,12000.0,0.0,5884
base-bldgtype-mf-unit.xml,6.8,91.76,10000.0,12000.0,0.0,5884.0,0.0,2732.0,0.0,287.0,1510.0,0.0,0.0,0.0,0.0,1354.0,0.0,0.0,7403.0,0.0,2731.0,0.0,103.0,193.0,0.0,0.0,0.0,0.0,183.0,0.0,3320.0,0.0,872.0,605.0,0.0,-195.0,0.0,800.0
base-bldgtype-mf-whole-building-common-spaces.xml,6.8,91.76,75000.0,36000.0,0.0,184939.0,0.0,12740.0,0.0,1148.0,19546.0,73730.0,0.0,3495.0,0.0,74278.0,0.0,0.0,93826.0,0.0,12400.0,0.0,412.0,3532.0,38802.0,0.0,0.0,0.0,10032.0,0.0,25180.0,0.0,3464.0,-5456.0,0.0,-10656.0,0.0,5200.0
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,6.8,91.76,60000.0,72000.0,0.0,81800.0,0.0,19110.0,0.0,1722.0,10626.0,0.0,2232.0,0.0,3830.0,44282.0,0.0,0.0,54508.0,0.0,18600.0,0.0,618.0,1356.0,0.0,592.0,0.0,2228.0,5992.0,0.0,19920.0,0.0,5196.0,-1564.0,0.0,-6364.0,0.0,4800.0
+base-bldgtype-mf-whole-building-fuels.xml,6.8,91.76,60000.0,72000.0,0.0,88754.0,0.0,19110.0,0.0,1722.0,10626.0,0.0,2232.0,0.0,3830.0,51232.0,0.0,0.0,54508.0,0.0,18600.0,0.0,618.0,1356.0,0.0,592.0,0.0,2228.0,5992.0,0.0,19920.0,0.0,5196.0,-1564.0,0.0,-6364.0,0.0,4800.0
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,6.8,91.76,75000.0,36000.0,0.0,81800.0,0.0,19110.0,0.0,1722.0,10626.0,0.0,2232.0,0.0,3830.0,44282.0,0.0,0.0,54508.0,0.0,18600.0,0.0,618.0,1356.0,0.0,592.0,0.0,2228.0,5992.0,0.0,19920.0,0.0,5196.0,-1564.0,0.0,-6364.0,0.0,4800.0
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,6.8,91.76,60000.0,72000.0,0.0,81800.0,0.0,19110.0,0.0,1722.0,10626.0,0.0,2232.0,0.0,3830.0,44282.0,0.0,0.0,54508.0,0.0,18600.0,0.0,618.0,1356.0,0.0,592.0,0.0,2228.0,5992.0,0.0,19920.0,0.0,5196.0,-1564.0,0.0,-6364.0,0.0,4800.0
base-bldgtype-mf-whole-building.xml,6.8,91.76,60000.0,72000.0,0.0,81800.0,0.0,19110.0,0.0,1722.0,10626.0,0.0,2232.0,0.0,3830.0,44282.0,0.0,0.0,54508.0,0.0,18600.0,0.0,618.0,1356.0,0.0,592.0,0.0,2228.0,5992.0,0.0,19920.0,0.0,5196.0,-1564.0,0.0,-6364.0,0.0,4800.0
diff --git a/workflow/tests/base_results/results_simulations_loads.csv b/workflow/tests/base_results/results_simulations_loads.csv
index 37c693265d..0a09a3c6f4 100644
--- a/workflow/tests/base_results/results_simulations_loads.csv
+++ b/workflow/tests/base_results/results_simulations_loads.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,1.093,0.0,8.432,10.368,0.467,0.0,0
base-bldgtype-mf-unit.xml,0.827,0.0,8.948,10.368,0.802,0.0,0.0,0.0,-0.003,1.696,0.0,0.0,0.263,2.569,-1.64,0.0,0.0,-0.017,0.0,-0.245,0.801,0.0,0.291,0.0,0.0,-2.414,-0.476,0.0,0.001,-1.97,0.0,0.0,-0.243,-2.741,6.923,0.0,0.0,-0.012,0.0,-0.237,-0.965,-1.533,-0.404,0.0,0.0,8.674,1.549
base-bldgtype-mf-whole-building-common-spaces.xml,31.768,0.0,25.32,62.257,5.111,0.0,0.0,0.0,3.936,8.554,0.758,5.147,0.739,9.585,-9.465,0.0,0.0,7.495,4.759,-0.461,25.602,0.0,0.0,0.0,0.0,-20.707,-4.101,0.0,4.837,2.161,-0.018,1.542,-0.016,-0.706,10.495,0.0,0.0,-1.436,-4.856,-0.458,-5.024,-3.027,0.0,0.0,0.0,18.584,3.22
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,42.236,0.0,46.521,62.257,5.023,0.0,0.0,0.0,7.463,18.694,0.0,0.0,2.33,28.754,-25.563,0.0,0.0,6.813,0.0,-2.272,50.719,0.0,0.0,0.0,0.0,-37.239,-7.151,0.0,-0.616,-3.646,0.0,0.0,-0.142,-3.534,34.272,0.0,0.0,-4.598,0.0,-2.249,-13.154,-8.741,0.0,0.0,0.0,41.457,7.49
+base-bldgtype-mf-whole-building-fuels.xml,38.289,0.0,51.252,62.258,0.0,0.0,0.0,0.0,7.379,18.386,0.0,0.0,2.301,28.24,-24.516,0.0,0.0,6.696,0.0,-2.428,49.731,0.0,0.0,0.0,0.0,-40.322,-6.815,0.0,-0.858,-4.432,0.0,0.0,-0.242,-4.791,35.32,0.0,0.0,-4.95,0.0,-2.404,-14.926,-9.162,0.0,0.0,0.0,49.896,7.825
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,25.104,0.0,27.683,62.257,5.046,0.0,0.0,0.0,3.473,14.756,0.0,0.0,1.141,14.465,-13.566,0.0,0.0,3.471,0.0,-0.868,25.685,0.0,0.0,0.0,0.0,-19.544,-3.769,0.0,-0.202,3.602,0.0,0.0,-0.079,-1.648,16.401,0.0,0.0,-2.643,0.0,-0.86,-6.016,-4.677,0.0,0.0,0.0,20.234,3.551
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,42.236,0.0,46.521,62.257,5.023,0.0,0.0,0.0,7.463,18.694,0.0,0.0,2.33,28.754,-25.563,0.0,0.0,6.813,0.0,-2.272,50.719,0.0,0.0,0.0,0.0,-37.239,-7.151,0.0,-0.616,-3.646,0.0,0.0,-0.142,-3.534,34.272,0.0,0.0,-4.598,0.0,-2.249,-13.154,-8.741,0.0,0.0,0.0,41.457,7.49
base-bldgtype-mf-whole-building.xml,42.236,0.0,46.521,62.257,5.023,0.0,0.0,0.0,7.463,18.694,0.0,0.0,2.33,28.754,-25.563,0.0,0.0,6.813,0.0,-2.272,50.719,0.0,0.0,0.0,0.0,-37.239,-7.151,0.0,-0.616,-3.646,0.0,0.0,-0.142,-3.534,34.272,0.0,0.0,-4.598,0.0,-2.249,-13.154,-8.741,0.0,0.0,0.0,41.457,7.49
diff --git a/workflow/tests/base_results/results_simulations_misc.csv b/workflow/tests/base_results/results_simulations_misc.csv
index afae467efe..6e67a0cda9 100644
--- a/workflow/tests/base_results/results_simulations_misc.csv
+++ b/workflow/tests/base_results/results_simulations_misc.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,0.0,0.0,0.0,1323.0,910.6,12046.2,4
base-bldgtype-mf-unit.xml,0.0,0.0,0.0,1323.0,910.7,12046.2,4107.6,1703.8,2103.2,2103.2,1703.8,2103.2,2103.2,3.871,8.399,0.0
base-bldgtype-mf-whole-building-common-spaces.xml,0.0,1.0,0.0,7938.3,5463.9,72300.8,24653.6,18244.6,14064.1,18244.6,18244.6,14064.1,18244.6,34.08,24.044,0.0
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,0.0,3.0,0.0,7938.3,5463.9,72300.5,24653.5,22676.9,17047.4,22676.9,22676.9,17047.4,22676.9,56.418,56.02,0.0
+base-bldgtype-mf-whole-building-fuels.xml,0.0,3.0,0.0,7938.3,5463.9,72281.5,24647.0,7208.6,11512.3,11512.3,7208.6,11512.3,11512.3,56.587,58.148,0.0
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,0.0,13.0,0.0,7938.3,5463.9,72301.4,24653.8,17409.8,13347.5,17409.8,17409.8,13347.5,17409.8,32.785,29.246,0.0
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,0.0,3.0,0.0,7938.3,5463.9,72300.5,24653.5,47794.7,44767.0,47794.7,47794.7,44767.0,47794.7,56.418,56.02,0.0
base-bldgtype-mf-whole-building.xml,0.0,3.0,0.0,7938.3,5463.9,72300.5,24653.5,22676.9,17047.4,22676.9,22676.9,17047.4,22676.9,56.418,56.02,0.0
diff --git a/workflow/tests/base_results/results_simulations_panel.csv b/workflow/tests/base_results/results_simulations_panel.csv
index bd3ab174c9..1b34293687 100644
--- a/workflow/tests/base_results/results_simulations_panel.csv
+++ b/workflow/tests/base_results/results_simulations_panel.csv
@@ -67,6 +67,7 @@ base-bldgtype-mf-unit-shared-water-heater.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.
base-bldgtype-mf-unit.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-common-spaces.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-detailed-electric-panel.xml,17584.2,6614.4,33000.6,0.0,7200.0,72000.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,48600.0,1200.0,100153.8,417.6,782.4,33750.0,140.4,1059.6,12.0,0.0,12.0,0.0,6.0,12.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,36.0,96.0,78.0,18.0
+base-bldgtype-mf-whole-building-fuels.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-inter-unit-heat-transfer.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building-vehicle-ev-charger.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
base-bldgtype-mf-whole-building.xml,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
diff --git a/workflow/tests/util.rb b/workflow/tests/util.rb
index 2ee10c7ff7..30d2bbd637 100644
--- a/workflow/tests/util.rb
+++ b/workflow/tests/util.rb
@@ -1180,7 +1180,9 @@ def get_tolerances(key)
'Humidity Ratio:', 'Relative Humidity:', 'Dewpoint Temperature:', 'Radiant Temperature:', 'Operative Temperature:',
'Utility Bills:',
'HVAC Zone Design Load:',
- 'HVAC Space Design Load:'].each do |key|
+ 'HVAC Space Design Load:',
+ 'Dwelling Unit Energy Use:',
+ 'Dwelling Unit Fuel Use:'].each do |key|
annual_results_1x.delete_if { |k, _v| k.start_with? key }
annual_results_10x.delete_if { |k, _v| k.start_with? key }
monthly_results_1x.delete_if { |k, _v| k.start_with? key }