Skip to content

Commit

Permalink
Merge pull request #1578 from NREL/room-by-room-sizing
Browse files Browse the repository at this point in the history
Room by room calculations
  • Loading branch information
shorowit committed May 16, 2024
2 parents 4a2edc0 + 32f5187 commit 10c2830
Show file tree
Hide file tree
Showing 49 changed files with 10,826 additions and 2,967 deletions.
106 changes: 50 additions & 56 deletions BuildResidentialHPXML/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4954,7 +4954,7 @@ def self.set_windows(hpxml_bldg, model, args, sorted_subsurfaces)
exterior_shading_factor_winter: args[:window_exterior_shading_winter],
exterior_shading_factor_summer: args[:window_exterior_shading_summer],
fraction_operable: args[:window_fraction_operable],
wall_idref: wall_idref)
attached_to_wall_idref: wall_idref)
end
end

Expand All @@ -4970,13 +4970,21 @@ def self.set_skylights(hpxml_bldg, args, sorted_subsurfaces)
roof_idref = @surface_ids[surface.name.to_s]
next if roof_idref.nil?

roof = hpxml_bldg.roofs.find { |roof| roof.id == roof_idref }
if roof.interior_adjacent_to != HPXML::LocationConditionedSpace
# This is the roof of an attic, so the skylight must have a shaft; attach it to the attic floor as well.
floor = hpxml_bldg.floors.find { |floor| floor.interior_adjacent_to == HPXML::LocationConditionedSpace && floor.exterior_adjacent_to == roof.interior_adjacent_to }
floor_idref = floor.id
end

hpxml_bldg.skylights.add(id: "Skylight#{hpxml_bldg.skylights.size + 1}",
area: UnitConversions.convert(sub_surface.grossArea, 'm^2', 'ft^2'),
azimuth: azimuth,
ufactor: args[:skylight_ufactor],
shgc: args[:skylight_shgc],
storm_type: args[:skylight_storm_type],
roof_idref: roof_idref)
attached_to_roof_idref: roof_idref,
attached_to_floor_idref: floor_idref)
end
end

Expand All @@ -4997,7 +5005,7 @@ def self.set_doors(hpxml_bldg, model, args, sorted_subsurfaces)
next if wall_idref.nil?

hpxml_bldg.doors.add(id: "Door#{hpxml_bldg.doors.size + 1}",
wall_idref: wall_idref,
attached_to_wall_idref: wall_idref,
area: UnitConversions.convert(sub_surface.grossArea, 'm^2', 'ft^2'),
azimuth: args[:geometry_unit_orientation],
r_value: args[:door_rvalue])
Expand Down Expand Up @@ -6554,72 +6562,58 @@ def self.collapse_surfaces(hpxml_bldg, args)
end

# After surfaces are collapsed, round all areas
(hpxml_bldg.roofs +
hpxml_bldg.rim_joists +
hpxml_bldg.walls +
hpxml_bldg.foundation_walls +
hpxml_bldg.floors +
hpxml_bldg.slabs +
hpxml_bldg.windows +
hpxml_bldg.skylights +
hpxml_bldg.doors).each do |s|
(hpxml_bldg.surfaces + hpxml_bldg.subsurfaces).each do |s|
s.area = s.area.round(1)
end
end

def self.renumber_hpxml_ids(hpxml_bldg)
# Renumber surfaces
{ hpxml_bldg.walls => 'Wall',
hpxml_bldg.foundation_walls => 'FoundationWall',
hpxml_bldg.rim_joists => 'RimJoist',
hpxml_bldg.floors => 'Floor',
hpxml_bldg.roofs => 'Roof',
hpxml_bldg.slabs => 'Slab',
hpxml_bldg.windows => 'Window',
hpxml_bldg.doors => 'Door',
hpxml_bldg.skylights => 'Skylight' }.each do |surfs, surf_name|
surfs.each_with_index do |surf, i|
(hpxml_bldg.attics + hpxml_bldg.foundations).each do |attic_or_fnd|
if attic_or_fnd.respond_to?(:attached_to_roof_idrefs) && !attic_or_fnd.attached_to_roof_idrefs.nil? && !attic_or_fnd.attached_to_roof_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_roof_idrefs << "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_wall_idrefs) && !attic_or_fnd.attached_to_wall_idrefs.nil? && !attic_or_fnd.attached_to_wall_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_wall_idrefs << "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_rim_joist_idrefs) && !attic_or_fnd.attached_to_rim_joist_idrefs.nil? && !attic_or_fnd.attached_to_rim_joist_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_rim_joist_idrefs << "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_floor_idrefs) && !attic_or_fnd.attached_to_floor_idrefs.nil? && !attic_or_fnd.attached_to_floor_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_floor_idrefs << "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_slab_idrefs) && !attic_or_fnd.attached_to_slab_idrefs.nil? && !attic_or_fnd.attached_to_slab_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_slab_idrefs << "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_foundation_wall_idrefs) && !attic_or_fnd.attached_to_foundation_wall_idrefs.nil? && !attic_or_fnd.attached_to_foundation_wall_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_foundation_wall_idrefs << "#{surf_name}#{i + 1}"
end
indexes = {}
(hpxml_bldg.surfaces + hpxml_bldg.subsurfaces).each do |surf|
surf_name = surf.class.to_s.gsub('HPXML::', '')
indexes[surf_name] = 0 if indexes[surf_name].nil?
indexes[surf_name] += 1
(hpxml_bldg.attics + hpxml_bldg.foundations).each do |attic_or_fnd|
if attic_or_fnd.respond_to?(:attached_to_roof_idrefs) && !attic_or_fnd.attached_to_roof_idrefs.nil? && !attic_or_fnd.attached_to_roof_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_roof_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
(hpxml_bldg.windows + hpxml_bldg.doors).each do |subsurf|
if subsurf.respond_to?(:wall_idref) && (subsurf.wall_idref == surf.id)
subsurf.wall_idref = "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_wall_idrefs) && !attic_or_fnd.attached_to_wall_idrefs.nil? && !attic_or_fnd.attached_to_wall_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_wall_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
hpxml_bldg.skylights.each do |subsurf|
if subsurf.respond_to?(:roof_idref) && (subsurf.roof_idref == surf.id)
subsurf.roof_idref = "#{surf_name}#{i + 1}"
end
if attic_or_fnd.respond_to?(:attached_to_rim_joist_idrefs) && !attic_or_fnd.attached_to_rim_joist_idrefs.nil? && !attic_or_fnd.attached_to_rim_joist_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_rim_joist_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
if attic_or_fnd.respond_to?(:attached_to_floor_idrefs) && !attic_or_fnd.attached_to_floor_idrefs.nil? && !attic_or_fnd.attached_to_floor_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_floor_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
surf.id = "#{surf_name}#{i + 1}"
if surf.respond_to? :insulation_id
surf.insulation_id = "#{surf_name}#{i + 1}Insulation"
if attic_or_fnd.respond_to?(:attached_to_slab_idrefs) && !attic_or_fnd.attached_to_slab_idrefs.nil? && !attic_or_fnd.attached_to_slab_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_slab_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
if surf.respond_to? :perimeter_insulation_id
surf.perimeter_insulation_id = "#{surf_name}#{i + 1}PerimeterInsulation"
if attic_or_fnd.respond_to?(:attached_to_foundation_wall_idrefs) && !attic_or_fnd.attached_to_foundation_wall_idrefs.nil? && !attic_or_fnd.attached_to_foundation_wall_idrefs.delete(surf.id).nil?
attic_or_fnd.attached_to_foundation_wall_idrefs << "#{surf_name}#{indexes[surf_name]}"
end
end
(hpxml_bldg.windows + hpxml_bldg.doors).each do |subsurf|
if subsurf.respond_to?(:attached_to_wall_idref) && (subsurf.attached_to_wall_idref == surf.id)
subsurf.attached_to_wall_idref = "#{surf_name}#{indexes[surf_name]}"
end
if surf.respond_to? :under_slab_insulation_id
surf.under_slab_insulation_id = "#{surf_name}#{i + 1}UnderSlabInsulation"
end
hpxml_bldg.skylights.each do |subsurf|
if subsurf.respond_to?(:attached_to_roof_idref) && (subsurf.attached_to_roof_idref == surf.id)
subsurf.attached_to_roof_idref = "#{surf_name}#{indexes[surf_name]}"
end
end
surf.id = "#{surf_name}#{indexes[surf_name]}"
if surf.respond_to? :insulation_id
surf.insulation_id = "#{surf_name}#{indexes[surf_name]}Insulation"
end
if surf.respond_to? :perimeter_insulation_id
surf.perimeter_insulation_id = "#{surf_name}#{indexes[surf_name]}PerimeterInsulation"
end
if surf.respond_to? :under_slab_insulation_id
surf.under_slab_insulation_id = "#{surf_name}#{indexes[surf_name]}UnderSlabInsulation"
end
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions BuildResidentialHPXML/measure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<schema_version>3.1</schema_version>
<name>build_residential_hpxml</name>
<uid>a13a8983-2b01-4930-8af2-42030b6e4233</uid>
<version_id>b0604dc5-b6a6-4e72-b423-b3c4e25ae1fc</version_id>
<version_modified>2024-05-07T13:37:00Z</version_modified>
<version_id>89391782-f408-4b0e-9801-b5f67d0f8241</version_id>
<version_modified>2024-05-15T20:26:57Z</version_modified>
<xml_checksum>2C38F48B</xml_checksum>
<class_name>BuildResidentialHPXML</class_name>
<display_name>HPXML Builder</display_name>
Expand Down Expand Up @@ -7342,7 +7342,7 @@
<filename>measure.rb</filename>
<filetype>rb</filetype>
<usage_type>script</usage_type>
<checksum>58EF2442</checksum>
<checksum>8BEED0CA</checksum>
</file>
<file>
<filename>geometry.rb</filename>
Expand Down
9 changes: 7 additions & 2 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ __New Features__
- Allows optional ground diffusivity input.
- Updates to using G-Functions from the [G-Function Library for Modeling Vertical Bore Ground Heat Exchanger](https://gdr.openei.org/submissions/1325).
- Updated heating/cooling performance curves to reflect newer equipment.
- Skylights with shafts or sun tunnels should include the `Skylight/AttachedToFloor` element.
- Allows optional `Ducts/DuctShape` and `Ducts/DuctFractionRectangular` inputs, which affect duct effective R-value used for modeling.
- Allows optional `HeatingAutosizingFactor`, `CoolingAutosizingFactor`, `BackupHeatingAutosizingFactor` inputs to scale HVAC capacities for autosized equipment.
- Allows optional `HeatingAutosizingLimit`, `CoolingAutosizingLimit`, `BackupHeatingAutosizingLimit` inputs to set maximum HVAC capacities ceiling for autosized equipment.
Expand All @@ -48,8 +49,12 @@ __New Features__
- Add soil and moisture type arguments (for determining ground conductivity and diffusivity) and optional geothermal loop arguments for ground source heat pumps.
- The "Geometry: Building Number of Units" input is now written to the HPXML `NumberofUnitsInBuilding` element.
- Adds a blower fan efficiency input for specifying fan power W/cfm at maximum speed.
- Manual J design load calculations:
- Allow additional outdoor design condition inputs: `DailyTemperatureRange` and `HumidityDifference`.
- HVAC Manual J design load calculations:
- **Breaking change**: Outputs for "Infiltration/Ventilation" category disaggregated into "Infiltration" and "Ventilation".
- **Breaking change**: Outputs for "Windows" category no longer includes AED excursion; now a separate "AED Excursion" category.
- Allows optional zone-level and space-level design load calculations using HPXML `Zones/Zone[ZoneType="conditioned"]/Spaces/Space` elements.
- Allows additional outdoor design condition inputs: `DailyTemperatureRange` and `HumidityDifference`.
- Adds a new detailed output file with block/space load details by surface, AED curves, etc.
- Miscellaneous improvements.
- Improves heating/cooling component loads; for timesteps where there is no heating/cooling load, assigns heat transfer to heating or cooling by comparing indoor temperature to the average of heating/cooling setpoints.
- Adds net energy and net electricity timeseries output columns even when there is no PV or generator.
Expand Down
51 changes: 43 additions & 8 deletions HPXMLtoOpenStudio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,36 @@ Absolute/relative path for the output files directory.

<br/>

**Debug Mode?**
**Output Format**

If true: 1) Writes in.osm file, 2) Generates additional log output, and 3) Creates all EnergyPlus output files.
The file format of the HVAC design load details output.

- **Name:** ``debug``
- **Type:** ``Boolean``
- **Name:** ``output_format``
- **Type:** ``Choice``

- **Required:** ``false``

- **Choices:** `csv`, `json`, `msgpack`

<br/>

**Annual Output File Name**

The name of the file w/ HVAC design loads and capacities. If not provided, defaults to 'results_annual.csv' (or 'results_annual.json' or 'results_annual.msgpack').

- **Name:** ``annual_output_file_name``
- **Type:** ``String``

- **Required:** ``false``

<br/>

**Design Load Details Output File Name**

The name of the file w/ additional HVAC design load details. If not provided, defaults to 'results_design_load_details.csv' (or 'results_design_load_details.json' or 'results_design_load_details.msgpack').

- **Name:** ``design_load_details_output_file_name``
- **Type:** ``String``

- **Required:** ``false``

Expand All @@ -55,6 +79,17 @@ If true, adds the calculation of heating/cooling component loads (not enabled by

<br/>

**BuildingID**

The ID of the HPXML Building. Only required if the HPXML has multiple Building elements and WholeSFAorMFBuildingSimulation is not true.

- **Name:** ``building_id``
- **Type:** ``String``

- **Required:** ``false``

<br/>

**Skip Validation?**

If true, bypasses HPXML input validation for faster performance. WARNING: This should only be used if the supplied HPXML file has already been validated against the Schema & Schematron documents.
Expand All @@ -66,12 +101,12 @@ If true, bypasses HPXML input validation for faster performance. WARNING: This s

<br/>

**BuildingID**
**Debug Mode?**

The ID of the HPXML Building. Only required if the HPXML has multiple Building elements and WholeSFAorMFBuildingSimulation is not true.
If true: 1) Writes in.osm file, 2) Generates additional log output, and 3) Creates all EnergyPlus output files.

- **Name:** ``building_id``
- **Type:** ``String``
- **Name:** ``debug``
- **Type:** ``Boolean``

- **Required:** ``false``

Expand Down

0 comments on commit 10c2830

Please sign in to comment.