diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml
index a358f362c5..fa4577339b 100644
--- a/.github/workflows/config.yml
+++ b/.github/workflows/config.yml
@@ -11,7 +11,7 @@ jobs:
build:
runs-on: ubuntu-latest
container:
- image: docker://nrel/openstudio:3.2.0
+ image: docker://nrel/openstudio:3.2.1
steps:
- uses: actions/checkout@v2
with:
@@ -75,7 +75,14 @@ jobs:
cp -r base_results/results*.csv workflow/tests/base_results
mkdir workflow/tests/results
cp -r results/results* workflow/tests/results
- ruby workflow/tests/compare.rb
+
+ pip install numpy
+ pip install pandas
+ pip install plotly
+ pip install kaleido
+
+ python workflow/tests/compare.py -a results
+ python workflow/tests/compare.py -a visualize
- name: Store comparisons
uses: actions/upload-artifact@v2
diff --git a/.rubocop.yml b/.rubocop.yml
index 0687da319b..830c44ba05 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1,16 +1,75 @@
Layout/EndOfLine:
Enabled: false
-Metrics/LineLength:
+Layout/LineLength:
AutoCorrect: false
Enabled: false
Layout/RescueEnsureAlignment:
AutoCorrect: true
Style/FrozenStringLiteralComment:
AutoCorrect: true
-# Enable the cops below when rubocop is upgraded
-#Style/HashEachMethods:
-# Enabled: true
-#Style/HashTransformKeys:
-# Enabled: true
-#Style/HashTransformValues:
-# Enabled: true
\ No newline at end of file
+Style/HashEachMethods:
+ Enabled: true
+Style/HashTransformKeys:
+ Enabled: true
+Style/HashTransformValues:
+ Enabled: true
+Gemspec/DateAssignment:
+ Enabled: true
+Layout/SpaceBeforeBrackets:
+ Enabled: true
+Lint/AmbiguousAssignment:
+ Enabled: true
+Lint/DeprecatedConstants:
+ Enabled: true
+Lint/DuplicateBranch:
+ Enabled: true
+Lint/DuplicateRegexpCharacterClassElement:
+ Enabled: true
+Lint/EmptyBlock:
+ Enabled: true
+Lint/EmptyClass:
+ Enabled: true
+Lint/LambdaWithoutLiteralBlock:
+ Enabled: true
+Lint/NoReturnInBeginEndBlocks:
+ Enabled: true
+Lint/NumberedParameterAssignment:
+ Enabled: true
+Lint/OrAssignmentToConstant:
+ Enabled: true
+Lint/RedundantDirGlobSort:
+ Enabled: true
+Lint/SymbolConversion:
+ Enabled: true
+Lint/ToEnumArguments:
+ Enabled: true
+Lint/TripleQuotes:
+ Enabled: true
+Lint/UnexpectedBlockArity:
+ Enabled: true
+Lint/UnmodifiedReduceAccumulator:
+ Enabled: true
+Style/ArgumentsForwarding:
+ Enabled: true
+Style/CollectionCompact:
+ Enabled: true
+Style/DocumentDynamicEvalDefinition:
+ Enabled: true
+Style/EndlessMethod:
+ Enabled: true
+Style/HashConversion:
+ Enabled: true
+Style/HashExcept:
+ Enabled: true
+Style/IfWithBooleanLiteralBranches:
+ Enabled: true
+Style/NegatedIfElseCondition:
+ Enabled: true
+Style/NilLambda:
+ Enabled: true
+Style/RedundantArgument:
+ Enabled: true
+Style/StringChars:
+ Enabled: true
+Style/SwapValues:
+ Enabled: true
\ No newline at end of file
diff --git a/Changelog.md b/Changelog.md
index 2a059e50ed..aa5c8e8bef 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,16 +1,35 @@
## OpenStudio-HPXML v1.3.0 (Pending)
__New Features__
-- Updates to OpenStudio 3.2.0/EnergyPlus 9.5.0.
-- Introduces a small amount of infiltration for unvented spaces.
+- Updates to OpenStudio 3.2.1/EnergyPlus 9.5.0.
- **Breaking change**: Replaces ClothesDryer `extension/IsVented` and `extension/VentedFlowRate` with `Vented` and `VentedFlowRate`.
-- Allows additional fuel types for generators.
- Adds an `--ep-input-format` argument to run_simulation.rb to choose epJSON as the EnergyPlus input file format instead of IDF.
+- Allows non-zero refrigerant charge defect ratios for ground source heat pumps.
- Allows `HeatingSeason` & `CoolingSeason` to be specified for defining heating and cooling equipment availability.
+- Revises shared mechanical ventilation preconditioning control logic to operate less often.
+- Allows `Ducts/FractionDuctArea` to be provided instead of `Ducts/DuctSurfaceArea`.
+- Allows CEER (Combined Energy Efficiency Ratio) efficiency unit for room AC.
+- Allows "none" for wall/rim joist siding.
+- Allows interior finish inputs (e.g., 0.5" drywall) for walls, ceilings, and roofs.
+- Allows `Orientation` to be provided instead of `Azimuth` for all applicable surfaces, PV systems, and solar thermal systems.
+- Allows `Length` to be provided instead of `Area` for foundation walls.
+- Allows additional fuel types for generators.
+- Allows more defaulting (optional inputs):
+ - HVAC/DHW system efficiency (by age).
+ - Mechanical ventilation fan power (by type).
+ - Color (solar absorptance) for walls, roofs, and rim joists.
+ - Foundation wall distance to top/bottom of insulation.
+ - Door azimuth.
+ - Radiant barrier grade.
+- For water heaters w/ UEF, allows `UsageBin` instead of `FirstHourRating` (or defaults if neither provided).
+- Switches to the EnergyPlus Fan:SystemModel object for all HVAC systems.
+- Introduces a small amount of infiltration for unvented spaces.
- Removes error-check for number of bedrooms based on conditioned floor area, per RESNET guidance.
+- Updates the reporting measure to register all outputs from the annual CSV with the OS runner (for use in, e.g., PAT).
__Bugfixes__
- Improves ground reflectance when there is shading of windows/skylights.
+- Fixes heating fan power for single-stage systems that have different heating/cooling airflow rates.
## OpenStudio-HPXML v1.2.0
diff --git a/Gemfile.lock b/Gemfile.lock
index 0fc6c36462..2c0d9d4e94 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,16 +4,7 @@ GEM
ansi (1.5.0)
ast (2.4.2)
builder (3.2.4)
- ci_reporter (2.0.0)
- builder (>= 2.1.2)
- ci_reporter_minitest (1.0.0)
- ci_reporter (~> 2.0)
- minitest (~> 5.0)
- codecov (0.2.12)
- json
- simplecov
docile (1.3.5)
- json (2.5.1)
mini_portile2 (2.5.0)
minitest (5.14.4)
minitest-reporters (1.4.3)
@@ -50,8 +41,6 @@ PLATFORMS
x64-mingw32
DEPENDENCIES
- ci_reporter_minitest (~> 1.0.0)
- codecov (= 0.2.12)
minitest (~> 5.9)
minitest-reporters
nokogiri (~> 1.10)
@@ -60,6 +49,7 @@ DEPENDENCIES
rake
schematron-nokogiri
simplecov
+ simplecov-html
BUNDLED WITH
2.2.11
diff --git a/HPXMLtoOpenStudio/measure.rb b/HPXMLtoOpenStudio/measure.rb
index b094437f7f..8de21c3305 100644
--- a/HPXMLtoOpenStudio/measure.rb
+++ b/HPXMLtoOpenStudio/measure.rb
@@ -300,7 +300,7 @@ def self.set_defaults_and_globals(runner, output_dir, epw_file, weather)
@ncfl = @hpxml.building_construction.number_of_conditioned_floors
@ncfl_ag = @hpxml.building_construction.number_of_conditioned_floors_above_grade
@nbeds = @hpxml.building_construction.number_of_bedrooms
- @default_azimuths = get_default_azimuths()
+ @default_azimuths = HPXMLDefaults.get_default_azimuths(@hpxml)
# Apply defaults to HPXML object
HPXMLDefaults.apply(@hpxml, @eri_version, weather, epw_file: epw_file)
@@ -535,42 +535,6 @@ def self.add_num_occupants(model, runner, spaces)
Geometry.apply_occupants(model, num_occ, @cfa, spaces[HPXML::LocationLivingSpace])
end
- def self.get_default_azimuths()
- def self.sanitize_azimuth(azimuth)
- # Ensure 0 <= orientation < 360
- while azimuth < 0
- azimuth += 360
- end
- while azimuth >= 360
- azimuth -= 360
- end
- return azimuth
- end
-
- # Returns a list of four azimuths (facing each direction). Determined based
- # on the primary azimuth, as defined by the azimuth with the largest surface
- # area, plus azimuths that are offset by 90/180/270 degrees. Used for
- # surfaces that may not have an azimuth defined (e.g., walls).
- azimuth_areas = {}
- (@hpxml.roofs + @hpxml.rim_joists + @hpxml.walls + @hpxml.foundation_walls +
- @hpxml.windows + @hpxml.skylights + @hpxml.doors).each do |surface|
- az = surface.azimuth
- next if az.nil?
-
- azimuth_areas[az] = 0 if azimuth_areas[az].nil?
- azimuth_areas[az] += surface.area
- end
- if azimuth_areas.empty?
- primary_azimuth = 0
- else
- primary_azimuth = azimuth_areas.max_by { |k, v| v }[0]
- end
- return [primary_azimuth,
- sanitize_azimuth(primary_azimuth + 90),
- sanitize_azimuth(primary_azimuth + 180),
- sanitize_azimuth(primary_azimuth + 270)].sort
- end
-
def self.create_or_get_space(model, spaces, spacetype)
if spaces[spacetype].nil?
Geometry.create_space_and_zone(model, spaces, spacetype)
@@ -621,8 +585,6 @@ def self.add_roofs(runner, model, spaces)
next if surfaces.empty?
# Apply construction
- solar_abs = roof.solar_absorptance
- emitt = roof.emittance
has_radiant_barrier = roof.radiant_barrier
if has_radiant_barrier
radiant_barrier_grade = roof.radiant_barrier_grade
@@ -630,23 +592,30 @@ def self.add_roofs(runner, model, spaces)
# FUTURE: Create Constructions.get_air_film(surface) method; use in measure.rb and hpxml_translator_test.rb
inside_film = Material.AirFilmRoof(Geometry.get_roof_pitch([surfaces[0]]))
outside_film = Material.AirFilmOutside
- mat_roofing = Material.RoofMaterial(roof.roof_type, emitt, solar_abs)
+ mat_roofing = Material.RoofMaterial(roof.roof_type)
if @apply_ashrae140_assumptions
inside_film = Material.AirFilmRoofASHRAE140
outside_film = Material.AirFilmOutsideASHRAE140
end
+ mat_int_finish = Material.InteriorFinishMaterial(roof.interior_finish_type, roof.interior_finish_thickness)
+ if mat_int_finish.nil?
+ fallback_mat_int_finish = nil
+ else
+ fallback_mat_int_finish = Material.InteriorFinishMaterial(mat_int_finish.name, 0.1) # Try thin material
+ end
install_grade = 1
assembly_r = roof.insulation_assembly_r_value
- if roof.is_thermal_boundary
+ if not mat_int_finish.nil?
+ # Closed cavity
constr_sets = [
- WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 20.0, 0.75, 0.5, mat_roofing), # 2x8, 24" o.c. + R20
- WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 10.0, 0.75, 0.5, mat_roofing), # 2x8, 24" o.c. + R10
- WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 0.0, 0.75, 0.5, mat_roofing), # 2x8, 24" o.c.
- WoodStudConstructionSet.new(Material.Stud2x6, 0.07, 0.0, 0.75, 0.5, mat_roofing), # 2x6, 24" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.07, 0.0, 0.5, 0.5, mat_roofing), # 2x4, 16" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, 0.0, mat_roofing), # Fallback
+ WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 20.0, 0.75, mat_int_finish, mat_roofing), # 2x8, 24" o.c. + R20
+ WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 10.0, 0.75, mat_int_finish, mat_roofing), # 2x8, 24" o.c. + R10
+ WoodStudConstructionSet.new(Material.Stud2x(8.0), 0.07, 0.0, 0.75, mat_int_finish, mat_roofing), # 2x8, 24" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.07, 0.0, 0.75, mat_int_finish, mat_roofing), # 2x6, 24" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.07, 0.0, 0.5, mat_int_finish, mat_roofing), # 2x4, 16" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, fallback_mat_int_finish, mat_roofing), # Fallback
]
match, constr_set, cavity_r = Constructions.pick_wood_stud_construction_set(assembly_r, constr_sets, inside_film, outside_film, roof.id)
@@ -654,15 +623,17 @@ def self.add_roofs(runner, model, spaces)
cavity_r, install_grade,
constr_set.stud.thick_in,
true, constr_set.framing_factor,
- constr_set.drywall_thick_in,
+ constr_set.mat_int_finish,
constr_set.osb_thick_in, constr_set.rigid_r,
- constr_set.exterior_material, has_radiant_barrier,
- inside_film, outside_film, radiant_barrier_grade)
+ constr_set.mat_ext_finish, has_radiant_barrier,
+ inside_film, outside_film, radiant_barrier_grade,
+ roof.solar_absorptance, roof.emittance)
else
+ # Open cavity
constr_sets = [
- GenericConstructionSet.new(10.0, 0.5, 0.0, mat_roofing), # w/R-10 rigid
- GenericConstructionSet.new(0.0, 0.5, 0.0, mat_roofing), # Standard
- GenericConstructionSet.new(0.0, 0.0, 0.0, mat_roofing), # Fallback
+ GenericConstructionSet.new(10.0, 0.5, nil, mat_roofing), # w/R-10 rigid
+ GenericConstructionSet.new(0.0, 0.5, nil, mat_roofing), # Standard
+ GenericConstructionSet.new(0.0, 0.0, nil, mat_roofing), # Fallback
]
match, constr_set, layer_r = Constructions.pick_generic_construction_set(assembly_r, constr_sets, inside_film, outside_film, roof.id)
@@ -676,7 +647,8 @@ def self.add_roofs(runner, model, spaces)
framing_factor, framing_thick_in,
constr_set.osb_thick_in, layer_r + constr_set.rigid_r,
mat_roofing, has_radiant_barrier,
- inside_film, outside_film, radiant_barrier_grade)
+ inside_film, outside_film, radiant_barrier_grade,
+ roof.solar_absorptance, roof.emittance)
end
Constructions.check_surface_assembly_rvalue(runner, surfaces, inside_film, outside_film, assembly_r, match)
end
@@ -730,15 +702,10 @@ def self.add_walls(runner, model, spaces)
# The code below constructs a reasonable wall construction based on the
# wall type while ensuring the correct assembly R-value.
- if wall.is_thermal_boundary
- drywall_thick_in = 0.5
- else
- drywall_thick_in = 0.0
- end
inside_film = Material.AirFilmVertical
if wall.is_exterior
outside_film = Material.AirFilmOutside
- mat_ext_finish = Material.ExteriorFinishMaterial(wall.siding, wall.emittance, wall.solar_absorptance)
+ mat_ext_finish = Material.ExteriorFinishMaterial(wall.siding)
else
outside_film = Material.AirFilmVertical
mat_ext_finish = nil
@@ -747,9 +714,11 @@ def self.add_walls(runner, model, spaces)
inside_film = Material.AirFilmVerticalASHRAE140
outside_film = Material.AirFilmOutsideASHRAE140
end
+ mat_int_finish = Material.InteriorFinishMaterial(wall.interior_finish_type, wall.interior_finish_thickness)
- Constructions.apply_wall_construction(runner, model, surfaces, wall, wall.id, wall.wall_type, wall.insulation_assembly_r_value,
- drywall_thick_in, inside_film, outside_film, mat_ext_finish)
+ Constructions.apply_wall_construction(runner, model, surfaces, wall.id, wall.wall_type, wall.insulation_assembly_r_value,
+ mat_int_finish, inside_film, outside_film, mat_ext_finish, wall.solar_absorptance,
+ wall.emittance)
end
end
@@ -795,15 +764,10 @@ def self.add_rim_joists(runner, model, spaces)
# Apply construction
- if rim_joist.is_thermal_boundary
- drywall_thick_in = 0.5
- else
- drywall_thick_in = 0.0
- end
inside_film = Material.AirFilmVertical
if rim_joist.is_exterior
outside_film = Material.AirFilmOutside
- mat_ext_finish = Material.ExteriorFinishMaterial(rim_joist.siding, rim_joist.emittance, rim_joist.solar_absorptance)
+ mat_ext_finish = Material.ExteriorFinishMaterial(rim_joist.siding)
else
outside_film = Material.AirFilmVertical
mat_ext_finish = nil
@@ -812,19 +776,20 @@ def self.add_rim_joists(runner, model, spaces)
assembly_r = rim_joist.insulation_assembly_r_value
constr_sets = [
- WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 20.0, 2.0, drywall_thick_in, mat_ext_finish), # 2x4 + R20
- WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 10.0, 2.0, drywall_thick_in, mat_ext_finish), # 2x4 + R10
- WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 0.0, 2.0, drywall_thick_in, mat_ext_finish), # 2x4
- WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.01, 0.0, 0.0, 0.0, mat_ext_finish), # Fallback
+ WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 20.0, 2.0, nil, mat_ext_finish), # 2x4 + R20
+ WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 10.0, 2.0, nil, mat_ext_finish), # 2x4 + R10
+ WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.17, 0.0, 2.0, nil, mat_ext_finish), # 2x4
+ WoodStudConstructionSet.new(Material.Stud2x(2.0), 0.01, 0.0, 0.0, nil, mat_ext_finish), # Fallback
]
match, constr_set, cavity_r = Constructions.pick_wood_stud_construction_set(assembly_r, constr_sets, inside_film, outside_film, rim_joist.id)
install_grade = 1
- Constructions.apply_rim_joist(runner, model, surfaces, rim_joist, "#{rim_joist.id} construction",
+ Constructions.apply_rim_joist(runner, model, surfaces, "#{rim_joist.id} construction",
cavity_r, install_grade, constr_set.framing_factor,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- constr_set.rigid_r, constr_set.exterior_material,
- inside_film, outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ constr_set.rigid_r, constr_set.mat_ext_finish,
+ inside_film, outside_film, rim_joist.solar_absorptance,
+ rim_joist.emittance)
Constructions.check_surface_assembly_rvalue(runner, surfaces, inside_film, outside_film, assembly_r, match)
end
end
@@ -871,10 +836,20 @@ def self.add_frame_floors(runner, model, spaces)
inside_film = Material.AirFilmFloorAverage
outside_film = Material.AirFilmFloorAverage
end
+ mat_int_finish = Material.InteriorFinishMaterial(frame_floor.interior_finish_type, frame_floor.interior_finish_thickness)
+ if mat_int_finish.nil?
+ fallback_mat_int_finish = nil
+ else
+ fallback_mat_int_finish = Material.InteriorFinishMaterial(mat_int_finish.name, 0.1) # Try thin material
+ end
constr_sets = [
- WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 0.0, 0.0, 0.5, nil), # 2x6, 24" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.13, 0.0, 0.0, 0.5, nil), # 2x4, 16" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, 0.0, nil), # Fallback
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 50.0, 0.0, mat_int_finish, nil), # 2x6, 24" o.c. + R50
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 40.0, 0.0, mat_int_finish, nil), # 2x6, 24" o.c. + R40
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 30.0, 0.0, mat_int_finish, nil), # 2x6, 24" o.c. + R30
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 20.0, 0.0, mat_int_finish, nil), # 2x6, 24" o.c. + R20
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 10.0, 0.0, mat_int_finish, nil), # 2x6, 24" o.c. + R10
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.13, 0.0, 0.0, mat_int_finish, nil), # 2x4, 16" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, fallback_mat_int_finish, nil), # Fallback
]
else # Floor
if @apply_ashrae140_assumptions
@@ -894,12 +869,17 @@ def self.add_frame_floors(runner, model, spaces)
covering = Material.CoveringBare
end
end
+ if covering.nil?
+ fallback_covering = nil
+ else
+ fallback_covering = Material.CoveringBare(0.8, 0.01) # Try thin material
+ end
constr_sets = [
- WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 20.0, 0.75, 0.0, covering), # 2x6, 24" o.c. + R20
- WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 10.0, 0.75, 0.0, covering), # 2x6, 24" o.c. + R10
- WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 0.0, 0.75, 0.0, covering), # 2x6, 24" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.13, 0.0, 0.5, 0.0, covering), # 2x4, 16" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, 0.0, nil), # Fallback
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 20.0, 0.75, nil, covering), # 2x6, 24" o.c. + R20
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 10.0, 0.75, nil, covering), # 2x6, 24" o.c. + R10
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.10, 0.0, 0.75, nil, covering), # 2x6, 24" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.13, 0.0, 0.5, nil, covering), # 2x4, 16" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, nil, fallback_covering), # Fallback
]
end
assembly_r = frame_floor.insulation_assembly_r_value
@@ -908,10 +888,11 @@ def self.add_frame_floors(runner, model, spaces)
install_grade = 1
if frame_floor.is_ceiling
+
Constructions.apply_ceiling(runner, model, [surface], "#{frame_floor.id} construction",
cavity_r, install_grade,
- constr_set.stud.thick_in, constr_set.framing_factor,
- constr_set.stud.thick_in, constr_set.drywall_thick_in,
+ constr_set.rigid_r, constr_set.framing_factor,
+ constr_set.stud.thick_in, constr_set.mat_int_finish,
inside_film, outside_film)
else # Floor
@@ -919,7 +900,7 @@ def self.add_frame_floors(runner, model, spaces)
cavity_r, install_grade,
constr_set.framing_factor, constr_set.stud.thick_in,
constr_set.osb_thick_in, constr_set.rigid_r,
- constr_set.exterior_material, inside_film, outside_film)
+ constr_set.mat_ext_finish, inside_film, outside_film)
end
Constructions.check_surface_assembly_rvalue(runner, [surface], inside_film, outside_film, assembly_r, match)
@@ -1054,24 +1035,22 @@ def self.add_foundation_walls_slabs(runner, model, spaces)
# Apply construction
wall_type = HPXML::WallTypeConcrete
- if foundation_wall.is_thermal_boundary
- drywall_thick_in = 0.5
- else
- drywall_thick_in = 0.0
- end
inside_film = Material.AirFilmVertical
outside_film = Material.AirFilmVertical
assembly_r = foundation_wall.insulation_assembly_r_value
+ mat_int_finish = Material.InteriorFinishMaterial(foundation_wall.interior_finish_type, foundation_wall.interior_finish_thickness)
if assembly_r.nil?
concrete_thick_in = foundation_wall.thickness
int_r = foundation_wall.insulation_interior_r_value
ext_r = foundation_wall.insulation_exterior_r_value
- assembly_r = int_r + ext_r + Material.Concrete(concrete_thick_in).rvalue + Material.GypsumWall(drywall_thick_in).rvalue + inside_film.rvalue + outside_film.rvalue
+ mat_concrete = Material.Concrete(concrete_thick_in)
+ mat_int_finish_rvalue = mat_int_finish.nil? ? 0.0 : mat_int_finish.rvalue
+ assembly_r = int_r + ext_r + mat_concrete.rvalue + mat_int_finish_rvalue + inside_film.rvalue + outside_film.rvalue
end
mat_ext_finish = nil
- Constructions.apply_wall_construction(runner, model, [surface], foundation_wall, foundation_wall.id, wall_type, assembly_r,
- drywall_thick_in, inside_film, outside_film, mat_ext_finish)
+ Constructions.apply_wall_construction(runner, model, [surface], foundation_wall.id, wall_type, assembly_r,
+ mat_int_finish, inside_film, outside_film, mat_ext_finish, nil, nil)
end
end
end
@@ -1115,22 +1094,20 @@ def self.add_foundation_wall(runner, model, spaces, foundation_wall, slab_frac,
set_surface_interior(model, spaces, surface, foundation_wall)
set_surface_exterior(model, spaces, surface, foundation_wall)
- if foundation_wall.is_thermal_boundary
- drywall_thick_in = 0.5
- else
- drywall_thick_in = 0.0
- end
concrete_thick_in = foundation_wall.thickness
assembly_r = foundation_wall.insulation_assembly_r_value
+ mat_int_finish = Material.InteriorFinishMaterial(foundation_wall.interior_finish_type, foundation_wall.interior_finish_thickness)
if not assembly_r.nil?
ext_rigid_height = height
ext_rigid_offset = 0.0
inside_film = Material.AirFilmVertical
- ext_rigid_r = assembly_r - Material.Concrete(concrete_thick_in).rvalue - Material.GypsumWall(drywall_thick_in).rvalue - inside_film.rvalue
+ mat_concrete = Material.Concrete(concrete_thick_in)
+ mat_int_finish_rvalue = mat_int_finish.nil? ? 0.0 : mat_int_finish.rvalue
+ ext_rigid_r = assembly_r - mat_concrete.rvalue - mat_int_finish_rvalue - inside_film.rvalue
int_rigid_r = 0.0
- if ext_rigid_r < 0 # Try without drywall
- drywall_thick_in = 0.0
- ext_rigid_r = assembly_r - Material.Concrete(concrete_thick_in).rvalue - Material.GypsumWall(drywall_thick_in).rvalue - inside_film.rvalue
+ if ext_rigid_r < 0 # Try without interior finish
+ mat_int_finish = nil
+ ext_rigid_r = assembly_r - mat_concrete.rvalue - inside_film.rvalue
end
if (ext_rigid_r > 0) && (ext_rigid_r < 0.1)
ext_rigid_r = 0.0 # Prevent tiny strip of insulation
@@ -1152,7 +1129,7 @@ def self.add_foundation_wall(runner, model, spaces, foundation_wall, slab_frac,
Constructions.apply_foundation_wall(runner, model, [surface], "#{foundation_wall.id} construction",
ext_rigid_offset, int_rigid_offset, ext_rigid_height, int_rigid_height,
- ext_rigid_r, int_rigid_r, drywall_thick_in, concrete_thick_in, height_ag)
+ ext_rigid_r, int_rigid_r, mat_int_finish, concrete_thick_in, height_ag)
if not assembly_r.nil?
Constructions.check_surface_assembly_rvalue(runner, [surface], inside_film, nil, assembly_r, match)
@@ -1204,7 +1181,11 @@ def self.add_foundation_slab(runner, model, spaces, slab, slab_exp_perim,
end
slab_whole_r = 0
end
- slab_gap_r = slab_under_r
+ if slab_under_r + slab_whole_r > 0
+ slab_gap_r = 5.0 # Assume gap insulation when insulation under slab is present
+ else
+ slab_gap_r = 0
+ end
mat_carpet = nil
if (slab.carpet_fraction > 0) && (slab.carpet_r_value > 0)
@@ -1288,16 +1269,16 @@ def self.add_thermal_mass(runner, model, spaces)
cfa_basement = @hpxml.slabs.select { |s| s.interior_adjacent_to == HPXML::LocationBasementConditioned }.map { |s| s.area }.sum(0.0)
if @apply_ashrae140_assumptions
# 1024 ft2 of interior partition wall mass, no furniture mass
- drywall_thick_in = 0.5
+ mat_int_finish = Material.InteriorFinishMaterial(HPXML::InteriorFinishGypsumBoard, 0.5)
partition_frac_of_cfa = (1024.0 * 2) / @cfa # Ratio of exposed partition wall area (both sides) to conditioned floor area
basement_frac_of_cfa = cfa_basement / @cfa
- Constructions.apply_partition_walls(runner, model, 'PartitionWallConstruction', drywall_thick_in, partition_frac_of_cfa,
+ Constructions.apply_partition_walls(runner, model, 'PartitionWallConstruction', mat_int_finish, partition_frac_of_cfa,
basement_frac_of_cfa, @cond_bsmnt_surfaces, spaces[HPXML::LocationLivingSpace])
else
- drywall_thick_in = 0.5
+ mat_int_finish = Material.InteriorFinishMaterial(HPXML::InteriorFinishGypsumBoard, 0.5)
partition_frac_of_cfa = 1.0 # Ratio of exposed partition wall area (both sides) to conditioned floor area
basement_frac_of_cfa = cfa_basement / @cfa
- Constructions.apply_partition_walls(runner, model, 'PartitionWallConstruction', drywall_thick_in, partition_frac_of_cfa,
+ Constructions.apply_partition_walls(runner, model, 'PartitionWallConstruction', mat_int_finish, partition_frac_of_cfa,
basement_frac_of_cfa, @cond_bsmnt_surfaces, spaces[HPXML::LocationLivingSpace])
mass_lb_per_sqft = 8.0
@@ -1308,9 +1289,6 @@ def self.add_thermal_mass(runner, model, spaces)
end
end
- def self.add_neighbors(runner, model, length)
- end
-
def self.add_shading_schedule(runner, model, weather)
# Use BAHSP cooling season, and not year-round or user-specified cooling season, to ensure windows use appropriate interior shading factors
default_heating_months, @default_cooling_months = HVAC.get_default_heating_and_cooling_seasons(weather)
@@ -1516,24 +1494,20 @@ def self.apply_adiabatic_construction(runner, model, surfaces, type)
return if surfaces.empty?
if type == 'wall'
- Constructions.apply_wood_stud_wall(runner, model, surfaces, nil, 'AdiabaticWallConstruction',
- 0, 1, 3.5, true, 0.1, 0.5, 0, 99,
- Material.ExteriorFinishMaterial(HPXML::SidingTypeWood, 0.90, 0.75),
- 0,
- Material.AirFilmVertical,
- Material.AirFilmVertical)
+ mat_int_finish = Material.InteriorFinishMaterial(HPXML::InteriorFinishGypsumBoard, 0.5)
+ mat_ext_finish = Material.ExteriorFinishMaterial(HPXML::SidingTypeWood)
+ Constructions.apply_wood_stud_wall(runner, model, surfaces, 'AdiabaticWallConstruction',
+ 0, 1, 3.5, true, 0.1, mat_int_finish, 0, 99, mat_ext_finish,
+ Material.AirFilmVertical, Material.AirFilmVertical)
elsif type == 'floor'
Constructions.apply_floor(runner, model, surfaces, 'AdiabaticFloorConstruction',
- 0, 1, 0.07, 5.5, 0.75, 99,
- Material.CoveringBare,
- Material.AirFilmFloorReduced,
- Material.AirFilmFloorReduced)
+ 0, 1, 0.07, 5.5, 0.75, 99, Material.CoveringBare,
+ Material.AirFilmFloorReduced, Material.AirFilmFloorReduced)
elsif type == 'roof'
Constructions.apply_open_cavity_roof(runner, model, surfaces, 'AdiabaticRoofConstruction',
0, 1, 7.25, 0.07, 7.25, 0.75, 99,
- Material.RoofMaterial(HPXML::RoofTypeAsphaltShingles, 0.90, 0.75),
- false,
- Material.AirFilmOutside,
+ Material.RoofMaterial(HPXML::RoofTypeAsphaltShingles),
+ false, Material.AirFilmOutside,
Material.AirFilmRoof(Geometry.get_roof_pitch(surfaces)), nil)
end
end
diff --git a/HPXMLtoOpenStudio/measure.xml b/HPXMLtoOpenStudio/measure.xml
index b84d1cefac..f4c65ca99e 100644
--- a/HPXMLtoOpenStudio/measure.xml
+++ b/HPXMLtoOpenStudio/measure.xml
@@ -1,11 +1,10 @@
3.0
- Unable to extract OpenStudio::Measure::OSMeasure object from /mnt/c/git/openstudio-hpxml/HPXMLtoOpenStudio/measure.rb. The script should contain a class that derives from OpenStudio::Measure::OSMeasure and should close with a line stating the class name followed by .new.registerWithApplication.
hpxm_lto_openstudio
b1543b30-9465-45ff-ba04-1d1f85e763bc
- c929f134-7b14-43a4-a9ee-11bb8d27da1f
- 20210513T171148Z
+ ae76a9bd-63a8-473f-a633-cfe27ceb3be7
+ 20210707T011559Z
D8922A73
HPXMLtoOpenStudio
HPXML to OpenStudio Translator
@@ -17,31 +16,22 @@
HPXML File Path
Absolute/relative path of the HPXML file.
String
-
true
false
-
-
-
output_dir
Directory for Output Files
Absolute/relative path for the output files directory.
String
-
true
false
-
-
-
debug
Debug Mode?
If true: 1) Writes in.osm file, 2) Generates additional log output, and 3) Creates all EnergyPlus output files.
Boolean
-
false
false
false
@@ -55,15 +45,12 @@
false
-
-
add_component_loads
Add component loads?
If true, adds the calculation of heating/cooling component loads (not enabled by default for faster performance).
Boolean
-
false
false
false
@@ -77,15 +64,12 @@
false
-
-
skip_validation
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.
Boolean
-
false
false
false
@@ -99,20 +83,14 @@
false
-
-
building_id
BuildingID
The ID of the HPXML Building. Only required if there are multiple Building elements in the HPXML file.
String
-
false
false
-
-
-
@@ -149,18 +127,6 @@
resource
38ED685E
-
- util.rb
- rb
- resource
- 7DAA5F02
-
-
- materials.rb
- rb
- resource
- F39A6C6A
-
HPXML.xsd
xsd
@@ -378,10 +344,22 @@
19007457
- test_hotwater_appliance.rb
+ energyplus.rb
+ rb
+ resource
+ CA9A2E46
+
+
+ test_generator.rb
rb
test
- E962DB16
+ 19007457
+
+
+ test_lighting.rb
+ rb
+ test
+ CC725437
simcontrols.rb
@@ -390,16 +368,16 @@
C18610A9
- test_water_heater.rb
+ generator.rb
rb
- test
- C8BB1267
+ resource
+ FC0A4F2E
- validator.rb
+ util.rb
rb
resource
- BF53D293
+ 7DAA5F02
test_validation.rb
@@ -408,183 +386,207 @@
4C662AE0
- airflow.rb
+ test_hotwater_appliance.rb
rb
- resource
- 99EB6060
+ test
+ E962DB16
- geometry.rb
+ util.rb
+ rb
+ test
+ B185ACE7
+
+
+ weather.rb
rb
resource
- 3AB6308D
+ 9BDDB2C2
- generator.rb
+ pv.rb
rb
resource
- FC0A4F2E
+ AF98955A
- meta_measure.rb
+ validator.rb
rb
resource
- 2ADA335B
+ BF53D293
- waterheater.rb
+ geometry.rb
rb
resource
- A9868999
+ 3AB6308D
- xmlhelper.rb
+ constants.rb
rb
resource
- CD54C911
+ F895FFF9
- pv.rb
+ lighting.rb
rb
resource
- AF98955A
+ C028223B
- test_airflow.rb
+ lu_hvac_equipment_efficiency.csv
+ csv
+ resource
+ 69BCF0A4
+
+
+ lu_water_heater_efficiency.csv
+ csv
+ resource
+ 9EC3B4D6
+
+
+ test_hvac.rb
rb
test
- 9219EDE1
+ 762FA454
- test_enclosure.rb
+ test_airflow.rb
rb
test
- 2A7EF627
+ 0E51466A
- constructions.rb
+ xmlhelper.rb
rb
resource
- 2BDDE11F
+ B15B5FA9
- energyplus.rb
+ waterheater.rb
rb
resource
- CA9A2E46
+ 99179FC2
- version.rb
- rb
+ BaseElements.xsd
+ xsd
resource
- 1277B716
+ F2C9CCA9
- hvac_sizing.rb
- rb
+ HPXMLDataTypes.xsd
+ xsd
resource
- 25E2DA28
+ 4A516EBC
- util.rb
+ test_water_heater.rb
rb
test
- B185ACE7
+ B415B698
- minitest_helper.rb
+ meta_measure.rb
rb
resource
- F3E1BE58
+ 6B409E9A
- weather.rb
+ minitest_helper.rb
rb
resource
- 9BDDB2C2
+ 02AE0222
schedules.rb
rb
resource
- 38A6C75D
+ 13B33774
- lighting.rb
+ version.rb
rb
resource
- C028223B
+ 9A3BAE35
- constants.rb
+ airflow.rb
rb
resource
- F895FFF9
+ A46E38D5
- HPXMLDataTypes.xsd
- xsd
+ hvac.rb
+ rb
resource
- CA8F8CC3
+ 291D4757
- BaseElements.xsd
- xsd
+ hvac_sizing.rb
+ rb
resource
- FD773DB8
+ 99C0D296
HPXMLvalidator.xml
xml
resource
- E14BA8AB
+ A31AF9C8
- test_hvac.rb
+ EPvalidator.xml
+ xml
+ resource
+ B671C9DB
+
+
+ test_defaults.rb
rb
test
- F3E85A51
+ D3FDBEF3
-
- OpenStudio
- 2.1.1
- 2.1.1
-
- measure.rb
+ hpxml_defaults.rb
rb
- script
- 76BEB7AB
+ resource
+ 4019B4D2
- hvac.rb
+ hpxml.rb
rb
resource
- ECBD9662
+ B03091CB
- test_defaults.rb
+ materials.rb
rb
- test
- BB81D4C0
+ resource
+ D9DFAD54
- hpxml_defaults.rb
+
+ OpenStudio
+ 3.2.0
+ 3.2.0
+
+ measure.rb
rb
- resource
- EDF78BC3
+ script
+ 3B94C81F
- EPvalidator.xml
- xml
+ constructions.rb
+ rb
resource
- 8EE695FA
+ 9A3E2816
- hpxml.rb
+ test_enclosure.rb
rb
- resource
- 4BBE084E
+ test
+ 1A78BA60
diff --git a/HPXMLtoOpenStudio/resources/BaseElements.xsd b/HPXMLtoOpenStudio/resources/BaseElements.xsd
index 97f3eeaeb4..44cb94ebea 100644
--- a/HPXMLtoOpenStudio/resources/BaseElements.xsd
+++ b/HPXMLtoOpenStudio/resources/BaseElements.xsd
@@ -215,6 +215,19 @@
+
+
+
+
+
+ [in]
+
+
+
+
+
+
+
@@ -451,7 +464,7 @@
Portable room dehumidifiers are typically used to dehumidify a single room or space and can be easily moved to where they are needed. Whole-home dehumidifiers are typically installed to use your home’s air ducts to dehumidify one or more rooms and are often permanent. Some dehumifiers can operate in both configurations by means of a ducting kit.
-
+
[L/kWh] DEPRECATED. This will be removed in v4.0. Use EnergyFactor or IntegratedEnergyFactor instead.
@@ -700,13 +713,13 @@
+
DEPRECATION WARNING: AttachedToFrameFloor will be deprecated in the future. Use AttachedToCeiling instead.
-
@@ -793,13 +806,9 @@
-
-
-
- DEPRECATION WARNING: AttachedToFrameFloor will be deprecated in the future. Use AttachedToCeiling instead.
-
-
+
+
@@ -829,7 +838,7 @@
-
+
[sq.ft.] Surface area of the roof itself
@@ -845,6 +854,7 @@
+
@@ -873,8 +883,8 @@
-
-
+
+
[sq.ft.]
@@ -925,8 +935,8 @@
-
-
+
+
@@ -950,6 +960,7 @@
+
@@ -981,8 +992,8 @@
-
-
+
+
@@ -1021,6 +1032,7 @@
+
[ft] Vertical distance from top of foundation wall to top of insulation.
@@ -1052,8 +1064,8 @@
-
-
+
+
@@ -1061,6 +1073,7 @@
[sq.ft.]
+
@@ -1085,8 +1098,8 @@
-
-
+
+
@@ -1095,6 +1108,7 @@
[sq.ft.]
+
@@ -1116,7 +1130,7 @@
-
+
[sq.ft.] Area of the slab
@@ -1256,7 +1270,11 @@
-
+
+
+ DEPRECATION WARNING: The "storm" choice will be deprecated in the future; use the StormDoor element instead.
+
+
@@ -1594,6 +1612,11 @@
with the water heater fully heated.
+
+
+ A water heater's usage bin is derived from its First Hour Rating (FHR) as part of the Uniform Energy Factor (UEF) testing procedures.
+
+
[gal per minute] The amount of gallons per minute of hot water that can be supplied by an instantaneous water heater while maintaining a
@@ -3554,7 +3577,6 @@
Consumer’s Directory of Certified Efficiency Ratings.
-
@@ -3631,6 +3653,7 @@
[grams per hour] from EPA label http://www.epa.gov/compliance/monitoring/programs/caa/woodheaters.html
+
@@ -3650,6 +3673,10 @@
+
+
+
+
@@ -4953,6 +4980,7 @@
+
DEPRECATED. This will be removed in v4.0. Use FractionOperable element instead.
diff --git a/HPXMLtoOpenStudio/resources/EPvalidator.xml b/HPXMLtoOpenStudio/resources/EPvalidator.xml
index c63d72eb8b..eabaeeb96c 100644
--- a/HPXMLtoOpenStudio/resources/EPvalidator.xml
+++ b/HPXMLtoOpenStudio/resources/EPvalidator.xml
@@ -145,7 +145,7 @@
[NeighborBuilding]
- Expected 1 element(s) for xpath: Azimuth
+ Expected 1 or more element(s) for xpath: Azimuth | Orientation
Expected 1 element(s) for xpath: Distance
Expected 0 or 1 element(s) for xpath: Height
@@ -222,11 +222,14 @@
Expected 1 element(s) for xpath: InteriorAdjacentTo
Expected InteriorAdjacentTo to be 'attic - vented' or 'attic - unvented' or 'living space' or 'garage'
Expected 1 element(s) for xpath: Area
- Expected 0 or 1 element(s) for xpath: Azimuth
+ Expected 0 or more element(s) for xpath: Azimuth | Orientation
Expected 0 or 1 element(s) for xpath: RoofType
Expected RoofType to be 'asphalt or fiberglass shingles' or 'wood shingles or shakes' or 'slate or tile shingles' or 'metal surfacing'
- Expected 1 or more element(s) for xpath: SolarAbsorptance | RoofColor
+ Expected 0 or more element(s) for xpath: RoofColor | SolarAbsorptance
Expected 0 or 1 element(s) for xpath: Emittance
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Type
+ Expected InteriorFinish/Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'none'
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Thickness
Expected 1 element(s) for xpath: Pitch
Expected 0 or 1 element(s) for xpath: RadiantBarrier
Expected 1 element(s) for xpath: Insulation/SystemIdentifier
@@ -244,7 +247,7 @@
[RadiantBarrier]
- Expected 1 element(s) for xpath: RadiantBarrierGrade
+ Expected 0 or 1 element(s) for xpath: RadiantBarrierGrade
@@ -257,10 +260,10 @@
Expected 1 element(s) for xpath: InteriorAdjacentTo
Expected InteriorAdjacentTo to be 'living space' or 'attic - vented' or 'attic - unvented' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace - vented' or 'crawlspace - unvented' or 'garage'
Expected 1 element(s) for xpath: Area
- Expected 0 or 1 element(s) for xpath: Azimuth
+ Expected 0 or more element(s) for xpath: Azimuth | Orientation
Expected 0 or 1 element(s) for xpath: Siding
- Expected Siding to be 'wood siding' or 'vinyl siding' or 'stucco' or 'fiber cement siding' or 'brick veneer' or 'aluminum siding'
- Expected 1 or more element(s) for xpath: SolarAbsorptance | Color
+ Expected Siding to be 'wood siding' or 'vinyl siding' or 'stucco' or 'fiber cement siding' or 'brick veneer' or 'aluminum siding' or 'none'
+ Expected 0 or more element(s) for xpath: Color | SolarAbsorptance
Expected 0 or 1 element(s) for xpath: Emittance
Expected 1 element(s) for xpath: Insulation/SystemIdentifier
Expected 1 element(s) for xpath: Insulation/AssemblyEffectiveRValue
@@ -277,11 +280,14 @@
Expected InteriorAdjacentTo to be 'living space' or 'attic - vented' or 'attic - unvented' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace - vented' or 'crawlspace - unvented' or 'garage'
Expected 1 element(s) for xpath: WallType[WoodStud | DoubleWoodStud | ConcreteMasonryUnit | StructurallyInsulatedPanel | InsulatedConcreteForms | SteelFrame | SolidConcrete | StructuralBrick | StrawBale | Stone | LogWall | Adobe]
Expected 1 element(s) for xpath: Area
- Expected 0 or 1 element(s) for xpath: Azimuth
+ Expected 0 or more element(s) for xpath: Azimuth | Orientation
Expected 0 or 1 element(s) for xpath: Siding
- Expected Siding to be 'wood siding' or 'vinyl siding' or 'stucco' or 'fiber cement siding' or 'brick veneer' or 'aluminum siding'
- Expected 1 or more element(s) for xpath: SolarAbsorptance | Color
+ Expected Siding to be 'wood siding' or 'vinyl siding' or 'stucco' or 'fiber cement siding' or 'brick veneer' or 'aluminum siding' or 'none'
+ Expected 0 or more element(s) for xpath: Color | SolarAbsorptance
Expected 0 or 1 element(s) for xpath: Emittance
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Type
+ Expected InteriorFinish/Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'none'
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Thickness
Expected 1 element(s) for xpath: Insulation/SystemIdentifier
Expected 1 element(s) for xpath: Insulation/AssemblyEffectiveRValue
@@ -296,9 +302,12 @@
Expected 1 element(s) for xpath: InteriorAdjacentTo
Expected InteriorAdjacentTo to be 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace - vented' or 'crawlspace - unvented' or 'garage'
Expected 1 element(s) for xpath: Height
- Expected 1 element(s) for xpath: Area
- Expected 0 or 1 element(s) for xpath: Azimuth
+ Expected 1 or more element(s) for xpath: Area | Length
+ Expected 0 or more element(s) for xpath: Azimuth | Orientation
Expected 0 or 1 element(s) for xpath: Thickness
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Type
+ Expected InteriorFinish/Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'none'
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Thickness
Expected 1 element(s) for xpath: DepthBelowGrade
Expected DepthBelowGrade to be less than or equal to Height
Expected 1 element(s) for xpath: Insulation/SystemIdentifier
@@ -319,8 +328,9 @@
[FoundationWallInsulationLayer]
Expected 1 element(s) for xpath: NominalRValue
- Expected 1 element(s) for xpath: extension/DistanceToTopOfInsulation
- Expected 1 element(s) for xpath: extension/DistanceToBottomOfInsulation
+
+ Expected 0 or 1 element(s) for xpath: extension/DistanceToTopOfInsulation
+ Expected 0 or 1 element(s) for xpath: extension/DistanceToBottomOfInsulation
Expected extension/DistanceToBottomOfInsulation to be greater than or equal to extension/DistanceToTopOfInsulation
Expected extension/DistanceToBottomOfInsulation to be less than or equal to ../../Height
@@ -335,6 +345,9 @@
Expected 1 element(s) for xpath: InteriorAdjacentTo
Expected InteriorAdjacentTo to be 'living space' or 'attic - vented' or 'attic - unvented' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace - vented' or 'crawlspace - unvented' or 'garage'
Expected 1 element(s) for xpath: Area
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Type
+ Expected InteriorFinish/Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'none'
+ Expected 0 or 1 element(s) for xpath: InteriorFinish/Thickness
Expected 1 element(s) for xpath: Insulation/SystemIdentifier
Expected 1 element(s) for xpath: Insulation/AssemblyEffectiveRValue
@@ -375,7 +388,7 @@
Expected 1 element(s) for xpath: SystemIdentifier
Expected 1 element(s) for xpath: Area
- Expected 1 element(s) for xpath: Azimuth
+ Expected 1 or more element(s) for xpath: Azimuth | Orientation
Expected 1 element(s) for xpath: UFactor
Expected 1 element(s) for xpath: SHGC
Expected 0 or 1 element(s) for xpath: ExteriorShading/SummerShadingCoefficient
@@ -403,7 +416,7 @@
Expected 1 element(s) for xpath: SystemIdentifier
Expected 1 element(s) for xpath: Area
- Expected 1 element(s) for xpath: Azimuth
+ Expected 1 or more element(s) for xpath: Azimuth | Orientation
Expected 1 element(s) for xpath: UFactor
Expected 1 element(s) for xpath: SHGC
Expected 0 or 1 element(s) for xpath: ExteriorShading/SummerShadingCoefficient
@@ -420,7 +433,7 @@
Expected 1 element(s) for xpath: SystemIdentifier
Expected 1 element(s) for xpath: AttachedToWall
Expected 1 element(s) for xpath: Area
- Expected 1 element(s) for xpath: Azimuth
+ Expected 0 or more element(s) for xpath: Azimuth | Orientation
Expected 1 element(s) for xpath: RValue
@@ -442,7 +455,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
+ Expected 0 or 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
Expected AnnualHeatingEfficiency[Units="Percent"]/Value to be less than or equal to 1
@@ -455,7 +468,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value
+ Expected 1 or more element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value | YearInstalled
Expected AnnualHeatingEfficiency[Units="AFUE"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWattsPerCFM
Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0
@@ -471,7 +484,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value
+ Expected 1 or more element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value | YearInstalled
Expected AnnualHeatingEfficiency[Units="AFUE"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -485,7 +498,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value
+ Expected 1 or more element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value | YearInstalled
Expected AnnualHeatingEfficiency[Units="AFUE"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -499,7 +512,7 @@
Expected 1 element(s) for xpath: DistributionSystem
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value
+ Expected 1 or more element(s) for xpath: AnnualHeatingEfficiency[Units="AFUE"]/Value | YearInstalled
Expected AnnualHeatingEfficiency[Units="AFUE"]/Value to be less than or equal to 1
@@ -548,7 +561,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
+ Expected 0 or 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
Expected AnnualHeatingEfficiency[Units="Percent"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -562,7 +575,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
+ Expected 0 or 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
Expected AnnualHeatingEfficiency[Units="Percent"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -576,7 +589,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
+ Expected 0 or 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
Expected AnnualHeatingEfficiency[Units="Percent"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -590,7 +603,7 @@
Expected 1 element(s) for xpath: HeatingSystemFuel
Expected HeatingSystemFuel to be 'electricity' or 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
+ Expected 0 or 1 element(s) for xpath: AnnualHeatingEfficiency[Units="Percent"]/Value
Expected AnnualHeatingEfficiency[Units="Percent"]/Value to be less than or equal to 1
Expected 0 or 1 element(s) for xpath: extension/FanPowerWatts
Expected extension/FanPowerWatts to be greater than or equal to 0
@@ -618,7 +631,7 @@
Expected 0 or 1 element(s) for xpath: CoolingCapacity
Expected 0 or 1 element(s) for xpath: CompressorType
Expected CompressorType to be 'single stage' or 'two stage' or 'variable speed'
- Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value
+ Expected 1 or more element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value | YearInstalled
Expected 0 or 1 element(s) for xpath: SensibleHeatFraction
Expected 0 or 1 element(s) for xpath: extension/FanPowerWattsPerCFM
Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0
@@ -634,7 +647,7 @@
Expected 0 element(s) for xpath: DistributionSystem
Expected 0 or 1 element(s) for xpath: CoolingCapacity
- Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="EER"]/Value
+ Expected 1 or more element(s) for xpath: AnnualCoolingEfficiency[Units="EER" or Units="CEER"]/Value | YearInstalled
Expected 0 or 1 element(s) for xpath: SensibleHeatFraction
@@ -652,22 +665,16 @@
[CoolingSystemType=MiniSplitAC]
Expected 0 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="regular velocity"] | ../../HVACDistribution/DistributionSystemType/Other[text()="DSE"]
- Expected 0 or 1 element(s) for xpath: DistributionSystem
+ Expected 0 or 1 element(s) for xpath: DistributionSystem
Expected 0 or 1 element(s) for xpath: CoolingCapacity
Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value
Expected 0 or 1 element(s) for xpath: SensibleHeatFraction
- Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
- Expected extension/ChargeDefectRatio to be greater than -1
-
-
-
-
- [CoolingSystemType=DuctedMiniSplitAC]
-
Expected 0 or 1 element(s) for xpath: extension/FanPowerWattsPerCFM
Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0
Expected 0 or 1 element(s) for xpath: extension/AirflowDefectRatio
Expected extension/AirflowDefectRatio to be greater than -1
+ Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
+ Expected extension/ChargeDefectRatio to be greater than -1
@@ -746,8 +753,8 @@
Expected 0 or 1 element(s) for xpath: CoolingSensibleHeatFraction
Expected 1 element(s) for xpath: FractionHeatLoadServed
Expected 1 element(s) for xpath: FractionCoolLoadServed
- Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value
- Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="HSPF"]/Value
+ Expected 1 or more element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value | YearInstalled
+ Expected 1 or more element(s) for xpath: AnnualHeatingEfficiency[Units="HSPF"]/Value | YearInstalled
Expected 0 or 1 element(s) for xpath: extension/FanPowerWattsPerCFM
Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0
Expected 0 or 1 element(s) for xpath: extension/AirflowDefectRatio
@@ -761,7 +768,7 @@
[HeatPumpType=MiniSplit]
Expected 0 or more element(s) for xpath: ../../HVACDistribution/DistributionSystemType/AirDistribution/AirDistributionType[text()="regular velocity"] | ../../HVACDistribution/DistributionSystemType/Other[text()="DSE"]
- Expected 0 or 1 element(s) for xpath: DistributionSystem
+ Expected 0 or 1 element(s) for xpath: DistributionSystem
Expected 0 or 1 element(s) for xpath: HeatingCapacity
Expected 0 or 1 element(s) for xpath: HeatingCapacity17F
Expected 0 or 1 element(s) for xpath: CoolingCapacity
@@ -770,21 +777,15 @@
Expected 1 element(s) for xpath: FractionCoolLoadServed
Expected 1 element(s) for xpath: AnnualCoolingEfficiency[Units="SEER"]/Value
Expected 1 element(s) for xpath: AnnualHeatingEfficiency[Units="HSPF"]/Value
- Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
- Expected extension/ChargeDefectRatio to be greater than -1
-
-
-
-
- [HeatPumpType=DuctedMiniSplit]
-
Expected 0 or 1 element(s) for xpath: extension/FanPowerWattsPerCFM
Expected extension/FanPowerWattsPerCFM to be greater than or equal to 0
Expected 0 or 1 element(s) for xpath: extension/AirflowDefectRatio
Expected extension/AirflowDefectRatio to be greater than -1
+ Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
+ Expected extension/ChargeDefectRatio to be greater than -1
-
+
[HeatPumpType=GroundSource]
@@ -806,10 +807,10 @@
Expected 0 or 1 element(s) for xpath: extension/AirflowDefectRatio
Expected extension/AirflowDefectRatio to be greater than -1
Expected 0 or 1 element(s) for xpath: extension/ChargeDefectRatio
- Expected extension/ChargeDefectRatio to be 0
+ Expected extension/ChargeDefectRatio to be greater than -1
-
+
[HeatPumpType=GroundSourceWithSharedLoop]
@@ -914,8 +915,8 @@
Expected AirDistributionType to be 'regular velocity' or 'gravity' or 'fan coil'
Expected 0 or more element(s) for xpath: Ducts
- Ducts are entirely within conditioned space but there is moderate leakage to the outside. Leakage to the outside is typically zero or near-zero in these situations, consider revising leakage values. Leakage will be modeled as heat lost to the ambient environment.
- Ducts are entirely within conditioned space but there is moderate leakage to the outside. Leakage to the outside is typically zero or near-zero in these situations, consider revising leakage values. Leakage will be modeled as heat lost to the ambient environment.
+ Ducts are entirely within conditioned space but there is moderate leakage to the outside. Leakage to the outside is typically zero or near-zero in these situations, consider revising leakage values. Leakage will be modeled as heat lost to the ambient environment.
+ Ducts are entirely within conditioned space but there is moderate leakage to the outside. Leakage to the outside is typically zero or near-zero in these situations, consider revising leakage values. Leakage will be modeled as heat lost to the ambient environment.
@@ -974,13 +975,27 @@
Expected 1 element(s) for xpath: DuctType
Expected DuctType to be 'supply' or 'return'
Expected 1 element(s) for xpath: DuctInsulationRValue
- Expected 0 or 2 element(s) for xpath: DuctSurfaceArea | DuctLocation
+ Expected 0 or 1 element(s) for xpath: DuctLocation
Expected DuctLocation to be 'living space' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace - vented' or 'crawlspace - unvented' or 'attic - vented' or 'attic - unvented' or 'garage' or 'exterior wall' or 'under slab' or 'roof deck' or 'outside' or 'other housing unit' or 'other heated space' or 'other multifamily buffer space' or 'other non-freezing space'
Expected 0 or 1 element(s) for xpath: ../NumberofReturnRegisters
Expected 1 element(s) for xpath: ../../../ConditionedFloorAreaServed
+
+ [HVACDuct=WithLocation]
+
+ Expected 1 or more element(s) for xpath: FractionDuctArea | DuctSurfaceArea
+
+
+
+
+ [HVACDuct=WithoutLocation]
+
+ Expected 0 element(s) for xpath: FractionDuctArea | DuctSurfaceArea
+
+
+
[MechanicalVentilation]
@@ -990,7 +1005,7 @@
Expected FanType to be 'energy recovery ventilator' or 'heat recovery ventilator' or 'exhaust only' or 'supply only' or 'balanced' or 'central fan integrated supply'
Expected 1 or more element(s) for xpath: TestedFlowRate | RatedFlowRate
Expected 0 or 1 element(s) for xpath: HoursInOperation
- Expected 1 element(s) for xpath: FanPower
+ Expected 0 or 1 element(s) for xpath: FanPower
@@ -1113,8 +1128,9 @@
Expected FuelType to be 'natural gas' or 'fuel oil' or 'fuel oil 1' or 'fuel oil 2' or 'fuel oil 4' or 'fuel oil 5/6' or 'diesel' or 'propane' or 'kerosene' or 'coal' or 'coke' or 'bituminous coal' or 'anthracite coal' or 'electricity' or 'wood' or 'wood pellets'
Expected 0 or 1 element(s) for xpath: TankVolume
Expected 0 or 1 element(s) for xpath: HeatingCapacity
- Expected 1 element(s) for xpath: UniformEnergyFactor | EnergyFactor
- Expected 1 or more element(s) for xpath: FirstHourRating | EnergyFactor
+ Expected 1 or more element(s) for xpath: UniformEnergyFactor | EnergyFactor | YearInstalled
+ Expected 0 or 1 element(s) for xpath: UniformEnergyFactor | EnergyFactor
+ Expected 0 or more element(s) for xpath: UsageBin | FirstHourRating
Expected UniformEnergyFactor to be less than 1
Expected EnergyFactor to be less than 1
Expected 0 or 1 element(s) for xpath: RecoveryEfficiency
@@ -1140,7 +1156,7 @@
Expected 1 element(s) for xpath: FuelType[text()="electricity"]
Expected 1 element(s) for xpath: TankVolume
Expected 1 element(s) for xpath: UniformEnergyFactor | EnergyFactor
- Expected 1 or more element(s) for xpath: FirstHourRating | EnergyFactor
+ Expected 0 or more element(s) for xpath: UsageBin | FirstHourRating
Expected UniformEnergyFactor to be greater than 1
Expected EnergyFactor to be greater than 1
Expected 0 or 1 element(s) for xpath: WaterHeaterInsulation/Jacket/JacketRValue
@@ -1252,7 +1268,7 @@
Expected CollectorLoopType to be 'liquid indirect' or 'liquid direct' or 'passive thermosyphon'
Expected 1 element(s) for xpath: CollectorType
Expected CollectorType to be 'single glazing black' or 'double glazing black' or 'evacuated tube' or 'integrated collector storage'
- Expected 1 element(s) for xpath: CollectorAzimuth
+ Expected 1 or more element(s) for xpath: CollectorAzimuth | CollectorOrientation
Expected 1 element(s) for xpath: CollectorTilt
Expected 1 element(s) for xpath: CollectorRatedOpticalEfficiency
Expected 1 element(s) for xpath: CollectorRatedThermalLosses
@@ -1279,7 +1295,7 @@
Expected ModuleType to be 'standard' or 'premium' or 'thin film'
Expected 0 or 1 element(s) for xpath: Tracking
Expected Tracking to be 'fixed' or '1-axis' or '1-axis backtracked' or '2-axis'
- Expected 1 element(s) for xpath: ArrayAzimuth
+ Expected 1 or more element(s) for xpath: ArrayAzimuth | ArrayOrientation
Expected 1 element(s) for xpath: ArrayTilt
Expected 1 element(s) for xpath: MaxPowerOutput
Expected 0 or 1 element(s) for xpath: InverterEfficiency
diff --git a/HPXMLtoOpenStudio/resources/HPXMLDataTypes.xsd b/HPXMLtoOpenStudio/resources/HPXMLDataTypes.xsd
index c71c8c4cd4..beacb7a815 100644
--- a/HPXMLtoOpenStudio/resources/HPXMLDataTypes.xsd
+++ b/HPXMLtoOpenStudio/resources/HPXMLDataTypes.xsd
@@ -1143,37 +1143,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -1192,6 +1162,7 @@
+
@@ -1203,12 +1174,12 @@
-
+
DEPRECATION WARNING: Choices "other housing unit above" and "other housing unit below" will be deprecated in the future. Use Ceiling vs FrameFloor to describe whether "other housing unit" is above or below the given surface.
-
+
@@ -1847,6 +1818,7 @@
+
@@ -3476,6 +3448,7 @@
+
@@ -3485,6 +3458,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4329,6 +4319,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -4741,4 +4746,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HPXMLtoOpenStudio/resources/HPXMLvalidator.xml b/HPXMLtoOpenStudio/resources/HPXMLvalidator.xml
index de62808525..f97ad8cba2 100644
--- a/HPXMLtoOpenStudio/resources/HPXMLvalidator.xml
+++ b/HPXMLtoOpenStudio/resources/HPXMLvalidator.xml
@@ -49,7 +49,7 @@
Expected Value to be greater than 0
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
Expected Azimuth to be less than 360
@@ -64,17 +64,21 @@
Expected RadiantBarrierGrade to be less than or equal to 3
Expected id attribute for SystemIdentifier
+
+ Expected Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'other' or 'none'
+ Expected Thickness to be greater than or equal to 0
+
Expected AssemblyEffectiveRValue to be greater than 0
Expected id attribute for SystemIdentifier
- Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
Expected Azimuth to be less than 360
- Expected Siding to be 'wood siding' or 'stucco' or 'synthetic stucco' or 'vinyl siding' or 'aluminum siding' or 'brick veneer' or 'asbestos siding' or 'fiber cement siding' or 'composite shingle siding' or 'masonite siding' or 'other'
+ Expected Siding to be 'wood siding' or 'stucco' or 'synthetic stucco' or 'vinyl siding' or 'aluminum siding' or 'brick veneer' or 'asbestos siding' or 'fiber cement siding' or 'composite shingle siding' or 'masonite siding' or 'other' or 'none'
Expected Color to be 'light' or 'medium' or 'medium dark' or 'dark' or 'reflective'
Expected SolarAbsorptance to be greater than or equal to 0
Expected SolarAbsorptance to be less than or equal to 1
@@ -87,12 +91,12 @@
Expected id attribute for SystemIdentifier
- Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
Expected Azimuth to be less than 360
- Expected Siding to be 'wood siding' or 'stucco' or 'synthetic stucco' or 'vinyl siding' or 'aluminum siding' or 'brick veneer' or 'asbestos siding' or 'fiber cement siding' or 'composite shingle siding' or 'masonite siding' or 'other'
+ Expected Siding to be 'wood siding' or 'stucco' or 'synthetic stucco' or 'vinyl siding' or 'aluminum siding' or 'brick veneer' or 'asbestos siding' or 'fiber cement siding' or 'composite shingle siding' or 'masonite siding' or 'other' or 'none'
Expected Color to be 'light' or 'medium' or 'medium dark' or 'dark' or 'reflective'
Expected SolarAbsorptance to be greater than or equal to 0
Expected SolarAbsorptance to be less than or equal to 1
@@ -100,13 +104,18 @@
Expected Emittance to be less than or equal to 1
Expected id attribute for SystemIdentifier
+
+ Expected Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'other' or 'none'
+ Expected Thickness to be greater than or equal to 0
+
Expected AssemblyEffectiveRValue to be greater than 0
Expected id attribute for SystemIdentifier
- Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
+ Expected Length to be greater than or equal to 0
Expected Height to be greater than or equal to 0
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
@@ -115,6 +124,10 @@
Expected DepthBelowGrade to be greater than or equal to 0
Expected id attribute for SystemIdentifier
+
+ Expected Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'other' or 'none'
+ Expected Thickness to be greater than or equal to 0
+
Expected AssemblyEffectiveRValue to be greater than 0
Expected id attribute for SystemIdentifier
@@ -124,17 +137,21 @@
Expected NominalRValue to be greater than or equal to 0
- Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected ExteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected Area to be greater than 0
Expected id attribute for SystemIdentifier
+
+ Expected Type to be 'gypsum board' or 'gypsum composite board' or 'plaster' or 'wood' or 'other' or 'none'
+ Expected Thickness to be greater than or equal to 0
+
Expected AssemblyEffectiveRValue to be greater than 0
Expected id attribute for SystemIdentifier
- Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected InteriorAdjacentTo to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected Area to be greater than 0
Expected Thickness to be greater than or equal to 0
Expected Perimeter to be greater than or equal to 0
@@ -154,6 +171,7 @@
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
Expected Azimuth to be less than 360
+ Expected Orientation to be 'north' or 'northwest' or 'west' or 'southwest' or 'south' or 'southeast' or 'east' or 'northeast'
Expected UFactor to be greater than 0
Expected SHGC to be greater than 0
Expected SHGC to be less than 1
@@ -209,6 +227,7 @@
Expected Area to be greater than 0
Expected Azimuth to be greater than or equal to 0
Expected Azimuth to be less than 360
+ Expected Orientation to be 'north' or 'northwest' or 'west' or 'southwest' or 'south' or 'southeast' or 'east' or 'northeast'
Expected RValue to be greater than or equal to 0
Expected id attribute for SystemIdentifier
Expected idref attribute for AttachedToWall
@@ -236,7 +255,7 @@
Expected idref attribute for DistributionSystem
- Expected Units to be 'SEER' or 'EER' or 'COP' or 'kW/ton'
+ Expected Units to be 'SEER' or 'CEER' or 'EER' or 'COP' or 'kW/ton'
Expected Value to be greater than or equal to 0
@@ -258,7 +277,7 @@
Expected Value to be greater than or equal to 0
- Expected Units to be 'SEER' or 'EER' or 'COP' or 'kW/ton'
+ Expected Units to be 'SEER' or 'CEER' or 'EER' or 'COP' or 'kW/ton'
Expected Value to be greater than or equal to 0
@@ -284,6 +303,8 @@
Expected DuctType to be 'supply' or 'return'
Expected DuctInsulationRValue to be greater than or equal to 0
Expected DuctLocation to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'exterior wall' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'interstitial space' or 'living space' or 'other heated space' or 'other housing unit' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'roof deck' or 'unconditioned space' or 'under slab'
+ Expected FractionDuctArea to be greater than or equal to 0
+ Expected FractionDuctArea to be less than or equal to 1
Expected DuctSurfaceArea to be greater than 0
@@ -330,6 +351,7 @@
Expected UniformEnergyFactor to be less than or equal to 5
Expected UniformEnergyFactor to be greater than 0
Expected FirstHourRating to be greater than 0
+ Expected UsageBin to be 'very small' or 'low' or 'medium' or 'high'
Expected RecoveryEfficiency to be less than or equal to 5
Expected RecoveryEfficiency to be greater than 0
Expected id attribute for SystemIdentifier
@@ -423,7 +445,7 @@
Expected Type to be 'portable' or 'whole-home'
- Expected Location to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'living space' or 'other' or 'unconditioned space'
+ Expected Location to be 'attic' or 'attic - conditioned' or 'attic - unconditioned' or 'attic - unvented' or 'attic - vented' or 'basement' or 'basement - conditioned' or 'basement - unconditioned' or 'crawlspace' or 'crawlspace - conditioned' or 'crawlspace - unconditioned' or 'crawlspace - unvented' or 'crawlspace - vented' or 'garage' or 'garage - conditioned' or 'garage - unconditioned' or 'ground' or 'living space' or 'other' or 'other heated space' or 'other housing unit' or 'other housing unit above' or 'other housing unit below' or 'other multifamily buffer space' or 'other non-freezing space' or 'outside' or 'unconditioned space'
Expected DehumidistatSetpoint to be greater than or equal to 0
Expected DehumidistatSetpoint to be less than or equal to 1
Expected FractionDehumidificationLoadServed to be greater than or equal to 0
diff --git a/HPXMLtoOpenStudio/resources/airflow.rb b/HPXMLtoOpenStudio/resources/airflow.rb
index 8d56d39835..6c2cdb265b 100644
--- a/HPXMLtoOpenStudio/resources/airflow.rb
+++ b/HPXMLtoOpenStudio/resources/airflow.rb
@@ -2,7 +2,7 @@
class Airflow
def self.apply(model, runner, weather, spaces, hpxml, cfa, nbeds,
- ncfl_ag, duct_systems, nv_clg_ssn_sensor, hvac_map, eri_version,
+ ncfl_ag, duct_systems, clg_ssn_sensor, hvac_map, eri_version,
frac_windows_operable, apply_ashrae140_assumptions)
# Global variables
@@ -75,10 +75,10 @@ def self.apply(model, runner, weather, spaces, hpxml, cfa, nbeds,
# Initialization
initialize_cfis(model, vent_fans_mech, hvac_map)
model.getAirLoopHVACs.each do |air_loop|
- initialize_air_loop_objects(model, air_loop)
+ initialize_fan_objects(model, air_loop)
end
model.getZoneHVACFourPipeFanCoils.each do |fan_coil|
- initialize_fan_coil_objects(model, fan_coil)
+ initialize_fan_objects(model, fan_coil)
end
# Apply ducts
@@ -106,10 +106,10 @@ def self.apply(model, runner, weather, spaces, hpxml, cfa, nbeds,
vented_crawl = foundation
end
- apply_natural_ventilation_and_whole_house_fan(model, weather, hpxml.site, vent_fans_whf, open_window_area, nv_clg_ssn_sensor)
+ apply_natural_ventilation_and_whole_house_fan(model, weather, hpxml.site, vent_fans_whf, open_window_area, clg_ssn_sensor)
apply_infiltration_and_ventilation_fans(model, weather, hpxml.site, vent_fans_mech, vent_fans_kitchen, vent_fans_bath, vented_dryers,
hpxml.building_construction.has_flue_or_chimney, hpxml.air_infiltration_measurements,
- vented_attic, vented_crawl, hvac_map)
+ vented_attic, vented_crawl, hvac_map, clg_ssn_sensor)
end
def self.get_default_fraction_of_windows_operable()
@@ -510,61 +510,47 @@ def self.initialize_cfis(model, vent_fans_mech, hvac_map)
end
end
- def self.initialize_air_loop_objects(model, air_loop)
+ def self.initialize_fan_objects(model, osm_object)
@fan_rtf_var = {} if @fan_rtf_var.nil?
@fan_mfr_max_var = {} if @fan_mfr_max_var.nil?
@fan_rtf_sensor = {} if @fan_rtf_sensor.nil?
@fan_mfr_sensor = {} if @fan_mfr_sensor.nil?
# Get the supply fan
- system = HVAC.get_unitary_system_from_air_loop_hvac(air_loop)
- if system.nil? # Evaporative cooler supply fan directly on air loop
- supply_fan = air_loop.supplyFan.get
+ if osm_object.is_a? OpenStudio::Model::ZoneHVACFourPipeFanCoil
+ supply_fan = osm_object.supplyAirFan
+ elsif osm_object.is_a? OpenStudio::Model::AirLoopHVAC
+ system = HVAC.get_unitary_system_from_air_loop_hvac(osm_object)
+ if system.nil? # Evaporative cooler supply fan directly on air loop
+ supply_fan = osm_object.supplyFan.get
+ else
+ supply_fan = system.supplyFan.get
+ end
else
- supply_fan = system.supplyFan.get
+ fail 'Unexpected object type.'
end
- @fan_rtf_var[air_loop] = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{air_loop.name} Fan RTF".gsub(' ', '_'))
+ @fan_rtf_var[osm_object] = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{osm_object.name} Fan RTF".gsub(' ', '_'))
# Supply fan maximum mass flow rate
- @fan_mfr_max_var[air_loop] = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, EPlus::EMSIntVarFanMFR)
- @fan_mfr_max_var[air_loop].setName("#{air_loop.name} max sup fan mfr")
- @fan_mfr_max_var[air_loop].setInternalDataIndexKeyName(supply_fan.name.to_s)
-
- if supply_fan.to_FanOnOff.is_initialized
- @fan_rtf_sensor[air_loop] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Fan Runtime Fraction')
- @fan_rtf_sensor[air_loop].setName("#{@fan_rtf_var[air_loop].name} s")
- @fan_rtf_sensor[air_loop].setKeyName(supply_fan.name.to_s)
- elsif supply_fan.to_FanVariableVolume.is_initialized # Evaporative cooler
- @fan_mfr_sensor[air_loop] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Fan Air Mass Flow Rate')
- @fan_mfr_sensor[air_loop].setName("#{supply_fan.name} air MFR")
- @fan_mfr_sensor[air_loop].setKeyName("#{supply_fan.name}")
- @fan_rtf_sensor[air_loop] = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{@fan_rtf_var[air_loop].name}_s")
- else
- fail "Unexpected fan: #{supply_fan.name}"
- end
- end
-
- def self.initialize_fan_coil_objects(model, fan_coil)
- @fan_rtf_var = {} if @fan_rtf_var.nil?
- @fan_mfr_max_var = {} if @fan_mfr_max_var.nil?
- @fan_rtf_sensor = {} if @fan_rtf_sensor.nil?
- @fan_mfr_sensor = {} if @fan_mfr_sensor.nil?
-
- # Get the supply fan
- supply_fan = fan_coil.supplyAirFan
-
- @fan_rtf_var[fan_coil] = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "#{fan_coil.name} Fan RTF".gsub(' ', '_'))
-
- # Supply fan maximum mass flow rate
- @fan_mfr_max_var[fan_coil] = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, EPlus::EMSIntVarFanMFR)
- @fan_mfr_max_var[fan_coil].setName("#{fan_coil.name} max sup fan mfr")
- @fan_mfr_max_var[fan_coil].setInternalDataIndexKeyName(supply_fan.name.to_s)
-
- if supply_fan.to_FanOnOff.is_initialized
- @fan_rtf_sensor[fan_coil] = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Fan Runtime Fraction')
- @fan_rtf_sensor[fan_coil].setName("#{@fan_rtf_var[fan_coil].name} s")
- @fan_rtf_sensor[fan_coil].setKeyName(supply_fan.name.to_s)
+ @fan_mfr_max_var[osm_object] = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, EPlus::EMSIntVarFanMFR)
+ @fan_mfr_max_var[osm_object].setName("#{osm_object.name} max sup fan mfr")
+ @fan_mfr_max_var[osm_object].setInternalDataIndexKeyName(supply_fan.name.to_s)
+
+ if supply_fan.to_FanSystemModel.is_initialized
+ @fan_rtf_sensor[osm_object] = []
+ num_speeds = supply_fan.to_FanSystemModel.get.numberofSpeeds
+ for i in 1..num_speeds
+ if num_speeds == 1
+ var_name = 'Fan Runtime Fraction'
+ else
+ var_name = "Fan Runtime Fraction Speed #{i}"
+ end
+ rtf_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, var_name)
+ rtf_sensor.setName("#{@fan_rtf_var[osm_object].name} s")
+ rtf_sensor.setKeyName(supply_fan.name.to_s)
+ @fan_rtf_sensor[osm_object] << rtf_sensor
+ end
else
fail "Unexpected fan: #{supply_fan.name}"
end
@@ -1007,10 +993,10 @@ def self.apply_ducts(model, ducts, object)
duct_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
duct_program.setName(object_name_idx + ' duct program')
duct_program.addLine("Set #{ah_mfr_var.name} = #{ah_mfr_sensor.name}")
- if @fan_rtf_sensor[object].is_a? OpenStudio::Model::EnergyManagementSystemGlobalVariable
- duct_program.addLine("Set #{@fan_rtf_sensor[object].name} = #{@fan_mfr_sensor[object].name} / #{@fan_mfr_max_var[object].name}")
+ duct_program.addLine("Set #{@fan_rtf_var[object].name} = 0")
+ @fan_rtf_sensor[object].each do |rtf_sensor|
+ duct_program.addLine("Set #{@fan_rtf_var[object].name} = #{@fan_rtf_var[object].name} + #{rtf_sensor.name}")
end
- duct_program.addLine("Set #{@fan_rtf_var[object].name} = #{@fan_rtf_sensor[object].name}")
duct_program.addLine("Set #{ah_vfr_var.name} = #{ah_vfr_sensor.name}")
duct_program.addLine("Set #{ah_tout_var.name} = #{ah_tout_sensor.name}")
duct_program.addLine("Set #{ah_wout_var.name} = #{ah_wout_sensor.name}")
@@ -1338,7 +1324,10 @@ def self.apply_cfis(infil_program, vent_mech_fans, cfis_fan_actuator)
infil_program.addLine('Set QWHV_cfis_oa = 0.0')
vent_mech_fans.each do |vent_mech|
- infil_program.addLine("Set fan_rtf_hvac = #{@fan_rtf_sensor[@cfis_airloop[vent_mech.id]].name}")
+ infil_program.addLine('Set fan_rtf_hvac = 0')
+ @fan_rtf_sensor[@cfis_airloop[vent_mech.id]].each do |rtf_sensor|
+ infil_program.addLine("Set fan_rtf_hvac = fan_rtf_hvac + #{rtf_sensor.name}")
+ end
infil_program.addLine("Set CFIS_fan_w = #{vent_mech.unit_fan_power}") # W
infil_program.addLine('If @ABS(Minute - ZoneTimeStep*60) < 0.1')
@@ -1486,6 +1475,8 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er
# Calculate mass flow rate based on outdoor air density
# Address load with flow-weighted combined effectiveness
infil_program.addLine("Set Fan_MFR = #{q_var} * OASupRho")
+ infil_program.addLine('Set ZoneInEnth = OASupInEnth')
+ infil_program.addLine('Set ZoneInTemp = OASupInTemp')
if not vent_mech_erv_hrv_tot.empty?
# ERV/HRV EMS load model
# E+ ERV model is using standard density for MFR calculation, caused discrepancy with other system types.
@@ -1502,14 +1493,12 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er
infil_program.addLine('Set ERVTotalHeatTrans = Fan_MFR * (ERVSupOutEnth - OASupInEnth)')
infil_program.addLine('Set ERVLatHeatTrans = ERVTotalHeatTrans - ERVSensHeatTrans')
# ERV/HRV Load calculation
- infil_program.addLine('Set FanTotalToLv = Fan_MFR * (ERVSupOutEnth - ZoneAirEnth)')
- infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (ERVSupOutTemp - ZoneTemp)')
- infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv')
- else
- infil_program.addLine('Set FanTotalToLv = Fan_MFR * (OASupInEnth - ZoneAirEnth)')
- infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (OASupInTemp - ZoneTemp)')
- infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv')
+ infil_program.addLine('Set ZoneInEnth = ERVSupOutEnth')
+ infil_program.addLine('Set ZoneInTemp = ERVSupOutTemp')
end
+ infil_program.addLine('Set FanTotalToLv = Fan_MFR * (ZoneInEnth - ZoneAirEnth)')
+ infil_program.addLine('Set FanSensToLv = Fan_MFR * ZoneCp * (ZoneInTemp - ZoneTemp)')
+ infil_program.addLine('Set FanLatToLv = FanTotalToLv - FanSensToLv')
# Actuator,
# If preconditioned, handle actuators later in calculate_precond_loads
@@ -1519,11 +1508,23 @@ def self.calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_er
end
end
- def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map)
+ def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map, clg_ssn_sensor)
# Preconditioning
# Assume introducing no sensible loads to zone if preconditioned
+ if not vent_mech_preheat.empty?
+ htg_stp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Thermostat Heating Setpoint Temperature')
+ htg_stp_sensor.setName("#{Constants.ObjectNameAirflow} htg stp s")
+ htg_stp_sensor.setKeyName(@living_zone.name.to_s)
+ infil_program.addLine("Set HtgStp = #{htg_stp_sensor.name}") # heating thermostat setpoint
+ end
+ if not vent_mech_precool.empty?
+ clg_stp_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Zone Thermostat Cooling Setpoint Temperature')
+ clg_stp_sensor.setName("#{Constants.ObjectNameAirflow} clg stp s")
+ clg_stp_sensor.setKeyName(@living_zone.name.to_s)
+ infil_program.addLine("Set ClgStp = #{clg_stp_sensor.name}") # cooling thermostat setpoint
+ end
vent_mech_preheat.each_with_index do |f_preheat, i|
- infil_program.addLine('If OASupInTemp < ZoneTemp')
+ infil_program.addLine("If (OASupInTemp < HtgStp) && (#{clg_ssn_sensor.name} < 1)")
htg_energy_actuator = create_other_equipment_object_and_actuator(model: model, name: "shared mech vent preheating energy #{i}", space: @living_space, frac_lat: 0.0, frac_lost: 1.0, hpxml_fuel_type: f_preheat.preheating_fuel, end_use: Constants.ObjectNameMechanicalVentilationPreconditioning)
hvac_map["#{f_preheat.id}_preheat"] = [htg_energy_actuator.actuatedComponent.get]
infil_program.addLine(" Set Qpreheat = #{UnitConversions.convert(f_preheat.average_oa_unit_flow_rate, 'cfm', 'm^3/s').round(4)}")
@@ -1534,16 +1535,21 @@ def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_m
end
calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qpreheat', true)
- infil_program.addLine(" Set PreHeatingEnergy = (-FanSensToLv) * #{f_preheat.preheating_fraction_load_served}")
- infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} + PreHeatingEnergy")
- infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv")
- infil_program.addLine(" Set #{htg_energy_actuator.name} = PreHeatingEnergy / #{f_preheat.preheating_efficiency_cop}")
+ infil_program.addLine(' If ZoneInTemp < HtgStp')
+ infil_program.addLine(' Set FanSensToSpt = Fan_MFR * ZoneCp * (ZoneInTemp - HtgStp)')
+ infil_program.addLine(" Set PreHeatingWatt = (-FanSensToSpt) * #{f_preheat.preheating_fraction_load_served}")
+ infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} + PreHeatingWatt")
+ infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") # Fixme:Does this assumption still apply?
+ infil_program.addLine(' Else')
+ infil_program.addLine(' Set PreHeatingWatt = 0.0')
+ infil_program.addLine(' EndIf')
infil_program.addLine('Else')
- infil_program.addLine(" Set #{htg_energy_actuator.name} = 0.0")
+ infil_program.addLine(' Set PreHeatingWatt = 0.0')
infil_program.addLine('EndIf')
+ infil_program.addLine("Set #{htg_energy_actuator.name} = PreHeatingWatt / #{f_preheat.preheating_efficiency_cop}")
end
vent_mech_precool.each_with_index do |f_precool, i|
- infil_program.addLine('If OASupInTemp > ZoneTemp')
+ infil_program.addLine("If (OASupInTemp > ClgStp) && (#{clg_ssn_sensor.name} > 0)")
clg_energy_actuator = create_other_equipment_object_and_actuator(model: model, name: "shared mech vent precooling energy #{i}", space: @living_space, frac_lat: 0.0, frac_lost: 1.0, hpxml_fuel_type: f_precool.precooling_fuel, end_use: Constants.ObjectNameMechanicalVentilationPreconditioning)
hvac_map["#{f_precool.id}_precool"] = [clg_energy_actuator.actuatedComponent.get]
infil_program.addLine(" Set Qprecool = #{UnitConversions.convert(f_precool.average_oa_unit_flow_rate, 'cfm', 'm^3/s').round(4)}")
@@ -1554,18 +1560,23 @@ def self.calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_m
end
calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qprecool', true)
- infil_program.addLine(" Set PreCoolingEnergy = FanSensToLv * #{f_precool.precooling_fraction_load_served}")
- infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} - PreCoolingEnergy")
- infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv")
- infil_program.addLine(" Set #{clg_energy_actuator.name} = PreCoolingEnergy / #{f_precool.precooling_efficiency_cop}")
+ infil_program.addLine(' If ZoneInTemp > ClgStp')
+ infil_program.addLine(' Set FanSensToSpt = Fan_MFR * ZoneCp * (ZoneInTemp - ClgStp)')
+ infil_program.addLine(" Set PreCoolingWatt = FanSensToSpt * #{f_precool.precooling_fraction_load_served}")
+ infil_program.addLine(" Set #{fan_sens_load_actuator.name} = #{fan_sens_load_actuator.name} - PreCoolingWatt")
+ infil_program.addLine(" Set #{fan_lat_load_actuator.name} = #{fan_lat_load_actuator.name} - FanLatToLv") # Fixme:Does this assumption still apply?
+ infil_program.addLine(' Else')
+ infil_program.addLine(' Set PreCoolingWatt = 0.0')
+ infil_program.addLine(' EndIf')
infil_program.addLine('Else')
- infil_program.addLine(" Set #{clg_energy_actuator.name} = 0.0")
+ infil_program.addLine(' Set PreCoolingWatt = 0.0')
infil_program.addLine('EndIf')
+ infil_program.addLine("Set #{clg_energy_actuator.name} = PreCoolingWatt / #{f_precool.precooling_efficiency_cop}")
end
end
def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_mech, living_ach50, living_const_ach, weather, vent_fans_kitchen, vent_fans_bath, vented_dryers,
- range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map)
+ range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map, clg_ssn_sensor)
# Categorize fans into different types
vent_mech_preheat = vent_fans_mech.select { |vent_mech| (not vent_mech.preheating_efficiency_cop.nil?) }
vent_mech_precool = vent_fans_mech.select { |vent_mech| (not vent_mech.precooling_efficiency_cop.nil?) }
@@ -1640,7 +1651,7 @@ def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_me
calculate_fan_loads(model, infil_program, vent_mech_erv_hrv_tot, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, 'Qload')
# Address preconditioning
- calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map)
+ calculate_precond_loads(model, infil_program, vent_mech_preheat, vent_mech_precool, hrv_erv_effectiveness_map, fan_sens_load_actuator, fan_lat_load_actuator, hvac_map, clg_ssn_sensor)
program_calling_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
program_calling_manager.setName("#{infil_program.name} calling manager")
@@ -1649,7 +1660,7 @@ def self.apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_me
end
def self.apply_infiltration_and_ventilation_fans(model, weather, site, vent_fans_mech, vent_fans_kitchen, vent_fans_bath, vented_dryers,
- has_flue_chimney, air_infils, vented_attic, vented_crawl, hvac_map)
+ has_flue_chimney, air_infils, vented_attic, vented_crawl, hvac_map, clg_ssn_sensor)
# Get living space infiltration
living_ach50 = nil
living_const_ach = nil
@@ -1687,7 +1698,7 @@ def self.apply_infiltration_and_ventilation_fans(model, weather, site, vent_fans
# Get mechanical ventilation
apply_infiltration_and_mechanical_ventilation(model, site, vent_fans_mech, living_ach50, living_const_ach, weather, vent_fans_kitchen, vent_fans_bath, vented_dryers,
- range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map)
+ range_sch_sensors_map, bath_sch_sensors_map, dryer_exhaust_sch_sensors_map, has_flue_chimney, hvac_map, clg_ssn_sensor)
end
def self.apply_infiltration_to_living(site, living_ach50, living_const_ach, infil_program, weather, has_flue_chimney)
@@ -1789,7 +1800,7 @@ def self.apply_infiltration_to_living(site, living_ach50, living_const_ach, infi
infil_program.addLine("Set Cs = #{(stack_coef * (UnitConversions.convert(1.0, 'inH2O/R', 'Pa/K')**n_i)).round(4)}")
infil_program.addLine("Set Cw = #{(wind_coef * (UnitConversions.convert(1.0, 'inH2O/mph^2', 'Pa*s^2/m^2')**n_i)).round(4)}")
infil_program.addLine("Set n = #{n_i}")
- infil_program.addLine("Set sft = (f_t*#{(((site_ap.aim2_shelter_coeff * (1.0 - y_i)) + (s_wflue * (1.5 * y_i))))})")
+ infil_program.addLine("Set sft = (f_t*#{(site_ap.aim2_shelter_coeff * (1.0 - y_i)) + (s_wflue * (1.5 * y_i))})")
infil_program.addLine("Set temp1 = ((c*Cw)*((sft*#{@vwind_sensor.name})^(2*n)))^2")
infil_program.addLine('Set Qinf = (((c*Cs*(dT^n))^2)+temp1)^0.5')
infil_program.addLine('Set Qinf = (@Max Qinf 0)')
diff --git a/HPXMLtoOpenStudio/resources/constructions.rb b/HPXMLtoOpenStudio/resources/constructions.rb
index ded646cc80..e18f88014b 100644
--- a/HPXMLtoOpenStudio/resources/constructions.rb
+++ b/HPXMLtoOpenStudio/resources/constructions.rb
@@ -3,11 +3,11 @@
class Constructions
# Container class for walls, floors/ceilings, roofs, etc.
- def self.apply_wood_stud_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_wood_stud_wall(runner, model, surfaces, constr_name,
cavity_r, install_grade, cavity_depth_in, cavity_filled,
- framing_factor, drywall_thick_in, osb_thick_in,
- rigid_r, mat_ext_finish, otherside_drywall_thick_in,
- inside_film, outside_film)
+ framing_factor, mat_int_finish, osb_thick_in,
+ rigid_r, mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -15,25 +15,25 @@ def self.apply_wood_stud_wall(runner, model, surfaces, wall, constr_name,
if cavity_r > 0
if cavity_filled
# Insulation
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth_in / cavity_r)
+ mat_cavity = Material.new(thick_in: cavity_depth_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth_in / cavity_r)
else
# Insulation plus air gap when insulation thickness < cavity depth
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth_in / (cavity_r + Gas.AirGapRvalue))
+ mat_cavity = Material.new(thick_in: cavity_depth_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth_in / (cavity_r + Gas.AirGapRvalue))
end
else
# Empty cavity
mat_cavity = Material.AirCavityClosed(cavity_depth_in)
end
- mat_framing = Material.new(name = nil, thick_in = cavity_depth_in, mat_base = BaseMaterial.Wood)
+ mat_framing = Material.new(thick_in: cavity_depth_in, mat_base: BaseMaterial.Wood)
mat_gap = Material.AirCavityClosed(cavity_depth_in)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -46,58 +46,60 @@ def self.apply_wood_stud_wall(runner, model, surfaces, wall, constr_name,
if not mat_ext_finish.nil?
constr.add_layer(mat_ext_finish)
end
- if otherside_drywall_thick_in > 0 # E.g., interior partition wall
- constr.add_layer(Material.GypsumWall(otherside_drywall_thick_in))
- end
if not mat_rigid.nil?
constr.add_layer(mat_rigid)
end
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'WallStudAndCavity')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'wall stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_double_stud_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_double_stud_wall(runner, model, surfaces, constr_name,
cavity_r, install_grade, stud_depth_in, gap_depth_in,
framing_factor, framing_spacing, is_staggered,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
# Define materials
cavity_depth_in = 2.0 * stud_depth_in + gap_depth_in
- mat_ins_inner_outer = Material.new(name = nil, thick_in = stud_depth_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth_in / cavity_r)
- mat_ins_middle = Material.new(name = nil, thick_in = gap_depth_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth_in / cavity_r)
- mat_framing_inner_outer = Material.new(name = nil, thick_in = stud_depth_in, mat_base = BaseMaterial.Wood)
- mat_framing_middle = Material.new(name = nil, thick_in = gap_depth_in, mat_base = BaseMaterial.Wood)
- mat_stud = Material.new(name = nil, thick_in = stud_depth_in, mat_base = BaseMaterial.Wood)
+ mat_ins_inner_outer = Material.new(thick_in: stud_depth_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth_in / cavity_r)
+ mat_ins_middle = Material.new(thick_in: gap_depth_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth_in / cavity_r)
+ mat_framing_inner_outer = Material.new(thick_in: stud_depth_in, mat_base: BaseMaterial.Wood)
+ mat_framing_middle = Material.new(thick_in: gap_depth_in, mat_base: BaseMaterial.Wood)
+ mat_stud = Material.new(thick_in: stud_depth_in, mat_base: BaseMaterial.Wood)
mat_gap_total = Material.AirCavityClosed(cavity_depth_in)
- mat_gap_inner_outer = Material.new(name = nil, thick_in = stud_depth_in, mat_base = nil, k_in = stud_depth_in / (mat_gap_total.rvalue * stud_depth_in / cavity_depth_in), rho = Gas.Air.rho, cp = Gas.Air.cp)
- mat_gap_middle = Material.new(name = nil, thick_in = gap_depth_in, mat_base = nil, k_in = gap_depth_in / (mat_gap_total.rvalue * gap_depth_in / cavity_depth_in), rho = Gas.Air.rho, cp = Gas.Air.cp)
+ mat_gap_inner_outer = Material.new(thick_in: stud_depth_in, k_in: stud_depth_in / (mat_gap_total.rvalue * stud_depth_in / cavity_depth_in), rho: Gas.Air.rho, cp: Gas.Air.cp)
+ mat_gap_middle = Material.new(thick_in: gap_depth_in, k_in: gap_depth_in / (mat_gap_total.rvalue * gap_depth_in / cavity_depth_in), rho: Gas.Air.rho, cp: Gas.Air.cp)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
stud_frac = 1.5 / framing_spacing
misc_framing_factor = framing_factor - stud_frac
if misc_framing_factor < 0
- fail "Framing Factor (#{framing_factor}) is less than the framing solely provided by the studs (#{stud_frac})."
+ stud_frac = framing_factor
+ misc_framing_factor = 0.0
end
dsGapFactor = get_gap_factor(install_grade, framing_factor, cavity_r)
@@ -116,52 +118,56 @@ def self.apply_double_stud_wall(runner, model, surfaces, wall, constr_name,
constr.add_layer(mat_osb)
end
if is_staggered
- constr.add_layer([mat_framing_inner_outer, mat_ins_inner_outer, mat_stud, mat_gap_inner_outer, mat_ins_inner_outer], 'WallStudandCavityOuter')
+ constr.add_layer([mat_framing_inner_outer, mat_ins_inner_outer, mat_stud, mat_gap_inner_outer, mat_ins_inner_outer], 'wall stud and cavity')
else
- constr.add_layer([mat_framing_inner_outer, mat_stud, mat_ins_inner_outer, mat_gap_inner_outer, mat_ins_inner_outer], 'WallStudandCavityOuter')
+ constr.add_layer([mat_framing_inner_outer, mat_stud, mat_ins_inner_outer, mat_gap_inner_outer, mat_ins_inner_outer], 'wall stud and cavity')
end
if gap_depth_in > 0
- constr.add_layer([mat_framing_middle, mat_ins_middle, mat_ins_middle, mat_gap_middle, mat_ins_middle], 'WallCavity')
+ constr.add_layer([mat_framing_middle, mat_ins_middle, mat_ins_middle, mat_gap_middle, mat_ins_middle], 'wall cavity')
end
- constr.add_layer([mat_framing_inner_outer, mat_stud, mat_ins_inner_outer, mat_gap_inner_outer, mat_ins_inner_outer], 'WallStudandCavityInner')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing_inner_outer, mat_stud, mat_ins_inner_outer, mat_gap_inner_outer, mat_ins_inner_outer], 'wall stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_cmu_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_cmu_wall(runner, model, surfaces, constr_name,
thick_in, conductivity, density, framing_factor,
furring_r, furring_cavity_depth, furring_spacing,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
# Define materials
- mat_cmu = Material.new(name = nil, thick_in = thick_in, mat_base = BaseMaterial.Concrete, k_in = conductivity, rho = density)
- mat_framing = Material.new(name = nil, thick_in = thick_in, mat_base = BaseMaterial.Wood)
+ mat_cmu = Material.new(thick_in: thick_in, mat_base: BaseMaterial.Concrete, k_in: conductivity, rho: density)
+ mat_framing = Material.new(thick_in: thick_in, mat_base: BaseMaterial.Wood)
mat_furring = nil
mat_furring_cavity = nil
if furring_cavity_depth != 0
- mat_furring = Material.new(name = nil, thick_in = furring_cavity_depth, mat_base = BaseMaterial.Wood)
+ mat_furring = Material.new(thick_in: furring_cavity_depth, mat_base: BaseMaterial.Wood)
if furring_r == 0
mat_furring_cavity = Material.AirCavityClosed(furring_cavity_depth)
else
- mat_furring_cavity = Material.new(name = nil, thick_in = furring_cavity_depth, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = furring_cavity_depth / furring_r)
+ mat_furring_cavity = Material.new(thick_in: furring_cavity_depth, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: furring_cavity_depth / furring_r)
end
end
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -186,40 +192,44 @@ def self.apply_cmu_wall(runner, model, surfaces, wall, constr_name,
constr.add_layer(mat_osb)
end
if not mat_furring.nil?
- constr.add_layer([mat_framing, mat_cmu, mat_cmu], 'WallCMU')
- constr.add_layer([mat_furring, mat_furring, mat_furring_cavity], 'WallFurring')
+ constr.add_layer([mat_framing, mat_cmu, mat_cmu], 'concrete block')
+ constr.add_layer([mat_furring, mat_furring, mat_furring_cavity], 'furring')
else
- constr.add_layer([mat_framing, mat_cmu], 'WallCMU')
+ constr.add_layer([mat_framing, mat_cmu], 'concrete block')
end
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_icf_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_icf_wall(runner, model, surfaces, constr_name,
icf_r, ins_thick_in, concrete_thick_in, framing_factor,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
# Define materials
- mat_ins = Material.new(name = nil, thick_in = ins_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = ins_thick_in / icf_r)
- mat_conc = Material.new(name = nil, thick_in = concrete_thick_in, mat_base = BaseMaterial.Concrete)
- mat_framing_inner_outer = Material.new(name = nil, thick_in = ins_thick_in, mat_base = BaseMaterial.Wood)
- mat_framing_middle = Material.new(name = nil, thick_in = concrete_thick_in, mat_base = BaseMaterial.Wood)
+ mat_ins = Material.new(thick_in: ins_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: ins_thick_in / icf_r)
+ mat_conc = Material.new(thick_in: concrete_thick_in, mat_base: BaseMaterial.Concrete)
+ mat_framing_inner_outer = Material.new(thick_in: ins_thick_in, mat_base: BaseMaterial.Wood)
+ mat_framing_middle = Material.new(thick_in: concrete_thick_in, mat_base: BaseMaterial.Wood)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -237,42 +247,46 @@ def self.apply_icf_wall(runner, model, surfaces, wall, constr_name,
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_framing_inner_outer, mat_ins], 'WallICFInsFormOuter')
- constr.add_layer([mat_framing_middle, mat_conc], 'WallICFConcrete')
- constr.add_layer([mat_framing_inner_outer, mat_ins], 'WallICFInsFormInner')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing_inner_outer, mat_ins], 'wall ins form')
+ constr.add_layer([mat_framing_middle, mat_conc], 'wall concrete')
+ constr.add_layer([mat_framing_inner_outer, mat_ins], 'wall ins form')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_sip_wall(runner, model, surfaces, wall, constr_name, sip_r,
+ def self.apply_sip_wall(runner, model, surfaces, constr_name, sip_r,
sip_thick_in, framing_factor, sheathing_thick_in,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
# Define materials
spline_thick_in = 0.5
ins_thick_in = sip_thick_in - (2.0 * spline_thick_in) # in
- mat_int_sheath = Material.new(name = 'WallIntSheathing', thick_in = sheathing_thick_in, mat_base = BaseMaterial.Wood)
- mat_framing_inner_outer = Material.new(name = nil, thick_in = spline_thick_in, mat_base = BaseMaterial.Wood)
- mat_framing_middle = Material.new(name = nil, thick_in = ins_thick_in, mat_base = BaseMaterial.Wood)
- mat_spline = Material.new(name = nil, thick_in = spline_thick_in, mat_base = BaseMaterial.Wood)
- mat_ins_inner_outer = Material.new(name = nil, thick_in = spline_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = sip_thick_in / sip_r)
- mat_ins_middle = Material.new(name = nil, thick_in = ins_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = sip_thick_in / sip_r)
+ mat_int_sheath = Material.OSBSheathing(sheathing_thick_in)
+ mat_framing_inner_outer = Material.new(thick_in: spline_thick_in, mat_base: BaseMaterial.Wood)
+ mat_framing_middle = Material.new(thick_in: ins_thick_in, mat_base: BaseMaterial.Wood)
+ mat_spline = Material.new(thick_in: spline_thick_in, mat_base: BaseMaterial.Wood)
+ mat_ins_inner_outer = Material.new(thick_in: spline_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: sip_thick_in / sip_r)
+ mat_ins_middle = Material.new(thick_in: ins_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: sip_thick_in / sip_r)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -292,24 +306,28 @@ def self.apply_sip_wall(runner, model, surfaces, wall, constr_name, sip_r,
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_framing_inner_outer, mat_spline, mat_ins_inner_outer], 'WallSplineLayerOuter')
- constr.add_layer([mat_framing_middle, mat_ins_middle, mat_ins_middle], 'WallIns')
- constr.add_layer([mat_framing_inner_outer, mat_spline, mat_ins_inner_outer], 'WallSplineLayerInner')
+ constr.add_layer([mat_framing_inner_outer, mat_spline, mat_ins_inner_outer], 'wall spline layer')
+ constr.add_layer([mat_framing_middle, mat_ins_middle, mat_ins_middle], 'wall ins layer')
+ constr.add_layer([mat_framing_inner_outer, mat_spline, mat_ins_inner_outer], 'wall spline layer')
constr.add_layer(mat_int_sheath)
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_steel_stud_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_steel_stud_wall(runner, model, surfaces, constr_name,
cavity_r, install_grade, cavity_depth,
cavity_filled, framing_factor, correction_factor,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -318,10 +336,10 @@ def self.apply_steel_stud_wall(runner, model, surfaces, wall, constr_name,
if eR > 0
if cavity_filled
# Insulation
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth / eR)
+ mat_cavity = Material.new(thick_in: cavity_depth, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth / eR)
else
# Insulation plus air gap when insulation thickness < cavity depth
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth / (eR + Gas.AirGapRvalue))
+ mat_cavity = Material.new(thick_in: cavity_depth, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth / (eR + Gas.AirGapRvalue))
end
else
# Empty cavity
@@ -330,12 +348,12 @@ def self.apply_steel_stud_wall(runner, model, surfaces, wall, constr_name,
mat_gap = Material.AirCavityClosed(cavity_depth)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -354,20 +372,24 @@ def self.apply_steel_stud_wall(runner, model, surfaces, wall, constr_name,
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_cavity, mat_gap], 'WallStudAndCavity')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_cavity, mat_gap], 'wall stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_generic_layered_wall(runner, model, surfaces, wall, constr_name,
+ def self.apply_generic_layered_wall(runner, model, surfaces, constr_name,
thick_ins, conds, denss, specheats,
- drywall_thick_in, osb_thick_in, rigid_r,
- mat_ext_finish, inside_film, outside_film)
+ mat_int_finish, osb_thick_in, rigid_r,
+ mat_ext_finish, inside_film, outside_film,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -380,27 +402,27 @@ def self.apply_generic_layered_wall(runner, model, surfaces, wall, constr_name,
# Define materials
mats = []
- mats << Material.new(name = 'WallLayer1', thick_in = thick_ins[0], mat_base = nil, k_in = conds[0], rho = denss[0], cp = specheats[0])
+ mats << Material.new(name: 'wall layer 1', thick_in: thick_ins[0], k_in: conds[0], rho: denss[0], cp: specheats[0])
if not thick_ins[1].nil?
- mats << Material.new(name = 'WallLayer2', thick_in = thick_ins[1], mat_base = nil, k_in = conds[1], rho = denss[1], cp = specheats[1])
+ mats << Material.new(name: 'wall layer 2', thick_in: thick_ins[1], k_in: conds[1], rho: denss[1], cp: specheats[1])
end
if not thick_ins[2].nil?
- mats << Material.new(name = 'WallLayer3', thick_in = thick_ins[2], mat_base = nil, k_in = conds[2], rho = denss[2], cp = specheats[2])
+ mats << Material.new(name: 'wall layer 3', thick_in: thick_ins[2], k_in: conds[2], rho: denss[2], cp: specheats[2])
end
if not thick_ins[3].nil?
- mats << Material.new(name = 'WallLayer4', thick_in = thick_ins[3], mat_base = nil, k_in = conds[3], rho = denss[3], cp = specheats[3])
+ mats << Material.new(name: 'wall layer 4', thick_in: thick_ins[3], k_in: conds[3], rho: denss[3], cp: specheats[3])
end
if not thick_ins[4].nil?
- mats << Material.new(name = 'WallLayer5', thick_in = thick_ins[4], mat_base = nil, k_in = conds[4], rho = denss[4], cp = specheats[4])
+ mats << Material.new(name: 'wall layer 5', thick_in: thick_ins[4], k_in: conds[4], rho: denss[4], cp: specheats[4])
end
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'WallSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'WallRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'wall rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -421,20 +443,23 @@ def self.apply_generic_layered_wall(runner, model, surfaces, wall, constr_name,
mats.each do |mat|
constr.add_layer(mat)
end
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_rim_joist(runner, model, surfaces, rim_joist, constr_name,
+ def self.apply_rim_joist(runner, model, surfaces, constr_name,
cavity_r, install_grade, framing_factor,
- drywall_thick_in, osb_thick_in,
+ mat_int_finish, osb_thick_in,
rigid_r, mat_ext_finish, inside_film,
- outside_film)
+ outside_film, solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -444,21 +469,21 @@ def self.apply_rim_joist(runner, model, surfaces, rim_joist, constr_name,
framing_thick_in = sill_plate_thick_in - rim_joist_thick_in # Extra non-continuous wood beyond rim joist thickness
if cavity_r > 0
# Insulation
- mat_cavity = Material.new(name = nil, thick_in = framing_thick_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = framing_thick_in / cavity_r)
+ mat_cavity = Material.new(thick_in: framing_thick_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: framing_thick_in / cavity_r)
else
# Empty cavity
mat_cavity = Material.AirCavityOpen(framing_thick_in)
end
- mat_framing = Material.new(name = nil, thick_in = framing_thick_in, mat_base = BaseMaterial.Wood)
+ mat_framing = Material.new(thick_in: framing_thick_in, mat_base: BaseMaterial.Wood)
mat_gap = Material.AirCavityClosed(framing_thick_in)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'RimJoistSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'RimJoistRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'rim joist rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -477,12 +502,15 @@ def self.apply_rim_joist(runner, model, surfaces, rim_joist, constr_name,
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'RimJoistStudAndCavity')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'rim joist stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
@@ -492,7 +520,8 @@ def self.apply_open_cavity_roof(runner, model, surfaces, constr_name,
framing_factor, framing_thick_in,
osb_thick_in, rigid_r,
mat_roofing, has_radiant_barrier,
- inside_film, outside_film, radiant_barrier_grade)
+ inside_film, outside_film, radiant_barrier_grade,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -505,23 +534,23 @@ def self.apply_open_cavity_roof(runner, model, surfaces, constr_name,
if cavity_ins_thick_in < framing_thick_in
cavity_k = cavity_k * framing_thick_in / cavity_ins_thick_in
end
- mat_cavity = Material.new(name = nil, thick_in = roof_ins_thickness_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_k)
+ mat_cavity = Material.new(thick_in: roof_ins_thickness_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_k)
end
if (cavity_ins_thick_in > framing_thick_in) && (framing_thick_in > 0)
wood_k = BaseMaterial.Wood.k_in * cavity_ins_thick_in / framing_thick_in
else
wood_k = BaseMaterial.Wood.k_in
end
- mat_framing = Material.new(name = nil, thick_in = roof_ins_thickness_in, mat_base = BaseMaterial.Wood, k_in = wood_k)
+ mat_framing = Material.new(thick_in: roof_ins_thickness_in, mat_base: BaseMaterial.Wood, k_in: wood_k)
mat_gap = Material.AirCavityOpen(roof_ins_thickness_in)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'RoofSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'RoofRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'roof rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
mat_rb = nil
if has_radiant_barrier
@@ -545,22 +574,26 @@ def self.apply_open_cavity_roof(runner, model, surfaces, constr_name,
constr.add_layer(mat_osb)
end
if framing_thick_in > 0
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'RoofStudAndCavity')
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'roof stud and cavity')
end
if not mat_rb.nil?
constr.add_layer(mat_rb)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to roof surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
def self.apply_closed_cavity_roof(runner, model, surfaces, constr_name,
cavity_r, install_grade, cavity_depth,
- filled_cavity, framing_factor, drywall_thick_in,
+ filled_cavity, framing_factor, mat_int_finish,
osb_thick_in, rigid_r, mat_roofing, has_radiant_barrier,
- inside_film, outside_film, radiant_barrier_grade)
+ inside_film, outside_film, radiant_barrier_grade,
+ solar_absorptance = nil, emittance = nil)
return if surfaces.empty?
@@ -568,25 +601,25 @@ def self.apply_closed_cavity_roof(runner, model, surfaces, constr_name,
if cavity_r > 0
if filled_cavity
# Insulation
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth / cavity_r)
+ mat_cavity = Material.new(thick_in: cavity_depth, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth / cavity_r)
else
# Insulation plus air gap when insulation thickness < cavity depth
- mat_cavity = Material.new(name = nil, thick_in = cavity_depth, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = cavity_depth / (cavity_r + Gas.AirGapRvalue))
+ mat_cavity = Material.new(thick_in: cavity_depth, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: cavity_depth / (cavity_r + Gas.AirGapRvalue))
end
else
# Empty cavity
mat_cavity = Material.AirCavityClosed(cavity_depth)
end
- mat_framing = Material.new(name = nil, thick_in = cavity_depth, mat_base = BaseMaterial.Wood)
+ mat_framing = Material.new(thick_in: cavity_depth, mat_base: BaseMaterial.Wood)
mat_gap = Material.AirCavityClosed(cavity_depth)
mat_osb = nil
if osb_thick_in > 0
- mat_osb = Material.new(name = 'RoofSheathing', thick_in = osb_thick_in, mat_base = BaseMaterial.Wood)
+ mat_osb = Material.OSBSheathing(osb_thick_in)
end
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'RoofRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'roof rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
mat_rb = nil
if has_radiant_barrier
@@ -609,48 +642,45 @@ def self.apply_closed_cavity_roof(runner, model, surfaces, constr_name,
if not mat_osb.nil?
constr.add_layer(mat_osb)
end
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'RoofStudAndCavity')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'roof stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
if not mat_rb.nil?
constr.add_layer(mat_rb)
end
constr.add_layer(inside_film)
+ constr.set_exterior_material_properties(solar_absorptance, emittance)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
def self.apply_ceiling(runner, model, surfaces, constr_name,
- cavity_r, install_grade, ins_thick_in,
+ cavity_r, install_grade, addtl_r,
framing_factor, joist_height_in,
- drywall_thick_in, inside_film, outside_film)
+ mat_int_finish, inside_film, outside_film)
- # Drywall below, open cavity above (e.g., attic floor)
+ # Interior finish below, open cavity above (e.g., attic floor)
return if surfaces.empty?
# Define materials
mat_addtl_ins = nil
- if ins_thick_in >= joist_height_in
- # If the ceiling insulation thickness is greater than the joist thickness
- cavity_k = ins_thick_in / cavity_r
- if ins_thick_in > joist_height_in
+ if cavity_r == 0
+ mat_cavity = Material.AirCavityOpen(joist_height_in)
+ else
+ if addtl_r > 0
# If there is additional insulation beyond the rafter height,
# these inputs are used for defining an additional layer
- mat_addtl_ins = Material.new(name = 'CeilingAdditionalIns', thick_in = (ins_thick_in - joist_height_in), mat_base = BaseMaterial.InsulationGenericLoosefill, k_in = cavity_k)
- end
- mat_cavity = Material.new(name = nil, thick_in = joist_height_in, mat_base = BaseMaterial.InsulationGenericLoosefill, k_in = cavity_k)
- else
- # Else the joist thickness is greater than the ceiling insulation thickness
- if cavity_r == 0
- mat_cavity = Material.AirCavityOpen(joist_height_in)
- else
- mat_cavity = Material.new(name = nil, thick_in = joist_height_in, mat_base = BaseMaterial.InsulationGenericLoosefill, k_in = joist_height_in / cavity_r)
+ addtl_thick_in = addtl_r / 3.0 # Assume roughly R-3 per inch of loose-fill above cavity
+ mat_addtl_ins = Material.new(name: 'ceiling loosefill ins', thick_in: addtl_thick_in, mat_base: BaseMaterial.InsulationGenericLoosefill, k_in: addtl_thick_in / addtl_r)
end
+ mat_cavity = Material.new(thick_in: joist_height_in, mat_base: BaseMaterial.InsulationGenericLoosefill, k_in: joist_height_in / cavity_r)
end
- mat_framing = Material.new(name = nil, thick_in = joist_height_in, mat_base = BaseMaterial.Wood)
+ mat_framing = Material.new(thick_in: joist_height_in, mat_base: BaseMaterial.Wood)
mat_gap = Material.AirCavityOpen(joist_height_in)
# Set paths
@@ -663,12 +693,14 @@ def self.apply_ceiling(runner, model, surfaces, constr_name,
if not mat_addtl_ins.nil?
constr.add_layer(mat_addtl_ins)
end
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'CeilingStudAndCavity')
- if drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(drywall_thick_in))
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'ceiling stud and cavity')
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
constr.add_layer(inside_film)
+ constr.set_interior_material_properties(debug: true)
+
# Create and assign construction to ceiling surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
@@ -688,14 +720,14 @@ def self.apply_floor(runner, model, surfaces, constr_name,
if cavity_r == 0
mat_cavity = Material.AirCavityOpen(mat_2x.thick_in)
else
- mat_cavity = Material.new(name = nil, thick_in = mat_2x.thick_in, mat_base = BaseMaterial.InsulationGenericDensepack, k_in = mat_2x.thick_in / cavity_r)
+ mat_cavity = Material.new(thick_in: mat_2x.thick_in, mat_base: BaseMaterial.InsulationGenericDensepack, k_in: mat_2x.thick_in / cavity_r)
end
- mat_framing = Material.new(name = nil, thick_in = mat_2x.thick_in, mat_base = BaseMaterial.Wood)
+ mat_framing = Material.new(thick_in: mat_2x.thick_in, mat_base: BaseMaterial.Wood)
mat_gap = Material.AirCavityOpen(joist_height_in)
mat_rigid = nil
if rigid_r > 0
rigid_thick_in = rigid_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'FloorRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / rigid_r)
+ mat_rigid = Material.new(name: 'floor rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / rigid_r)
end
# Set paths
@@ -705,48 +737,51 @@ def self.apply_floor(runner, model, surfaces, constr_name,
# Define construction
constr = Construction.new(constr_name, path_fracs)
constr.add_layer(outside_film)
- constr.add_layer([mat_framing, mat_cavity, mat_gap], 'FloorStudAndCavity')
+ constr.add_layer([mat_framing, mat_cavity, mat_gap], 'floor stud and cavity')
if not mat_rigid.nil?
constr.add_layer(mat_rigid)
end
if plywood_thick_in > 0
- constr.add_layer(Material.Plywood(plywood_thick_in))
+ constr.add_layer(Material.OSBSheathing(plywood_thick_in))
end
if not mat_floor_covering.nil?
constr.add_layer(mat_floor_covering)
end
constr.add_layer(inside_film)
+ constr.set_interior_material_properties()
+
# Create and assign construction to surfaces
constr.create_and_assign_constructions(runner, surfaces, model)
end
- def self.apply_foundation_wall(runner, model, wall_surfaces, wall_constr_name,
+ def self.apply_foundation_wall(runner, model, surfaces, constr_name,
ext_rigid_ins_offset, int_rigid_ins_offset, ext_rigid_ins_height,
- int_rigid_ins_height, ext_rigid_r, int_rigid_r, wall_drywall_thick_in, wall_concrete_thick_in, wall_height_above_grade)
+ int_rigid_ins_height, ext_rigid_r, int_rigid_r, mat_int_finish,
+ concrete_thick_in, height_above_grade)
# Create Kiva foundation
foundation = apply_kiva_walled_foundation(model, ext_rigid_r, int_rigid_r, ext_rigid_ins_offset,
int_rigid_ins_offset, ext_rigid_ins_height,
- int_rigid_ins_height, wall_height_above_grade,
- wall_concrete_thick_in, wall_drywall_thick_in)
+ int_rigid_ins_height, height_above_grade,
+ concrete_thick_in, mat_int_finish)
# Define materials
- mat_concrete = Material.Concrete(wall_concrete_thick_in)
+ mat_concrete = Material.Concrete(concrete_thick_in)
# Define construction
- constr = Construction.new(wall_constr_name, [1])
+ constr = Construction.new(constr_name, [1])
constr.add_layer(mat_concrete)
- if wall_drywall_thick_in > 0
- constr.add_layer(Material.GypsumWall(wall_drywall_thick_in))
+ if not mat_int_finish.nil?
+ constr.add_layer(mat_int_finish)
end
# Create and assign construction to surfaces
- constr.create_and_assign_constructions(runner, wall_surfaces, model)
+ constr.create_and_assign_constructions(runner, surfaces, model)
# Assign surfaces to Kiva foundation
- wall_surfaces.each do |wall_surface|
- wall_surface.setAdjacentFoundation(foundation)
+ surfaces.each do |surface|
+ surface.setAdjacentFoundation(foundation)
end
end
@@ -767,7 +802,7 @@ def self.apply_foundation_slab(runner, model, surface, constr_name,
else
# Kiva foundation (for crawlspace/basement) exists
if (under_r > 0) && (under_width > 0)
- int_horiz_mat = create_insulation_material(model, 'FoundationIntHorizIns', under_r)
+ int_horiz_mat = create_insulation_material(model, 'interior horizontal ins', under_r)
foundation.setInteriorHorizontalInsulationMaterial(int_horiz_mat)
foundation.setInteriorHorizontalInsulationDepth(0)
foundation.setInteriorHorizontalInsulationWidth(UnitConversions.convert(under_width, 'ft', 'm'))
@@ -786,7 +821,7 @@ def self.apply_foundation_slab(runner, model, surface, constr_name,
mat_rigid = nil
if whole_r > 0
rigid_thick_in = whole_r * BaseMaterial.InsulationRigid.k_in
- mat_rigid = Material.new(name = 'SlabRigidIns', thick_in = rigid_thick_in, mat_base = BaseMaterial.InsulationRigid, k_in = rigid_thick_in / whole_r)
+ mat_rigid = Material.new(name: 'slab rigid ins', thick_in: rigid_thick_in, mat_base: BaseMaterial.InsulationRigid, k_in: rigid_thick_in / whole_r)
end
# Define construction
@@ -818,7 +853,7 @@ def self.apply_door(runner, model, subsurfaces, constr_name, ufactor, inside_fil
# Define materials
door_Rvalue = 1.0 / ufactor - inside_film.rvalue - outside_film.rvalue
door_thickness = 1.75 # in
- fin_door_mat = Material.new(name = 'DoorMaterial', thick_in = door_thickness, mat_base = BaseMaterial.Wood, k_in = 1.0 / door_Rvalue * door_thickness)
+ fin_door_mat = Material.new(name: 'door material', thick_in: door_thickness, mat_base: BaseMaterial.Wood, k_in: 1.0 / door_Rvalue * door_thickness)
# Set paths
path_fracs = [1]
@@ -839,7 +874,7 @@ def self.apply_skylight(runner, model, subsurface, constr_name, ufactor, shgc)
apply_window_skylight(runner, model, 'Skylight', subsurface, constr_name, ufactor, shgc)
end
- def self.apply_partition_walls(runner, model, constr_name, drywall_thick_in, frac_of_ffa,
+ def self.apply_partition_walls(runner, model, constr_name, mat_int_finish, frac_of_ffa,
basement_frac_of_cfa, cond_base_surfaces, living_space)
imdefs = []
@@ -865,9 +900,9 @@ def self.apply_partition_walls(runner, model, constr_name, drywall_thick_in, fra
imdefs << imdef
end
- apply_wood_stud_wall(runner, model, imdefs, nil, constr_name,
+ apply_wood_stud_wall(runner, model, imdefs, constr_name,
0, 1, 3.5, false, 0.16,
- drywall_thick_in, 0, 0, nil, drywall_thick_in,
+ mat_int_finish, 0, 0, mat_int_finish,
Material.AirFilmVertical,
Material.AirFilmVertical)
end
@@ -901,7 +936,7 @@ def self.apply_furniture(runner, model, mass_lb_per_sqft, density_lb_per_cuft,
furnThickness = UnitConversions.convert(furnMass / (furnDensity * furnAreaFraction), 'ft', 'in')
# Define materials
- mat_fm = Material.new(name = mat_obj_name_space, thick_in = furnThickness, mat_base = nil, k_in = furnConductivity, rho = furnDensity, cp = furnSpecHeat, tAbs = 0.9, sAbs = furnSolarAbsorptance, vAbs = 0.1)
+ mat_fm = Material.new(name: mat_obj_name_space, thick_in: furnThickness, k_in: furnConductivity, rho: furnDensity, cp: furnSpecHeat, tAbs: 0.9, sAbs: furnSolarAbsorptance)
# Set paths
path_fracs = [1]
@@ -1042,7 +1077,7 @@ def self.create_kiva_slab_foundation(model, int_horiz_r, int_horiz_width, int_ve
# Interior horizontal insulation
if (int_horiz_r > 0) && (int_horiz_width > 0)
- int_horiz_mat = create_insulation_material(model, 'FoundationIntHorizIns', int_horiz_r)
+ int_horiz_mat = create_insulation_material(model, 'interior horizontal ins', int_horiz_r)
foundation.setInteriorHorizontalInsulationMaterial(int_horiz_mat)
foundation.setInteriorHorizontalInsulationDepth(0)
foundation.setInteriorHorizontalInsulationWidth(UnitConversions.convert(int_horiz_width, 'ft', 'm'))
@@ -1050,14 +1085,14 @@ def self.create_kiva_slab_foundation(model, int_horiz_r, int_horiz_width, int_ve
# Interior vertical insulation
if int_vert_r > 0
- int_vert_mat = create_insulation_material(model, 'FoundationIntVertIns', int_vert_r)
+ int_vert_mat = create_insulation_material(model, 'interior vertical ins', int_vert_r)
foundation.setInteriorVerticalInsulationMaterial(int_vert_mat)
foundation.setInteriorVerticalInsulationDepth(UnitConversions.convert(int_vert_depth, 'ft', 'm'))
end
# Exterior vertical insulation
if (ext_vert_r > 0) && (ext_vert_depth > 0)
- ext_vert_mat = create_insulation_material(model, 'FoundationExtVertIns', ext_vert_r)
+ ext_vert_mat = create_insulation_material(model, 'exterior vertical ins', ext_vert_r)
foundation.setExteriorVerticalInsulationMaterial(ext_vert_mat)
foundation.setExteriorVerticalInsulationDepth(UnitConversions.convert(ext_vert_depth, 'ft', 'm'))
end
@@ -1072,14 +1107,14 @@ def self.create_kiva_slab_foundation(model, int_horiz_r, int_horiz_width, int_ve
def self.apply_kiva_walled_foundation(model, ext_vert_r, int_vert_r,
ext_vert_offset, int_vert_offset, ext_vert_depth, int_vert_depth,
- wall_height_above_grade, wall_concrete_thick_in, wall_drywall_thick_in)
+ wall_height_above_grade, wall_concrete_thick_in, wall_mat_int_finish)
# Create the Foundation:Kiva object for crawl/basement foundations
foundation = OpenStudio::Model::FoundationKiva.new(model)
# Interior vertical insulation
if (int_vert_r > 0) && (int_vert_depth > 0)
- int_vert_mat = create_insulation_material(model, 'FoundationIntVertIns', int_vert_r)
+ int_vert_mat = create_insulation_material(model, 'interior vertical ins', int_vert_r)
foundation.addCustomBlock(int_vert_mat,
UnitConversions.convert(int_vert_depth, 'ft', 'm'),
-int_vert_mat.thickness,
@@ -1088,10 +1123,11 @@ def self.apply_kiva_walled_foundation(model, ext_vert_r, int_vert_r,
# Exterior vertical insulation
if (ext_vert_r > 0) && (ext_vert_depth > 0)
- ext_vert_mat = create_insulation_material(model, 'FoundationExtVertIns', ext_vert_r)
+ ext_vert_mat = create_insulation_material(model, 'exterior vertical ins', ext_vert_r)
+ wall_mat_int_finish_thick_in = wall_mat_int_finish.nil? ? 0.0 : wall_mat_int_finish.thick_in
foundation.addCustomBlock(ext_vert_mat,
UnitConversions.convert(ext_vert_depth, 'ft', 'm'),
- UnitConversions.convert(wall_concrete_thick_in + wall_drywall_thick_in, 'in', 'm'),
+ UnitConversions.convert(wall_concrete_thick_in + wall_mat_int_finish_thick_in, 'in', 'm'),
UnitConversions.convert(ext_vert_offset, 'ft', 'm'))
end
@@ -1156,7 +1192,7 @@ def self.apply_window_skylight(runner, model, type, subsurface, constr_name, ufa
# by 1.20." Thus we divide by 1.2 to get the vertical position value.
ufactor /= 1.2
end
- glaz_mat = GlazingMaterial.new("#{type}Material", ufactor, shgc)
+ glaz_mat = GlazingMaterial.new(name: "#{type}Material", ufactor: ufactor, shgc: shgc)
# Set paths
path_fracs = [1]
@@ -1234,29 +1270,35 @@ def self.apply_window_skylight_shading(model, window_or_skylight, index, shading
def self.calc_non_cavity_r(film_r, constr_set)
# Calculate R-value for all non-cavity layers
non_cavity_r = film_r
- if not constr_set.exterior_material.nil?
- non_cavity_r += constr_set.exterior_material.rvalue
+ if not constr_set.mat_ext_finish.nil?
+ non_cavity_r += constr_set.mat_ext_finish.rvalue
end
if not constr_set.rigid_r.nil?
non_cavity_r += constr_set.rigid_r
end
if not constr_set.osb_thick_in.nil?
- non_cavity_r += Material.Plywood(constr_set.osb_thick_in).rvalue
+ non_cavity_r += Material.OSBSheathing(constr_set.osb_thick_in).rvalue
end
- if not constr_set.drywall_thick_in.nil?
- non_cavity_r += Material.GypsumWall(constr_set.drywall_thick_in).rvalue
+ if not constr_set.mat_int_finish.nil?
+ non_cavity_r += constr_set.mat_int_finish.rvalue
end
return non_cavity_r
end
- def self.apply_wall_construction(runner, model, surfaces, wall, wall_id, wall_type, assembly_r,
- drywall_thick_in, inside_film, outside_film, mat_ext_finish)
+ def self.apply_wall_construction(runner, model, surfaces, wall_id, wall_type, assembly_r,
+ mat_int_finish, inside_film, outside_film, mat_ext_finish,
+ solar_absorptance, emittance)
film_r = inside_film.rvalue + outside_film.rvalue
if mat_ext_finish.nil?
fallback_mat_ext_finish = nil
else
- fallback_mat_ext_finish = Material.ExteriorFinishMaterial(mat_ext_finish.name, mat_ext_finish.tAbs, mat_ext_finish.sAbs, 0.1)
+ fallback_mat_ext_finish = Material.ExteriorFinishMaterial(mat_ext_finish.name, 0.1) # Try thin material
+ end
+ if mat_int_finish.nil?
+ fallback_mat_int_finish = nil
+ else
+ fallback_mat_int_finish = Material.InteriorFinishMaterial(mat_int_finish.name, 0.1) # Try thin material
end
if wall_type == HPXML::WallTypeWoodStud
@@ -1264,57 +1306,60 @@ def self.apply_wall_construction(runner, model, surfaces, wall, wall_id, wall_ty
cavity_filled = true
constr_sets = [
- WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 20.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c. + R20
- WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 10.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c. + R10
- WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.23, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x4, 16" o.c.
- WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 20.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c. + R20
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 10.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c. + R10
+ WoodStudConstructionSet.new(Material.Stud2x6, 0.20, 0.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.23, 0.0, 0.5, mat_int_finish, mat_ext_finish), # 2x4, 16" o.c.
+ WoodStudConstructionSet.new(Material.Stud2x4, 0.01, 0.0, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, cavity_r = pick_wood_stud_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_wood_stud_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_wood_stud_wall(runner, model, surfaces, "#{wall_id} construction",
cavity_r, install_grade, constr_set.stud.thick_in,
cavity_filled, constr_set.framing_factor,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- constr_set.rigid_r, constr_set.exterior_material,
- 0, inside_film, outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ constr_set.rigid_r, constr_set.mat_ext_finish,
+ inside_film, outside_film, solar_absorptance,
+ emittance)
elsif wall_type == HPXML::WallTypeSteelStud
install_grade = 1
cavity_filled = true
corr_factor = 0.45
constr_sets = [
- SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 10.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c. + R20
- SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 10.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c. + R10
- SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x6, 24" o.c.
- SteelStudConstructionSet.new(3.5, corr_factor, 0.23, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x4, 16" o.c.
- SteelStudConstructionSet.new(3.5, 1.0, 0.01, 0.0, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 10.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c. + R20
+ SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 10.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c. + R10
+ SteelStudConstructionSet.new(5.5, corr_factor, 0.20, 0.0, 0.5, mat_int_finish, mat_ext_finish), # 2x6, 24" o.c.
+ SteelStudConstructionSet.new(3.5, corr_factor, 0.23, 0.0, 0.5, mat_int_finish, mat_ext_finish), # 2x4, 16" o.c.
+ SteelStudConstructionSet.new(3.5, 1.0, 0.01, 0.0, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, cavity_r = pick_steel_stud_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_steel_stud_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_steel_stud_wall(runner, model, surfaces, "#{wall_id} construction",
cavity_r, install_grade, constr_set.cavity_thick_in,
cavity_filled, constr_set.framing_factor,
- constr_set.corr_factor, constr_set.drywall_thick_in,
+ constr_set.corr_factor, constr_set.mat_int_finish,
constr_set.osb_thick_in, constr_set.rigid_r,
- constr_set.exterior_material, inside_film, outside_film)
+ constr_set.mat_ext_finish, inside_film, outside_film,
+ solar_absorptance, emittance)
elsif wall_type == HPXML::WallTypeDoubleWoodStud
install_grade = 1
is_staggered = false
constr_sets = [
- DoubleStudConstructionSet.new(Material.Stud2x4, 0.23, 24.0, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # 2x4, 24" o.c.
- DoubleStudConstructionSet.new(Material.Stud2x4, 0.01, 16.0, 0.0, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ DoubleStudConstructionSet.new(Material.Stud2x4, 0.23, 24.0, 0.0, 0.5, mat_int_finish, mat_ext_finish), # 2x4, 24" o.c.
+ DoubleStudConstructionSet.new(Material.Stud2x4, 0.01, 16.0, 0.0, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, cavity_r = pick_double_stud_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_double_stud_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_double_stud_wall(runner, model, surfaces, "#{wall_id} construction",
cavity_r, install_grade, constr_set.stud.thick_in,
constr_set.stud.thick_in, constr_set.framing_factor,
constr_set.framing_spacing, is_staggered,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- constr_set.rigid_r, constr_set.exterior_material,
- inside_film, outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ constr_set.rigid_r, constr_set.mat_ext_finish,
+ inside_film, outside_film, solar_absorptance,
+ emittance)
elsif wall_type == HPXML::WallTypeCMU
density = 119.0 # lb/ft^3
furring_r = 0
@@ -1322,51 +1367,53 @@ def self.apply_wall_construction(runner, model, surfaces, wall, wall_id, wall_ty
furring_spacing = 0
constr_sets = [
- CMUConstructionSet.new(8.0, 1.4, 0.08, 0.5, drywall_thick_in, mat_ext_finish), # 8" perlite-filled CMU
- CMUConstructionSet.new(6.0, 5.29, 0.01, 0.0, 0.0, fallback_mat_ext_finish), # Fallback (6" hollow CMU)
+ CMUConstructionSet.new(8.0, 1.4, 0.08, 0.5, mat_int_finish, mat_ext_finish), # 8" perlite-filled CMU
+ CMUConstructionSet.new(6.0, 5.29, 0.01, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback (6" hollow CMU)
]
match, constr_set, rigid_r = pick_cmu_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_cmu_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_cmu_wall(runner, model, surfaces, "#{wall_id} construction",
constr_set.thick_in, constr_set.cond_in, density,
constr_set.framing_factor, furring_r,
furring_cavity_depth_in, furring_spacing,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- rigid_r, constr_set.exterior_material, inside_film,
- outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ rigid_r, constr_set.mat_ext_finish, inside_film,
+ outside_film, solar_absorptance, emittance)
elsif wall_type == HPXML::WallTypeSIP
sheathing_thick_in = 0.44
constr_sets = [
- SIPConstructionSet.new(10.0, 0.16, 0.0, sheathing_thick_in, 0.5, drywall_thick_in, mat_ext_finish), # 10" SIP core
- SIPConstructionSet.new(5.0, 0.16, 0.0, sheathing_thick_in, 0.5, drywall_thick_in, mat_ext_finish), # 5" SIP core
- SIPConstructionSet.new(1.0, 0.01, 0.0, sheathing_thick_in, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ SIPConstructionSet.new(10.0, 0.16, 0.0, sheathing_thick_in, 0.5, mat_int_finish, mat_ext_finish), # 10" SIP core
+ SIPConstructionSet.new(5.0, 0.16, 0.0, sheathing_thick_in, 0.5, mat_int_finish, mat_ext_finish), # 5" SIP core
+ SIPConstructionSet.new(1.0, 0.01, 0.0, sheathing_thick_in, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, cavity_r = pick_sip_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_sip_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_sip_wall(runner, model, surfaces, "#{wall_id} construction",
cavity_r, constr_set.thick_in, constr_set.framing_factor,
- constr_set.sheath_thick_in, constr_set.drywall_thick_in,
+ constr_set.sheath_thick_in, constr_set.mat_int_finish,
constr_set.osb_thick_in, constr_set.rigid_r,
- constr_set.exterior_material, inside_film, outside_film)
+ constr_set.mat_ext_finish, inside_film, outside_film,
+ solar_absorptance, emittance)
elsif wall_type == HPXML::WallTypeICF
constr_sets = [
- ICFConstructionSet.new(2.0, 4.0, 0.08, 0.0, 0.5, drywall_thick_in, mat_ext_finish), # ICF w/4" concrete and 2" rigid ins layers
- ICFConstructionSet.new(1.0, 1.0, 0.01, 0.0, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ ICFConstructionSet.new(2.0, 4.0, 0.08, 0.0, 0.5, mat_int_finish, mat_ext_finish), # ICF w/4" concrete and 2" rigid ins layers
+ ICFConstructionSet.new(1.0, 1.0, 0.01, 0.0, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, icf_r = pick_icf_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
- apply_icf_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_icf_wall(runner, model, surfaces, "#{wall_id} construction",
icf_r, constr_set.ins_thick_in,
constr_set.concrete_thick_in, constr_set.framing_factor,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- constr_set.rigid_r, constr_set.exterior_material,
- inside_film, outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ constr_set.rigid_r, constr_set.mat_ext_finish,
+ inside_film, outside_film, solar_absorptance,
+ emittance)
elsif [HPXML::WallTypeConcrete, HPXML::WallTypeBrick, HPXML::WallTypeAdobe, HPXML::WallTypeStrawBale, HPXML::WallTypeStone, HPXML::WallTypeLog].include? wall_type
constr_sets = [
- GenericConstructionSet.new(10.0, 0.5, drywall_thick_in, mat_ext_finish), # w/R-10 rigid
- GenericConstructionSet.new(0.0, 0.5, drywall_thick_in, mat_ext_finish), # Standard
- GenericConstructionSet.new(0.0, 0.0, 0.0, fallback_mat_ext_finish), # Fallback
+ GenericConstructionSet.new(10.0, 0.5, mat_int_finish, mat_ext_finish), # w/R-10 rigid
+ GenericConstructionSet.new(0.0, 0.5, mat_int_finish, mat_ext_finish), # Standard
+ GenericConstructionSet.new(0.0, 0.0, fallback_mat_int_finish, fallback_mat_ext_finish), # Fallback
]
match, constr_set, layer_r = pick_generic_construction_set(assembly_r, constr_sets, inside_film, outside_film, wall_id)
@@ -1398,11 +1445,12 @@ def self.apply_wall_construction(runner, model, surfaces, wall, wall_id, wall_ty
denss = [base_mat.rho]
specheats = [base_mat.cp]
- apply_generic_layered_wall(runner, model, surfaces, wall, "#{wall_id} construction",
+ apply_generic_layered_wall(runner, model, surfaces, "#{wall_id} construction",
thick_ins, conds, denss, specheats,
- constr_set.drywall_thick_in, constr_set.osb_thick_in,
- constr_set.rigid_r, constr_set.exterior_material,
- inside_film, outside_film)
+ constr_set.mat_int_finish, constr_set.osb_thick_in,
+ constr_set.rigid_r, constr_set.mat_ext_finish,
+ inside_film, outside_film, solar_absorptance,
+ emittance)
else
fail "Unexpected wall type '#{wall_type}'."
end
@@ -1424,7 +1472,7 @@ def self.pick_wood_stud_construction_set(assembly_r, constr_sets, inside_film, o
# Assumes installation quality 1
cavity_frac = 1.0 - constr_set.framing_factor
cavity_r = cavity_frac / (1.0 / assembly_r - constr_set.framing_factor / (constr_set.stud.rvalue + non_cavity_r)) - non_cavity_r
- if cavity_r > 0 # Choose this construction set
+ if cavity_r > 0 && cavity_r < Float::INFINITY # Choose this construction set
return true, constr_set, cavity_r
end
end
@@ -1445,7 +1493,7 @@ def self.pick_steel_stud_construction_set(assembly_r, constr_sets, inside_film,
# Calculate effective cavity R-value
# Assumes installation quality 1
cavity_r = (assembly_r - non_cavity_r) / constr_set.corr_factor
- if cavity_r > 0 # Choose this construction set
+ if cavity_r > 0 && cavity_r < Float::INFINITY # Choose this construction set
return true, constr_set, cavity_r
end
end
@@ -1476,7 +1524,7 @@ def self.pick_double_stud_construction_set(assembly_r, constr_sets, inside_film,
e = misc_framing_factor
cavity_r = ((3 * c + d) * Math.sqrt(4 * a**2 * b**2 + 12 * a**2 * b * e + 4 * a**2 * b + 9 * a**2 * e**2 - 6 * a**2 * e + a**2 - 48 * a * b * c - 16 * a * b * d - 36 * a * c * e + 12 * a * c - 12 * a * d * e + 4 * a * d + 36 * c**2 + 24 * c * d + 4 * d**2) + 6 * a * b * c + 2 * a * b * d + 3 * a * c * e + 3 * a * c + 3 * a * d * e + a * d - 18 * c**2 - 18 * c * d - 4 * d**2) / (2 * (-3 * a * e + 9 * c + 3 * d))
cavity_r = 3 * cavity_r
- if cavity_r > 0 # Choose this construction set
+ if cavity_r > 0 && cavity_r < Float::INFINITY # Choose this construction set
return true, constr_set, cavity_r
end
end
@@ -1493,14 +1541,14 @@ def self.pick_sip_construction_set(assembly_r, constr_sets, inside_film, outside
film_r = inside_film.rvalue + outside_film.rvalue
non_cavity_r = calc_non_cavity_r(film_r, constr_set)
- non_cavity_r += Material.new(nil, constr_set.sheath_thick_in, BaseMaterial.Wood).rvalue
+ non_cavity_r += Material.new(thick_in: constr_set.sheath_thick_in, mat_base: BaseMaterial.Wood).rvalue
# Calculate effective SIP core R-value
# Solved in Wolfram Alpha: https://www.wolframalpha.com/input/?i=1%2FA+%3D+B%2F(C%2BD)+%2B+E%2F(2*F%2BG%2FH*x%2BD)+%2B+(1-B-E)%2F(x%2BD)
spline_thick_in = 0.5 # in
ins_thick_in = constr_set.thick_in - (2.0 * spline_thick_in) # in
- framing_r = Material.new(nil, constr_set.thick_in, BaseMaterial.Wood).rvalue
- spline_r = Material.new(nil, spline_thick_in, BaseMaterial.Wood).rvalue
+ framing_r = Material.new(thick_in: constr_set.thick_in, mat_base: BaseMaterial.Wood).rvalue
+ spline_r = Material.new(thick_in: spline_thick_in, mat_base: BaseMaterial.Wood).rvalue
spline_frac = 4.0 / 48.0 # One 4" spline for every 48" wide panel
cavity_frac = 1.0 - (spline_frac + constr_set.framing_factor)
a = assembly_r
@@ -1512,7 +1560,7 @@ def self.pick_sip_construction_set(assembly_r, constr_sets, inside_film, outside
g = ins_thick_in
h = constr_set.thick_in
cavity_r = (Math.sqrt((a * b * c * g - a * b * d * h - 2 * a * b * f * h + a * c * e * g - a * c * e * h - a * c * g + a * d * e * g - a * d * e * h - a * d * g + c * d * g + c * d * h + 2 * c * f * h + d**2 * g + d**2 * h + 2 * d * f * h)**2 - 4 * (-a * b * g + c * g + d * g) * (a * b * c * d * h + 2 * a * b * c * f * h - a * c * d * h + 2 * a * c * e * f * h - 2 * a * c * f * h - a * d**2 * h + 2 * a * d * e * f * h - 2 * a * d * f * h + c * d**2 * h + 2 * c * d * f * h + d**3 * h + 2 * d**2 * f * h)) - a * b * c * g + a * b * d * h + 2 * a * b * f * h - a * c * e * g + a * c * e * h + a * c * g - a * d * e * g + a * d * e * h + a * d * g - c * d * g - c * d * h - 2 * c * f * h - g * d**2 - d**2 * h - 2 * d * f * h) / (2 * (-a * b * g + c * g + d * g))
- if cavity_r > 0 # Choose this construction set
+ if cavity_r > 0 && cavity_r < Float::INFINITY # Choose this construction set
return true, constr_set, cavity_r
end
end
@@ -1535,11 +1583,11 @@ def self.pick_cmu_construction_set(assembly_r, constr_sets, inside_film, outside
# Solved in Wolfram Alpha: https://www.wolframalpha.com/input/?i=1%2FA+%3D+B%2F(C%2BE%2Bx)+%2B+(1-B)%2F(D%2BE%2Bx)
a = assembly_r
b = constr_set.framing_factor
- c = Material.new(nil, constr_set.thick_in, BaseMaterial.Wood).rvalue # Framing
- d = Material.new(nil, constr_set.thick_in, BaseMaterial.Concrete, constr_set.cond_in).rvalue # Concrete
+ c = Material.new(thick_in: constr_set.thick_in, mat_base: BaseMaterial.Wood).rvalue # Framing
+ d = Material.new(thick_in: constr_set.thick_in, mat_base: BaseMaterial.Concrete, k_in: constr_set.cond_in).rvalue # Concrete
e = non_cavity_r
rigid_r = 0.5 * (Math.sqrt(a**2 - 4 * a * b * c + 4 * a * b * d + 2 * a * c - 2 * a * d + c**2 - 2 * c * d + d**2) + a - c - d - 2 * e)
- if rigid_r > 0 # Choose this construction set
+ if rigid_r > 0 && rigid_r < Float::INFINITY # Choose this construction set
return true, constr_set, rigid_r
end
end
@@ -1561,11 +1609,11 @@ def self.pick_icf_construction_set(assembly_r, constr_sets, inside_film, outside
# Solved in Wolfram Alpha: https://www.wolframalpha.com/input/?i=1%2FA+%3D+B%2F(C%2BE)+%2B+(1-B)%2F(D%2BE%2B2*x)
a = assembly_r
b = constr_set.framing_factor
- c = Material.new(nil, 2 * constr_set.ins_thick_in + constr_set.concrete_thick_in, BaseMaterial.Wood).rvalue # Framing
- d = Material.new(nil, constr_set.concrete_thick_in, BaseMaterial.Concrete).rvalue # Concrete
+ c = Material.new(thick_in: 2 * constr_set.ins_thick_in + constr_set.concrete_thick_in, mat_base: BaseMaterial.Wood).rvalue # Framing
+ d = Material.new(thick_in: constr_set.concrete_thick_in, mat_base: BaseMaterial.Concrete).rvalue # Concrete
e = non_cavity_r
icf_r = (a * b * c - a * b * d - a * c - a * e + c * d + c * e + d * e + e**2) / (2 * (a * b - c - e))
- if icf_r > 0 # Choose this construction set
+ if icf_r > 0 && icf_r < Float::INFINITY # Choose this construction set
return true, constr_set, icf_r
end
end
@@ -1585,7 +1633,7 @@ def self.pick_generic_construction_set(assembly_r, constr_sets, inside_film, out
# Calculate effective ins layer R-value
layer_r = assembly_r - non_cavity_r
- if layer_r > 0 # Choose this construction set
+ if layer_r > 0 && layer_r < Float::INFINITY # Choose this construction set
return true, constr_set, layer_r
end
end
@@ -1713,13 +1761,29 @@ def create_and_assign_constructions(runner, surfaces, model)
end
end
+ def set_exterior_material_properties(solar_absorptance = 0.75, emittance = 0.9)
+ @layers_materials[1].each do |exterior_material|
+ exterior_material.sAbs = solar_absorptance
+ exterior_material.tAbs = emittance
+ end
+ end
+
+ def set_interior_material_properties(solar_absorptance = 0.6, emittance = 0.9, debug: false)
+ if @layers_materials.size > 3 # Only apply if there is a separate interior material
+ @layers_materials[-2].each do |interior_material|
+ interior_material.sAbs = solar_absorptance
+ interior_material.tAbs = emittance
+ end
+ end
+ end
+
private
def get_parallel_material(curr_layer_num, name)
# Returns a Material object with effective properties for the specified
# parallel path layer of the construction.
- mat = Material.new(name)
+ mat = Material.new(name: name)
curr_layer_materials = @layers_materials[curr_layer_num]
@@ -1767,6 +1831,12 @@ def get_parallel_material(curr_layer_num, name)
mat.cp += (curr_layer_materials[path_num].cp * curr_layer_materials[path_num].rho * path_frac) / mat.rho
end
+ # Material solar absorptance
+ mat.sAbs = curr_layer_materials[0].sAbs # All paths have equal solar absorptance
+
+ # Material thermal absorptance
+ mat.tAbs = curr_layer_materials[0].tAbs # All paths have equal thermal absorptance
+
return mat
end
@@ -1822,8 +1892,8 @@ def validate
# Check for valid object types
@layers_materials.each do |layer_materials|
layer_materials.each do |mat|
- if (not mat.is_a? SimpleMaterial) && (not mat.is_a? Material)
- fail 'Invalid construction: Materials must be instances of SimpleMaterial or Material classes.'
+ if (not mat.is_a? Material)
+ fail 'Invalid construction: Materials must be instances of Material classes.'
end
end
end
@@ -1835,17 +1905,29 @@ def validate
end
end
- # Check if multiple materials in a given layer have differing thicknesses
+ # Check if multiple materials in a given layer have differing thicknesses/absorptances
@layers_materials.each do |layer_materials|
next unless layer_materials.size > 1
thick_in = nil
+ solar_abs = nil
+ emitt = nil
layer_materials.each do |mat|
if thick_in.nil?
thick_in = mat.thick_in
elsif thick_in != mat.thick_in
fail 'Invalid construction: Materials in a layer have different thicknesses.'
end
+ if solar_abs.nil?
+ solar_abs = mat.sAbs
+ elsif solar_abs != mat.sAbs
+ fail 'Invalid construction: Materials in a layer have different solar absorptances.'
+ end
+ if emitt.nil?
+ emitt = mat.tAbs
+ elsif emitt != mat.tAbs
+ fail 'Invalid construction: Materials in a layer have different thermal absorptances.'
+ end
end
end
@@ -1868,20 +1950,7 @@ def validate
def self.create_os_material(runner, model, material)
name = material.name
tolerance = 0.0001
- if material.is_a? SimpleMaterial
- # Material already exists?
- model.getMasslessOpaqueMaterials.each do |mat|
- next if mat.roughness.downcase.to_s != 'rough'
- next if (mat.thermalResistance - UnitConversions.convert(material.rvalue, 'hr*ft^2*F/Btu', 'm^2*K/W')).abs > tolerance
-
- return mat
- end
- # New material
- mat = OpenStudio::Model::MasslessOpaqueMaterial.new(model)
- mat.setName(name)
- mat.setRoughness('Rough')
- mat.setThermalResistance(UnitConversions.convert(material.rvalue, 'hr*ft^2*F/Btu', 'm^2*K/W'))
- elsif material.is_a? GlazingMaterial
+ if material.is_a? GlazingMaterial
max_ufactor = UnitConversions.convert(7.0, 'W/(m^2*K)', 'Btu/(hr*ft^2*F)') # Max value EnergyPlus allows
if material.ufactor > max_ufactor
runner.registerWarning("Glazing U-factor (#{material.ufactor}) for '#{material.name}' above maximum expected value. U-factor decreased to #{max_ufactor.round(2)}.")
@@ -1890,11 +1959,13 @@ def self.create_os_material(runner, model, material)
# Material already exists?
model.getSimpleGlazings.each do |mat|
+ next if !mat.name.to_s.start_with?(material.name)
next if (mat.uFactor - UnitConversions.convert(material.ufactor, 'Btu/(hr*ft^2*F)', 'W/(m^2*K)')).abs > tolerance
next if (mat.solarHeatGainCoefficient - material.shgc).abs > tolerance
return mat
end
+
# New material
mat = OpenStudio::Model::SimpleGlazing.new(model)
mat.setName(name)
@@ -1903,17 +1974,18 @@ def self.create_os_material(runner, model, material)
else
# Material already exists?
model.getStandardOpaqueMaterials.each do |mat|
+ next if !mat.name.to_s.start_with?(material.name)
next if mat.roughness.downcase.to_s != 'rough'
next if (mat.thickness - UnitConversions.convert(material.thick_in, 'in', 'm')).abs > tolerance
next if (mat.conductivity - UnitConversions.convert(material.k, 'Btu/(hr*ft*R)', 'W/(m*K)')).abs > tolerance
next if (mat.density - UnitConversions.convert(material.rho, 'lbm/ft^3', 'kg/m^3')).abs > tolerance
next if (mat.specificHeat - UnitConversions.convert(material.cp, 'Btu/(lbm*R)', 'J/(kg*K)')).abs > tolerance
- next if (not material.tAbs.nil?) && ((mat.thermalAbsorptance - material.tAbs).abs > tolerance)
- next if (not material.sAbs.nil?) && ((mat.solarAbsorptance - material.sAbs).abs > tolerance)
- next if (not material.vAbs.nil?) && ((mat.visibleAbsorptance - material.vAbs).abs > tolerance)
+ next if (mat.thermalAbsorptance - material.tAbs.to_f).abs > tolerance
+ next if (mat.solarAbsorptance - material.sAbs.to_f).abs > tolerance
return mat
end
+
# New material
mat = OpenStudio::Model::StandardOpaqueMaterial.new(model)
mat.setName(name)
@@ -1927,9 +1999,7 @@ def self.create_os_material(runner, model, material)
end
if not material.sAbs.nil?
mat.setSolarAbsorptance(material.sAbs)
- end
- if not material.vAbs.nil?
- mat.setVisibleAbsorptance(material.vAbs)
+ mat.setVisibleAbsorptance(material.sAbs)
end
end
return mat
@@ -1937,88 +2007,88 @@ def self.create_os_material(runner, model, material)
end
class WoodStudConstructionSet
- def initialize(stud, framing_factor, rigid_r, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(stud, framing_factor, rigid_r, osb_thick_in, mat_int_finish, mat_ext_finish)
@stud = stud
@framing_factor = framing_factor
@rigid_r = rigid_r
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:stud, :framing_factor, :rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:stud, :framing_factor, :rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class SteelStudConstructionSet
- def initialize(cavity_thick_in, corr_factor, framing_factor, rigid_r, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(cavity_thick_in, corr_factor, framing_factor, rigid_r, osb_thick_in, mat_int_finish, mat_ext_finish)
@cavity_thick_in = cavity_thick_in
@corr_factor = corr_factor
@framing_factor = framing_factor
@rigid_r = rigid_r
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:cavity_thick_in, :corr_factor, :framing_factor, :rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:cavity_thick_in, :corr_factor, :framing_factor, :rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class DoubleStudConstructionSet
- def initialize(stud, framing_factor, framing_spacing, rigid_r, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(stud, framing_factor, framing_spacing, rigid_r, osb_thick_in, mat_int_finish, mat_ext_finish)
@stud = stud
@framing_factor = framing_factor
@framing_spacing = framing_spacing
@rigid_r = rigid_r
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:stud, :framing_factor, :framing_spacing, :rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:stud, :framing_factor, :framing_spacing, :rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class SIPConstructionSet
- def initialize(thick_in, framing_factor, rigid_r, sheath_thick_in, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(thick_in, framing_factor, rigid_r, sheath_thick_in, osb_thick_in, mat_int_finish, mat_ext_finish)
@thick_in = thick_in
@framing_factor = framing_factor
@rigid_r = rigid_r
@sheath_thick_in = sheath_thick_in
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:thick_in, :framing_factor, :rigid_r, :sheath_thick_in, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:thick_in, :framing_factor, :rigid_r, :sheath_thick_in, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class CMUConstructionSet
- def initialize(thick_in, cond_in, framing_factor, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(thick_in, cond_in, framing_factor, osb_thick_in, mat_int_finish, mat_ext_finish)
@thick_in = thick_in
@cond_in = cond_in
@framing_factor = framing_factor
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
@rigid_r = nil # solved for
end
- attr_accessor(:thick_in, :cond_in, :framing_factor, :rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:thick_in, :cond_in, :framing_factor, :rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class ICFConstructionSet
- def initialize(ins_thick_in, concrete_thick_in, framing_factor, rigid_r, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(ins_thick_in, concrete_thick_in, framing_factor, rigid_r, osb_thick_in, mat_int_finish, mat_ext_finish)
@ins_thick_in = ins_thick_in
@concrete_thick_in = concrete_thick_in
@framing_factor = framing_factor
@rigid_r = rigid_r
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:ins_thick_in, :concrete_thick_in, :framing_factor, :rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:ins_thick_in, :concrete_thick_in, :framing_factor, :rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
class GenericConstructionSet
- def initialize(rigid_r, osb_thick_in, drywall_thick_in, exterior_material)
+ def initialize(rigid_r, osb_thick_in, mat_int_finish, mat_ext_finish)
@rigid_r = rigid_r
@osb_thick_in = osb_thick_in
- @drywall_thick_in = drywall_thick_in
- @exterior_material = exterior_material
+ @mat_int_finish = mat_int_finish
+ @mat_ext_finish = mat_ext_finish
end
- attr_accessor(:rigid_r, :osb_thick_in, :drywall_thick_in, :exterior_material)
+ attr_accessor(:rigid_r, :osb_thick_in, :mat_int_finish, :mat_ext_finish)
end
diff --git a/HPXMLtoOpenStudio/resources/hpxml.rb b/HPXMLtoOpenStudio/resources/hpxml.rb
index ae9ef48625..bdde9f57b2 100644
--- a/HPXMLtoOpenStudio/resources/hpxml.rb
+++ b/HPXMLtoOpenStudio/resources/hpxml.rb
@@ -159,6 +159,11 @@ class HPXML < Object
HydronicTypeRadiantFloor = 'radiant floor'
HydronicTypeRadiator = 'radiator'
HydronicTypeWaterLoop = 'water loop'
+ InteriorFinishGypsumBoard = 'gypsum board'
+ InteriorFinishGypsumCompositeBoard = 'gypsum composite board'
+ InteriorFinishNone = 'none'
+ InteriorFinishPlaster = 'plaster'
+ InteriorFinishWood = 'wood'
LeakinessTight = 'tight'
LeakinessAverage = 'average'
LightingTypeCFL = 'CompactFluorescent'
@@ -230,6 +235,7 @@ class HPXML < Object
SidingTypeAluminum = 'aluminum siding'
SidingTypeBrick = 'brick veneer'
SidingTypeFiberCement = 'fiber cement siding'
+ SidingTypeNone = 'none'
SidingTypeStucco = 'stucco'
SidingTypeVinyl = 'vinyl siding'
SidingTypeWood = 'wood siding'
@@ -252,6 +258,7 @@ class HPXML < Object
UnitsCFM25 = 'CFM25'
UnitsCOP = 'COP'
UnitsEER = 'EER'
+ UnitsCEER = 'CEER'
UnitsHSPF = 'HSPF'
UnitsKwhPerYear = 'kWh/year'
UnitsKwPerTon = 'kW/ton'
@@ -278,6 +285,10 @@ class HPXML < Object
WaterHeaterTypeHeatPump = 'heat pump water heater'
WaterHeaterTypeTankless = 'instantaneous water heater'
WaterHeaterTypeStorage = 'storage water heater'
+ WaterHeaterUsageBinVerySmall = 'very small'
+ WaterHeaterUsageBinLow = 'low'
+ WaterHeaterUsageBinMedium = 'medium'
+ WaterHeaterUsageBinHigh = 'high'
WindowFrameTypeAluminum = 'Aluminum'
WindowFrameTypeComposite = 'Composite'
WindowFrameTypeFiberglass = 'Fiberglass'
@@ -955,7 +966,7 @@ def from_oga(hpxml)
end
class NeighborBuilding < BaseElement
- ATTRS = [:azimuth, :distance, :height]
+ ATTRS = [:azimuth, :orientation, :distance, :height]
attr_accessor(*ATTRS)
def check_for_errors
@@ -968,7 +979,8 @@ def to_oga(doc)
neighbors = XMLHelper.create_elements_as_needed(doc, ['HPXML', 'Building', 'BuildingDetails', 'BuildingSummary', 'Site', 'extension', 'Neighbors'])
neighbor_building = XMLHelper.add_element(neighbors, 'NeighborBuilding')
- XMLHelper.add_element(neighbor_building, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
+ XMLHelper.add_element(neighbor_building, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
+ XMLHelper.add_element(neighbor_building, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
XMLHelper.add_element(neighbor_building, 'Distance', @distance, :float) unless @distance.nil?
XMLHelper.add_element(neighbor_building, 'Height', @height, :float) unless @height.nil?
end
@@ -976,6 +988,7 @@ def to_oga(doc)
def from_oga(neighbor_building)
return if neighbor_building.nil?
+ @orientation = XMLHelper.get_value(neighbor_building, 'Orientation', :string)
@azimuth = XMLHelper.get_value(neighbor_building, 'Azimuth', :integer)
@distance = XMLHelper.get_value(neighbor_building, 'Distance', :float)
@height = XMLHelper.get_value(neighbor_building, 'Height', :float)
@@ -1484,7 +1497,8 @@ class Roof < BaseElement
ATTRS = [:id, :interior_adjacent_to, :area, :azimuth, :orientation, :roof_type,
:roof_color, :solar_absorptance, :emittance, :pitch, :radiant_barrier,
:insulation_id, :insulation_assembly_r_value, :insulation_cavity_r_value,
- :insulation_continuous_r_value, :radiant_barrier_grade]
+ :insulation_continuous_r_value, :radiant_barrier_grade,
+ :interior_finish_type, :interior_finish_thickness]
attr_accessor(*ATTRS)
def skylights
@@ -1524,6 +1538,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.roofs.delete(self)
skylights.reverse_each do |skylight|
@@ -1549,15 +1567,20 @@ def to_oga(doc)
XMLHelper.add_attribute(sys_id, 'id', @id)
XMLHelper.add_element(roof, 'InteriorAdjacentTo', @interior_adjacent_to, :string) unless @interior_adjacent_to.nil?
XMLHelper.add_element(roof, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(roof, 'Orientation', @orientation, :string) unless @orientation.nil?
- XMLHelper.add_element(roof, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
+ XMLHelper.add_element(roof, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
+ XMLHelper.add_element(roof, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
XMLHelper.add_element(roof, 'RoofType', @roof_type, :string, @roof_type_isdefaulted) unless @roof_type.nil?
XMLHelper.add_element(roof, 'RoofColor', @roof_color, :string, @roof_color_isdefaulted) unless @roof_color.nil?
XMLHelper.add_element(roof, 'SolarAbsorptance', @solar_absorptance, :float, @solar_absorptance_isdefaulted) unless @solar_absorptance.nil?
XMLHelper.add_element(roof, 'Emittance', @emittance, :float, @emittance_isdefaulted) unless @emittance.nil?
+ if (not @interior_finish_type.nil?) || (not @interior_finish_thickness.nil?)
+ interior_finish = XMLHelper.add_element(roof, 'InteriorFinish')
+ XMLHelper.add_element(interior_finish, 'Type', @interior_finish_type, :string, @interior_finish_type_isdefaulted) unless @interior_finish_type.nil?
+ XMLHelper.add_element(interior_finish, 'Thickness', @interior_finish_thickness, :float, @interior_finish_thickness_isdefaulted) unless @interior_finish_thickness.nil?
+ end
XMLHelper.add_element(roof, 'Pitch', @pitch, :float) unless @pitch.nil?
XMLHelper.add_element(roof, 'RadiantBarrier', @radiant_barrier, :boolean, @radiant_barrier_isdefaulted) unless @radiant_barrier.nil?
- XMLHelper.add_element(roof, 'RadiantBarrierGrade', @radiant_barrier_grade, :integer) unless @radiant_barrier_grade.nil?
+ XMLHelper.add_element(roof, 'RadiantBarrierGrade', @radiant_barrier_grade, :integer, @radiant_barrier_grade_isdefaulted) unless @radiant_barrier_grade.nil?
insulation = XMLHelper.add_element(roof, 'Insulation')
sys_id = XMLHelper.add_element(insulation, 'SystemIdentifier')
if not @insulation_id.nil?
@@ -1590,6 +1613,11 @@ def from_oga(roof)
@roof_color = XMLHelper.get_value(roof, 'RoofColor', :string)
@solar_absorptance = XMLHelper.get_value(roof, 'SolarAbsorptance', :float)
@emittance = XMLHelper.get_value(roof, 'Emittance', :float)
+ interior_finish = XMLHelper.get_element(roof, 'InteriorFinish')
+ if not interior_finish.nil?
+ @interior_finish_type = XMLHelper.get_value(interior_finish, 'Type', :string)
+ @interior_finish_thickness = XMLHelper.get_value(interior_finish, 'Thickness', :float)
+ end
@pitch = XMLHelper.get_value(roof, 'Pitch', :float)
@radiant_barrier = XMLHelper.get_value(roof, 'RadiantBarrier', :boolean)
@radiant_barrier_grade = XMLHelper.get_value(roof, 'RadiantBarrierGrade', :integer)
@@ -1647,6 +1675,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.rim_joists.delete(self)
end
@@ -1666,8 +1698,8 @@ def to_oga(doc)
XMLHelper.add_element(rim_joist, 'ExteriorAdjacentTo', @exterior_adjacent_to, :string) unless @exterior_adjacent_to.nil?
XMLHelper.add_element(rim_joist, 'InteriorAdjacentTo', @interior_adjacent_to, :string) unless @interior_adjacent_to.nil?
XMLHelper.add_element(rim_joist, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(rim_joist, 'Orientation', @orientation, :string) unless @orientation.nil?
- XMLHelper.add_element(rim_joist, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
+ XMLHelper.add_element(rim_joist, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
+ XMLHelper.add_element(rim_joist, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
XMLHelper.add_element(rim_joist, 'Siding', @siding, :string, @siding_isdefaulted) unless @siding.nil?
XMLHelper.add_element(rim_joist, 'Color', @color, :string, @color_isdefaulted) unless @color.nil?
XMLHelper.add_element(rim_joist, 'SolarAbsorptance', @solar_absorptance, :float, @solar_absorptance_isdefaulted) unless @solar_absorptance.nil?
@@ -1732,7 +1764,8 @@ def from_oga(hpxml)
class Wall < BaseElement
ATTRS = [:id, :exterior_adjacent_to, :interior_adjacent_to, :wall_type, :optimum_value_engineering,
:area, :orientation, :azimuth, :siding, :color, :solar_absorptance, :emittance, :insulation_id,
- :insulation_assembly_r_value, :insulation_cavity_r_value, :insulation_continuous_r_value]
+ :insulation_assembly_r_value, :insulation_cavity_r_value, :insulation_continuous_r_value,
+ :interior_finish_type, :interior_finish_thickness]
attr_accessor(*ATTRS)
def windows
@@ -1780,6 +1813,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.walls.delete(self)
windows.reverse_each do |window|
@@ -1813,12 +1850,17 @@ def to_oga(doc)
end
end
XMLHelper.add_element(wall, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(wall, 'Orientation', @orientation, :string) unless @orientation.nil?
- XMLHelper.add_element(wall, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
+ XMLHelper.add_element(wall, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
+ XMLHelper.add_element(wall, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
XMLHelper.add_element(wall, 'Siding', @siding, :string, @siding_isdefaulted) unless @siding.nil?
XMLHelper.add_element(wall, 'Color', @color, :string, @color_isdefaulted) unless @color.nil?
XMLHelper.add_element(wall, 'SolarAbsorptance', @solar_absorptance, :float, @solar_absorptance_isdefaulted) unless @solar_absorptance.nil?
XMLHelper.add_element(wall, 'Emittance', @emittance, :float, @emittance_isdefaulted) unless @emittance.nil?
+ if (not @interior_finish_type.nil?) || (not @interior_finish_thickness.nil?)
+ interior_finish = XMLHelper.add_element(wall, 'InteriorFinish')
+ XMLHelper.add_element(interior_finish, 'Type', @interior_finish_type, :string, @interior_finish_type_isdefaulted) unless @interior_finish_type.nil?
+ XMLHelper.add_element(interior_finish, 'Thickness', @interior_finish_thickness, :float, @interior_finish_thickness_isdefaulted) unless @interior_finish_thickness.nil?
+ end
insulation = XMLHelper.add_element(wall, 'Insulation')
sys_id = XMLHelper.add_element(insulation, 'SystemIdentifier')
if not @insulation_id.nil?
@@ -1856,6 +1898,11 @@ def from_oga(wall)
@color = XMLHelper.get_value(wall, 'Color', :string)
@solar_absorptance = XMLHelper.get_value(wall, 'SolarAbsorptance', :float)
@emittance = XMLHelper.get_value(wall, 'Emittance', :float)
+ interior_finish = XMLHelper.get_element(wall, 'InteriorFinish')
+ if not interior_finish.nil?
+ @interior_finish_type = XMLHelper.get_value(interior_finish, 'Type', :string)
+ @interior_finish_thickness = XMLHelper.get_value(interior_finish, 'Thickness', :float)
+ end
insulation = XMLHelper.get_element(wall, 'Insulation')
if not insulation.nil?
@insulation_id = HPXML::get_id(insulation)
@@ -1881,12 +1928,12 @@ def from_oga(hpxml)
end
class FoundationWall < BaseElement
- ATTRS = [:id, :exterior_adjacent_to, :interior_adjacent_to, :height, :area, :orientation, :azimuth,
- :thickness, :depth_below_grade, :insulation_id, :insulation_interior_r_value,
+ ATTRS = [:id, :exterior_adjacent_to, :interior_adjacent_to, :length, :height, :area, :orientation,
+ :azimuth, :thickness, :depth_below_grade, :insulation_id, :insulation_interior_r_value,
:insulation_interior_distance_to_top, :insulation_interior_distance_to_bottom,
:insulation_exterior_r_value, :insulation_exterior_distance_to_top,
:insulation_exterior_distance_to_bottom, :insulation_assembly_r_value,
- :insulation_continuous_r_value]
+ :insulation_continuous_r_value, :interior_finish_type, :interior_finish_thickness]
attr_accessor(*ATTRS)
def windows
@@ -1936,6 +1983,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.foundation_walls.delete(self)
windows.reverse_each do |window|
@@ -1964,12 +2015,18 @@ def to_oga(doc)
XMLHelper.add_attribute(sys_id, 'id', @id)
XMLHelper.add_element(foundation_wall, 'ExteriorAdjacentTo', @exterior_adjacent_to, :string) unless @exterior_adjacent_to.nil?
XMLHelper.add_element(foundation_wall, 'InteriorAdjacentTo', @interior_adjacent_to, :string) unless @interior_adjacent_to.nil?
+ XMLHelper.add_element(foundation_wall, 'Length', @length, :float) unless @length.nil?
XMLHelper.add_element(foundation_wall, 'Height', @height, :float) unless @height.nil?
- XMLHelper.add_element(foundation_wall, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(foundation_wall, 'Orientation', @orientation, :string) unless @orientation.nil?
- XMLHelper.add_element(foundation_wall, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
+ XMLHelper.add_element(foundation_wall, 'Area', @area, :float, @area_isdefaulted) unless @area.nil?
+ XMLHelper.add_element(foundation_wall, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
+ XMLHelper.add_element(foundation_wall, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
XMLHelper.add_element(foundation_wall, 'Thickness', @thickness, :float, @thickness_isdefaulted) unless @thickness.nil?
XMLHelper.add_element(foundation_wall, 'DepthBelowGrade', @depth_below_grade, :float) unless @depth_below_grade.nil?
+ if (not @interior_finish_type.nil?) || (not @interior_finish_thickness.nil?)
+ interior_finish = XMLHelper.add_element(foundation_wall, 'InteriorFinish')
+ XMLHelper.add_element(interior_finish, 'Type', @interior_finish_type, :string, @interior_finish_type_isdefaulted) unless @interior_finish_type.nil?
+ XMLHelper.add_element(interior_finish, 'Thickness', @interior_finish_thickness, :float, @interior_finish_thickness_isdefaulted) unless @interior_finish_thickness.nil?
+ end
insulation = XMLHelper.add_element(foundation_wall, 'Insulation')
sys_id = XMLHelper.add_element(insulation, 'SystemIdentifier')
if not @insulation_id.nil?
@@ -1982,15 +2039,15 @@ def to_oga(doc)
layer = XMLHelper.add_element(insulation, 'Layer')
XMLHelper.add_element(layer, 'InstallationType', 'continuous - exterior', :string)
XMLHelper.add_element(layer, 'NominalRValue', @insulation_exterior_r_value, :float)
- XMLHelper.add_extension(layer, 'DistanceToTopOfInsulation', @insulation_exterior_distance_to_top, :float) unless @insulation_exterior_distance_to_top.nil?
- XMLHelper.add_extension(layer, 'DistanceToBottomOfInsulation', @insulation_exterior_distance_to_bottom, :float) unless @insulation_exterior_distance_to_bottom.nil?
+ XMLHelper.add_extension(layer, 'DistanceToTopOfInsulation', @insulation_exterior_distance_to_top, :float, @insulation_exterior_distance_to_top_isdefaulted) unless @insulation_exterior_distance_to_top.nil?
+ XMLHelper.add_extension(layer, 'DistanceToBottomOfInsulation', @insulation_exterior_distance_to_bottom, :float, @insulation_exterior_distance_to_bottom_isdefaulted) unless @insulation_exterior_distance_to_bottom.nil?
end
if not @insulation_interior_r_value.nil?
layer = XMLHelper.add_element(insulation, 'Layer')
XMLHelper.add_element(layer, 'InstallationType', 'continuous - interior', :string)
XMLHelper.add_element(layer, 'NominalRValue', @insulation_interior_r_value, :float)
- XMLHelper.add_extension(layer, 'DistanceToTopOfInsulation', @insulation_interior_distance_to_top, :float) unless @insulation_interior_distance_to_top.nil?
- XMLHelper.add_extension(layer, 'DistanceToBottomOfInsulation', @insulation_interior_distance_to_bottom, :float) unless @insulation_interior_distance_to_bottom.nil?
+ XMLHelper.add_extension(layer, 'DistanceToTopOfInsulation', @insulation_interior_distance_to_top, :float, @insulation_interior_distance_to_top_isdefaulted) unless @insulation_interior_distance_to_top.nil?
+ XMLHelper.add_extension(layer, 'DistanceToBottomOfInsulation', @insulation_interior_distance_to_bottom, :float, @insulation_interior_distance_to_bottom_isdefaulted) unless @insulation_interior_distance_to_bottom.nil?
end
end
@@ -2000,12 +2057,18 @@ def from_oga(foundation_wall)
@id = HPXML::get_id(foundation_wall)
@exterior_adjacent_to = XMLHelper.get_value(foundation_wall, 'ExteriorAdjacentTo', :string)
@interior_adjacent_to = XMLHelper.get_value(foundation_wall, 'InteriorAdjacentTo', :string)
+ @length = XMLHelper.get_value(foundation_wall, 'Length', :float)
@height = XMLHelper.get_value(foundation_wall, 'Height', :float)
@area = XMLHelper.get_value(foundation_wall, 'Area', :float)
@orientation = XMLHelper.get_value(foundation_wall, 'Orientation', :string)
@azimuth = XMLHelper.get_value(foundation_wall, 'Azimuth', :integer)
@thickness = XMLHelper.get_value(foundation_wall, 'Thickness', :float)
@depth_below_grade = XMLHelper.get_value(foundation_wall, 'DepthBelowGrade', :float)
+ interior_finish = XMLHelper.get_element(foundation_wall, 'InteriorFinish')
+ if not interior_finish.nil?
+ @interior_finish_type = XMLHelper.get_value(interior_finish, 'Type', :string)
+ @interior_finish_thickness = XMLHelper.get_value(interior_finish, 'Thickness', :float)
+ end
insulation = XMLHelper.get_element(foundation_wall, 'Insulation')
if not insulation.nil?
@insulation_id = HPXML::get_id(insulation)
@@ -2038,7 +2101,7 @@ def from_oga(hpxml)
class FrameFloor < BaseElement
ATTRS = [:id, :exterior_adjacent_to, :interior_adjacent_to, :area, :insulation_id,
:insulation_assembly_r_value, :insulation_cavity_r_value, :insulation_continuous_r_value,
- :other_space_above_or_below]
+ :other_space_above_or_below, :interior_finish_type, :interior_finish_thickness]
attr_accessor(*ATTRS)
def is_ceiling
@@ -2081,6 +2144,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.frame_floors.delete(self)
@hpxml_object.attics.each do |attic|
@@ -2106,6 +2173,11 @@ def to_oga(doc)
XMLHelper.add_element(frame_floor, 'ExteriorAdjacentTo', @exterior_adjacent_to, :string) unless @exterior_adjacent_to.nil?
XMLHelper.add_element(frame_floor, 'InteriorAdjacentTo', @interior_adjacent_to, :string) unless @interior_adjacent_to.nil?
XMLHelper.add_element(frame_floor, 'Area', @area, :float) unless @area.nil?
+ if (not @interior_finish_type.nil?) || (not @interior_finish_thickness.nil?)
+ interior_finish = XMLHelper.add_element(frame_floor, 'InteriorFinish')
+ XMLHelper.add_element(interior_finish, 'Type', @interior_finish_type, :string, @interior_finish_type_isdefaulted) unless @interior_finish_type.nil?
+ XMLHelper.add_element(interior_finish, 'Thickness', @interior_finish_thickness, :float, @interior_finish_thickness_isdefaulted) unless @interior_finish_thickness.nil?
+ end
insulation = XMLHelper.add_element(frame_floor, 'Insulation')
sys_id = XMLHelper.add_element(insulation, 'SystemIdentifier')
if not @insulation_id.nil?
@@ -2134,6 +2206,11 @@ def from_oga(frame_floor)
@exterior_adjacent_to = XMLHelper.get_value(frame_floor, 'ExteriorAdjacentTo', :string)
@interior_adjacent_to = XMLHelper.get_value(frame_floor, 'InteriorAdjacentTo', :string)
@area = XMLHelper.get_value(frame_floor, 'Area', :float)
+ interior_finish = XMLHelper.get_element(frame_floor, 'InteriorFinish')
+ if not interior_finish.nil?
+ @interior_finish_type = XMLHelper.get_value(interior_finish, 'Type', :string)
+ @interior_finish_thickness = XMLHelper.get_value(interior_finish, 'Thickness', :float)
+ end
insulation = XMLHelper.get_element(frame_floor, 'Insulation')
if not insulation.nil?
@insulation_id = HPXML::get_id(insulation)
@@ -2187,6 +2264,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.slabs.delete(self)
@hpxml_object.foundations.each do |foundation|
@@ -2313,6 +2394,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.windows.delete(self)
end
@@ -2331,8 +2416,8 @@ def to_oga(doc)
sys_id = XMLHelper.add_element(window, 'SystemIdentifier')
XMLHelper.add_attribute(sys_id, 'id', @id)
XMLHelper.add_element(window, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(window, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
- XMLHelper.add_element(window, 'Orientation', @orientation, :string) unless @orientation.nil?
+ XMLHelper.add_element(window, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
+ XMLHelper.add_element(window, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
if not @frame_type.nil?
frame_type_el = XMLHelper.add_element(window, 'FrameType')
frame_type = XMLHelper.add_element(frame_type_el, @frame_type)
@@ -2454,6 +2539,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.skylights.delete(self)
end
@@ -2472,8 +2561,8 @@ def to_oga(doc)
sys_id = XMLHelper.add_element(skylight, 'SystemIdentifier')
XMLHelper.add_attribute(sys_id, 'id', @id)
XMLHelper.add_element(skylight, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(skylight, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
- XMLHelper.add_element(skylight, 'Orientation', @orientation, :string) unless @orientation.nil?
+ XMLHelper.add_element(skylight, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
+ XMLHelper.add_element(skylight, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
if not @frame_type.nil?
frame_type_el = XMLHelper.add_element(skylight, 'FrameType')
frame_type = XMLHelper.add_element(frame_type_el, @frame_type)
@@ -2577,6 +2666,10 @@ def is_exterior_thermal_boundary
return (is_exterior && is_thermal_boundary)
end
+ def is_conditioned
+ return HPXML::is_conditioned(self)
+ end
+
def delete
@hpxml_object.doors.delete(self)
end
@@ -2599,8 +2692,8 @@ def to_oga(doc)
XMLHelper.add_attribute(attached_to_wall, 'idref', @wall_idref)
end
XMLHelper.add_element(door, 'Area', @area, :float) unless @area.nil?
- XMLHelper.add_element(door, 'Azimuth', @azimuth, :integer) unless @azimuth.nil?
- XMLHelper.add_element(door, 'Orientation', @orientation, :string) unless @orientation.nil?
+ XMLHelper.add_element(door, 'Azimuth', @azimuth, :integer, @azimuth_isdefaulted) unless @azimuth.nil?
+ XMLHelper.add_element(door, 'Orientation', @orientation, :string, @orientation_isdefaulted) unless @orientation.nil?
XMLHelper.add_element(door, 'RValue', @r_value, :float) unless @r_value.nil?
end
@@ -2640,8 +2733,7 @@ class HeatingSystem < BaseElement
:heating_efficiency_percent, :fraction_heat_load_served, :electric_auxiliary_energy,
:third_party_certification, :seed_id, :is_shared_system, :number_of_units_served,
:shared_loop_watts, :shared_loop_motor_efficiency, :fan_coil_watts, :fan_watts_per_cfm,
- :fan_power_not_tested, :airflow_defect_ratio, :airflow_not_tested,
- :fan_watts, :heating_airflow_cfm, :location]
+ :airflow_defect_ratio, :fan_watts, :heating_airflow_cfm, :location]
attr_accessor(*ATTRS)
def distribution_system
@@ -2709,14 +2801,16 @@ def to_oga(doc)
if [HVACTypeFurnace, HVACTypeWallFurnace, HVACTypeFloorFurnace, HVACTypeBoiler].include? @heating_system_type
efficiency_units = UnitsAFUE
efficiency_value = @heating_efficiency_afue
+ efficiency_value_isdefaulted = @heating_efficiency_afue_isdefaulted
elsif [HVACTypeElectricResistance, HVACTypeStove, HVACTypePortableHeater, HVACTypeFixedHeater, HVACTypeFireplace].include? @heating_system_type
efficiency_units = UnitsPercent
efficiency_value = @heating_efficiency_percent
+ efficiency_value_isdefaulted = @heating_efficiency_percent_isdefaulted
end
if not efficiency_value.nil?
annual_efficiency = XMLHelper.add_element(heating_system, 'AnnualHeatingEfficiency')
XMLHelper.add_element(annual_efficiency, 'Units', efficiency_units, :string)
- XMLHelper.add_element(annual_efficiency, 'Value', efficiency_value, :float)
+ XMLHelper.add_element(annual_efficiency, 'Value', efficiency_value, :float, efficiency_value_isdefaulted)
end
XMLHelper.add_element(heating_system, 'FractionHeatLoadServed', @fraction_heat_load_served, :float, @fraction_heat_load_served_isdefaulted) unless @fraction_heat_load_served.nil?
XMLHelper.add_element(heating_system, 'ElectricAuxiliaryEnergy', @electric_auxiliary_energy, :float, @electric_auxiliary_energy_isdefaulted) unless @electric_auxiliary_energy.nil?
@@ -2725,9 +2819,7 @@ def to_oga(doc)
XMLHelper.add_extension(heating_system, 'FanCoilWatts', @fan_coil_watts, :float) unless @fan_coil_watts.nil?
XMLHelper.add_extension(heating_system, 'FanPowerWattsPerCFM', @fan_watts_per_cfm, :float, @fan_watts_per_cfm_isdefaulted) unless @fan_watts_per_cfm.nil?
XMLHelper.add_extension(heating_system, 'FanPowerWatts', @fan_watts, :float, @fan_watts_isdefaulted) unless @fan_watts.nil?
- XMLHelper.add_extension(heating_system, 'FanPowerNotTested', @fan_power_not_tested, :boolean) unless @fan_power_not_tested.nil?
XMLHelper.add_extension(heating_system, 'AirflowDefectRatio', @airflow_defect_ratio, :float, @airflow_defect_ratio_isdefaulted) unless @airflow_defect_ratio.nil?
- XMLHelper.add_extension(heating_system, 'AirflowNotTested', @airflow_not_tested, :boolean) unless @airflow_not_tested.nil?
XMLHelper.add_extension(heating_system, 'HeatingAirflowCFM', @heating_airflow_cfm, :float, @heating_airflow_cfm_isdefaulted) unless @heating_airflow_cfm.nil?
XMLHelper.add_extension(heating_system, 'SeedId', @seed_id, :string) unless @seed_id.nil?
end
@@ -2757,9 +2849,7 @@ def from_oga(heating_system)
@fan_coil_watts = XMLHelper.get_value(heating_system, 'extension/FanCoilWatts', :float)
@fan_watts_per_cfm = XMLHelper.get_value(heating_system, 'extension/FanPowerWattsPerCFM', :float)
@fan_watts = XMLHelper.get_value(heating_system, 'extension/FanPowerWatts', :float)
- @fan_power_not_tested = XMLHelper.get_value(heating_system, 'extension/FanPowerNotTested', :boolean)
@airflow_defect_ratio = XMLHelper.get_value(heating_system, 'extension/AirflowDefectRatio', :float)
- @airflow_not_tested = XMLHelper.get_value(heating_system, 'extension/AirflowNotTested', :boolean)
@heating_airflow_cfm = XMLHelper.get_value(heating_system, 'extension/HeatingAirflowCFM', :float)
@seed_id = XMLHelper.get_value(heating_system, 'extension/SeedId', :string)
end
@@ -2786,11 +2876,10 @@ def total_fraction_cool_load_served
class CoolingSystem < BaseElement
ATTRS = [:id, :distribution_system_idref, :year_installed, :cooling_system_type,
:cooling_system_fuel, :cooling_capacity, :compressor_type, :fraction_cool_load_served,
- :cooling_efficiency_seer, :cooling_efficiency_eer, :cooling_efficiency_kw_per_ton,
+ :cooling_efficiency_seer, :cooling_efficiency_eer, :cooling_efficiency_ceer, :cooling_efficiency_kw_per_ton,
:cooling_shr, :third_party_certification, :seed_id, :is_shared_system, :number_of_units_served,
:shared_loop_watts, :shared_loop_motor_efficiency, :fan_coil_watts, :airflow_defect_ratio,
- :fan_watts_per_cfm, :fan_power_not_tested, :airflow_not_tested, :charge_defect_ratio,
- :charge_not_tested, :cooling_airflow_cfm, :location]
+ :fan_watts_per_cfm, :charge_defect_ratio, :cooling_airflow_cfm, :location]
attr_accessor(*ATTRS)
def distribution_system
@@ -2857,25 +2946,31 @@ def to_oga(doc)
if [HVACTypeCentralAirConditioner, HVACTypeMiniSplitAirConditioner].include? @cooling_system_type
efficiency_units = UnitsSEER
efficiency_value = @cooling_efficiency_seer
+ efficiency_value_isdefaulted = @cooling_efficiency_seer_isdefaulted
elsif [HVACTypeRoomAirConditioner].include? @cooling_system_type
- efficiency_units = UnitsEER
- efficiency_value = @cooling_efficiency_eer
+ if not @cooling_efficiency_eer.nil?
+ efficiency_units = UnitsEER
+ efficiency_value = @cooling_efficiency_eer
+ efficiency_value_isdefaulted = @cooling_efficiency_eer_isdefaulted
+ elsif not @cooling_efficiency_ceer.nil?
+ efficiency_units = UnitsCEER
+ efficiency_value = @cooling_efficiency_ceer
+ efficiency_value_isdefaulted = @cooling_efficiency_ceer_isdefaulted
+ end
elsif [HVACTypeChiller].include? @cooling_system_type
efficiency_units = UnitsKwPerTon
efficiency_value = @cooling_efficiency_kw_per_ton
+ efficiency_value_isdefaulted = @cooling_efficiency_kw_per_ton_isdefaulted
end
if not efficiency_value.nil?
annual_efficiency = XMLHelper.add_element(cooling_system, 'AnnualCoolingEfficiency')
XMLHelper.add_element(annual_efficiency, 'Units', efficiency_units, :string)
- XMLHelper.add_element(annual_efficiency, 'Value', efficiency_value, :float)
+ XMLHelper.add_element(annual_efficiency, 'Value', efficiency_value, :float, efficiency_value_isdefaulted)
end
XMLHelper.add_element(cooling_system, 'SensibleHeatFraction', @cooling_shr, :float, @cooling_shr_isdefaulted) unless @cooling_shr.nil?
XMLHelper.add_extension(cooling_system, 'AirflowDefectRatio', @airflow_defect_ratio, :float, @airflow_defect_ratio_isdefaulted) unless @airflow_defect_ratio.nil?
XMLHelper.add_extension(cooling_system, 'ChargeDefectRatio', @charge_defect_ratio, :float, @charge_defect_ratio_isdefaulted) unless @charge_defect_ratio.nil?
- XMLHelper.add_extension(cooling_system, 'ChargeNotTested', @charge_not_tested, :boolean) unless @charge_not_tested.nil?
XMLHelper.add_extension(cooling_system, 'FanPowerWattsPerCFM', @fan_watts_per_cfm, :float, @fan_watts_per_cfm_isdefaulted) unless @fan_watts_per_cfm.nil?
- XMLHelper.add_extension(cooling_system, 'FanPowerNotTested', @fan_power_not_tested, :boolean) unless @fan_power_not_tested.nil?
- XMLHelper.add_extension(cooling_system, 'AirflowNotTested', @airflow_not_tested, :boolean) unless @airflow_not_tested.nil?
XMLHelper.add_extension(cooling_system, 'CoolingAirflowCFM', @cooling_airflow_cfm, :float, @cooling_airflow_cfm_isdefaulted) unless @cooling_airflow_cfm.nil?
XMLHelper.add_extension(cooling_system, 'SharedLoopWatts', @shared_loop_watts, :float) unless @shared_loop_watts.nil?
XMLHelper.add_extension(cooling_system, 'SharedLoopMotorEfficiency', @shared_loop_motor_efficiency, :float) unless @shared_loop_motor_efficiency.nil?
@@ -2902,16 +2997,14 @@ def from_oga(cooling_system)
@cooling_efficiency_seer = XMLHelper.get_value(cooling_system, "AnnualCoolingEfficiency[Units='#{UnitsSEER}']/Value", :float)
elsif [HVACTypeRoomAirConditioner].include? @cooling_system_type
@cooling_efficiency_eer = XMLHelper.get_value(cooling_system, "AnnualCoolingEfficiency[Units='#{UnitsEER}']/Value", :float)
+ @cooling_efficiency_ceer = XMLHelper.get_value(cooling_system, "AnnualCoolingEfficiency[Units='#{UnitsCEER}']/Value", :float)
elsif [HVACTypeChiller].include? @cooling_system_type
@cooling_efficiency_kw_per_ton = XMLHelper.get_value(cooling_system, "AnnualCoolingEfficiency[Units='#{UnitsKwPerTon}']/Value", :float)
end
@cooling_shr = XMLHelper.get_value(cooling_system, 'SensibleHeatFraction', :float)
@airflow_defect_ratio = XMLHelper.get_value(cooling_system, 'extension/AirflowDefectRatio', :float)
@charge_defect_ratio = XMLHelper.get_value(cooling_system, 'extension/ChargeDefectRatio', :float)
- @charge_not_tested = XMLHelper.get_value(cooling_system, 'extension/ChargeNotTested', :boolean)
@fan_watts_per_cfm = XMLHelper.get_value(cooling_system, 'extension/FanPowerWattsPerCFM', :float)
- @fan_power_not_tested = XMLHelper.get_value(cooling_system, 'extension/FanPowerNotTested', :boolean)
- @airflow_not_tested = XMLHelper.get_value(cooling_system, 'extension/AirflowNotTested', :boolean)
@cooling_airflow_cfm = XMLHelper.get_value(cooling_system, 'extension/CoolingAirflowCFM', :float)
@shared_loop_watts = XMLHelper.get_value(cooling_system, 'extension/SharedLoopWatts', :float)
@shared_loop_motor_efficiency = XMLHelper.get_value(cooling_system, 'extension/SharedLoopMotorEfficiency', :float)
@@ -2950,10 +3043,9 @@ class HeatPump < BaseElement
:backup_heating_switchover_temp, :fraction_heat_load_served, :fraction_cool_load_served,
:cooling_efficiency_seer, :cooling_efficiency_eer, :heating_efficiency_hspf,
:heating_efficiency_cop, :third_party_certification, :seed_id, :pump_watts_per_ton,
- :fan_watts_per_cfm, :fan_power_not_tested, :is_shared_system, :number_of_units_served,
- :shared_loop_watts, :shared_loop_motor_efficiency, :airflow_defect_ratio, :airflow_not_tested,
- :charge_defect_ratio, :charge_not_tested, :heating_airflow_cfm, :cooling_airflow_cfm,
- :location]
+ :fan_watts_per_cfm, :is_shared_system, :number_of_units_served, :shared_loop_watts,
+ :shared_loop_motor_efficiency, :airflow_defect_ratio, :charge_defect_ratio,
+ :heating_airflow_cfm, :cooling_airflow_cfm, :location]
attr_accessor(*ATTRS)
def distribution_system
@@ -3027,30 +3119,31 @@ def to_oga(doc)
if [HVACTypeHeatPumpAirToAir, HVACTypeHeatPumpMiniSplit].include? @heat_pump_type
clg_efficiency_units = UnitsSEER
clg_efficiency_value = @cooling_efficiency_seer
+ clg_efficiency_value_isdefaulted = @cooling_efficiency_seer_isdefaulted
htg_efficiency_units = UnitsHSPF
htg_efficiency_value = @heating_efficiency_hspf
+ htg_efficiency_value_isdefaulted = @heating_efficiency_hspf_isdefaulted
elsif [HVACTypeHeatPumpGroundToAir, HVACTypeHeatPumpWaterLoopToAir].include? @heat_pump_type
clg_efficiency_units = UnitsEER
clg_efficiency_value = @cooling_efficiency_eer
+ clg_efficiency_value_isdefaulted = @cooling_efficiency_eer_isdefaulted
htg_efficiency_units = UnitsCOP
htg_efficiency_value = @heating_efficiency_cop
+ htg_efficiency_value_isdefaulted = @heating_efficiency_cop_isdefaulted
end
if not clg_efficiency_value.nil?
annual_efficiency = XMLHelper.add_element(heat_pump, 'AnnualCoolingEfficiency')
XMLHelper.add_element(annual_efficiency, 'Units', clg_efficiency_units, :string)
- XMLHelper.add_element(annual_efficiency, 'Value', clg_efficiency_value, :float)
+ XMLHelper.add_element(annual_efficiency, 'Value', clg_efficiency_value, :float, clg_efficiency_value_isdefaulted)
end
if not htg_efficiency_value.nil?
annual_efficiency = XMLHelper.add_element(heat_pump, 'AnnualHeatingEfficiency')
XMLHelper.add_element(annual_efficiency, 'Units', htg_efficiency_units, :string)
- XMLHelper.add_element(annual_efficiency, 'Value', htg_efficiency_value, :float)
+ XMLHelper.add_element(annual_efficiency, 'Value', htg_efficiency_value, :float, htg_efficiency_value_isdefaulted)
end
XMLHelper.add_extension(heat_pump, 'AirflowDefectRatio', @airflow_defect_ratio, :float, @airflow_defect_ratio_isdefaulted) unless @airflow_defect_ratio.nil?
XMLHelper.add_extension(heat_pump, 'ChargeDefectRatio', @charge_defect_ratio, :float, @charge_defect_ratio_isdefaulted) unless @charge_defect_ratio.nil?
- XMLHelper.add_extension(heat_pump, 'ChargeNotTested', @charge_not_tested, :boolean) unless @charge_not_tested.nil?
XMLHelper.add_extension(heat_pump, 'FanPowerWattsPerCFM', @fan_watts_per_cfm, :float, @fan_watts_per_cfm_isdefaulted) unless @fan_watts_per_cfm.nil?
- XMLHelper.add_extension(heat_pump, 'FanPowerNotTested', @fan_power_not_tested, :boolean) unless @fan_power_not_tested.nil?
- XMLHelper.add_extension(heat_pump, 'AirflowNotTested', @airflow_not_tested, :boolean) unless @airflow_not_tested.nil?
XMLHelper.add_extension(heat_pump, 'HeatingAirflowCFM', @heating_airflow_cfm, :float, @heating_airflow_cfm_isdefaulted) unless @heating_airflow_cfm.nil?
XMLHelper.add_extension(heat_pump, 'CoolingAirflowCFM', @cooling_airflow_cfm, :float, @cooling_airflow_cfm_isdefaulted) unless @cooling_airflow_cfm.nil?
XMLHelper.add_extension(heat_pump, 'PumpPowerWattsPerTon', @pump_watts_per_ton, :float, @pump_watts_per_ton_isdefaulted) unless @pump_watts_per_ton.nil?
@@ -3095,10 +3188,7 @@ def from_oga(heat_pump)
end
@airflow_defect_ratio = XMLHelper.get_value(heat_pump, 'extension/AirflowDefectRatio', :float)
@charge_defect_ratio = XMLHelper.get_value(heat_pump, 'extension/ChargeDefectRatio', :float)
- @charge_not_tested = XMLHelper.get_value(heat_pump, 'extension/ChargeNotTested', :boolean)
@fan_watts_per_cfm = XMLHelper.get_value(heat_pump, 'extension/FanPowerWattsPerCFM', :float)
- @fan_power_not_tested = XMLHelper.get_value(heat_pump, 'extension/FanPowerNotTested', :boolean)
- @airflow_not_tested = XMLHelper.get_value(heat_pump, 'extension/AirflowNotTested', :boolean)
@heating_airflow_cfm = XMLHelper.get_value(heat_pump, 'extension/HeatingAirflowCFM', :float)
@cooling_airflow_cfm = XMLHelper.get_value(heat_pump, 'extension/CoolingAirflowCFM', :float)
@pump_watts_per_ton = XMLHelper.get_value(heat_pump, 'extension/PumpPowerWattsPerTon', :float)
@@ -3173,13 +3263,13 @@ def from_oga(hpxml)
return if hvac_plant.nil?
HDL_ATTRS.each do |attr, element_name|
- send("#{attr.to_s}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/Heating/#{element_name}", :float))
+ send("#{attr}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/Heating/#{element_name}", :float))
end
CDL_SENS_ATTRS.each do |attr, element_name|
- send("#{attr.to_s}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/CoolingSensible/#{element_name}", :float))
+ send("#{attr}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/CoolingSensible/#{element_name}", :float))
end
CDL_LAT_ATTRS.each do |attr, element_name|
- send("#{attr.to_s}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/CoolingLatent/#{element_name}", :float))
+ send("#{attr}=", XMLHelper.get_value(hvac_plant, "extension/DesignLoads/CoolingLatent/#{element_name}", :float))
end
end
end
@@ -3812,7 +3902,7 @@ def from_oga(hpxml)
class WaterHeatingSystem < BaseElement
ATTRS = [:id, :year_installed, :fuel_type, :water_heater_type, :location, :performance_adjustment,
- :tank_volume, :fraction_dhw_load_served, :heating_capacity, :energy_factor,
+ :tank_volume, :fraction_dhw_load_served, :heating_capacity, :energy_factor, :usage_bin,
:uniform_energy_factor, :first_hour_rating, :recovery_efficiency, :uses_desuperheater, :jacket_r_value,
:related_hvac_idref, :third_party_certification, :standby_loss, :temperature, :is_shared_system,
:number_of_units_served]
@@ -3862,9 +3952,10 @@ def to_oga(doc)
XMLHelper.add_element(water_heating_system, 'TankVolume', @tank_volume, :float, @tank_volume_isdefaulted) unless @tank_volume.nil?
XMLHelper.add_element(water_heating_system, 'FractionDHWLoadServed', @fraction_dhw_load_served, :float) unless @fraction_dhw_load_served.nil?
XMLHelper.add_element(water_heating_system, 'HeatingCapacity', @heating_capacity, :float, @heating_capacity_isdefaulted) unless @heating_capacity.nil?
- XMLHelper.add_element(water_heating_system, 'EnergyFactor', @energy_factor, :float) unless @energy_factor.nil?
+ XMLHelper.add_element(water_heating_system, 'EnergyFactor', @energy_factor, :float, @energy_factor_isdefaulted) unless @energy_factor.nil?
XMLHelper.add_element(water_heating_system, 'UniformEnergyFactor', @uniform_energy_factor, :float) unless @uniform_energy_factor.nil?
XMLHelper.add_element(water_heating_system, 'FirstHourRating', @first_hour_rating, :float) unless @first_hour_rating.nil?
+ XMLHelper.add_element(water_heating_system, 'UsageBin', @usage_bin, :string, @usage_bin_isdefaulted) unless @usage_bin.nil?
XMLHelper.add_element(water_heating_system, 'RecoveryEfficiency', @recovery_efficiency, :float, @recovery_efficiency_isdefaulted) unless @recovery_efficiency.nil?
if not @jacket_r_value.nil?
water_heater_insulation = XMLHelper.add_element(water_heating_system, 'WaterHeaterInsulation')
@@ -3898,6 +3989,7 @@ def from_oga(water_heating_system)
@energy_factor = XMLHelper.get_value(water_heating_system, 'EnergyFactor', :float)
@uniform_energy_factor = XMLHelper.get_value(water_heating_system, 'UniformEnergyFactor', :float)
@first_hour_rating = XMLHelper.get_value(water_heating_system, 'FirstHourRating', :float)
+ @usage_bin = XMLHelper.get_value(water_heating_system, 'UsageBin', :string)
@recovery_efficiency = XMLHelper.get_value(water_heating_system, 'RecoveryEfficiency', :float)
@jacket_r_value = XMLHelper.get_value(water_heating_system, 'WaterHeaterInsulation/Jacket/JacketRValue', :float)
@standby_loss = XMLHelper.get_value(water_heating_system, 'StandbyLoss', :float)
@@ -4096,7 +4188,7 @@ def from_oga(hpxml)
end
class SolarThermalSystem < BaseElement
- ATTRS = [:id, :system_type, :collector_area, :collector_loop_type, :collector_azimuth,
+ ATTRS = [:id, :system_type, :collector_area, :collector_loop_type, :collector_orientation, :collector_azimuth,
:collector_type, :collector_tilt, :collector_frta, :collector_frul, :storage_volume,
:water_heating_system_idref, :solar_fraction]
attr_accessor(*ATTRS)
@@ -4133,7 +4225,8 @@ def to_oga(doc)
XMLHelper.add_element(solar_thermal_system, 'CollectorArea', @collector_area, :float) unless @collector_area.nil?
XMLHelper.add_element(solar_thermal_system, 'CollectorLoopType', @collector_loop_type, :string) unless @collector_loop_type.nil?
XMLHelper.add_element(solar_thermal_system, 'CollectorType', @collector_type, :string) unless @collector_type.nil?
- XMLHelper.add_element(solar_thermal_system, 'CollectorAzimuth', @collector_azimuth, :integer) unless @collector_azimuth.nil?
+ XMLHelper.add_element(solar_thermal_system, 'CollectorOrientation', @collector_orientation, :string, @collector_orientation_isdefaulted) unless @collector_orientation.nil?
+ XMLHelper.add_element(solar_thermal_system, 'CollectorAzimuth', @collector_azimuth, :integer, @collector_azimuth_isdefaulted) unless @collector_azimuth.nil?
XMLHelper.add_element(solar_thermal_system, 'CollectorTilt', @collector_tilt, :float) unless @collector_tilt.nil?
XMLHelper.add_element(solar_thermal_system, 'CollectorRatedOpticalEfficiency', @collector_frta, :float) unless @collector_frta.nil?
XMLHelper.add_element(solar_thermal_system, 'CollectorRatedThermalLosses', @collector_frul, :float) unless @collector_frul.nil?
@@ -4153,6 +4246,7 @@ def from_oga(solar_thermal_system)
@collector_area = XMLHelper.get_value(solar_thermal_system, 'CollectorArea', :float)
@collector_loop_type = XMLHelper.get_value(solar_thermal_system, 'CollectorLoopType', :string)
@collector_type = XMLHelper.get_value(solar_thermal_system, 'CollectorType', :string)
+ @collector_orientation = XMLHelper.get_value(solar_thermal_system, 'CollectorOrientation', :string)
@collector_azimuth = XMLHelper.get_value(solar_thermal_system, 'CollectorAzimuth', :integer)
@collector_tilt = XMLHelper.get_value(solar_thermal_system, 'CollectorTilt', :float)
@collector_frta = XMLHelper.get_value(solar_thermal_system, 'CollectorRatedOpticalEfficiency', :float)
@@ -4203,8 +4297,8 @@ def to_oga(doc)
XMLHelper.add_element(pv_system, 'Location', @location, :string, @location_isdefaulted) unless @location.nil?
XMLHelper.add_element(pv_system, 'ModuleType', @module_type, :string, @module_type_isdefaulted) unless @module_type.nil?
XMLHelper.add_element(pv_system, 'Tracking', @tracking, :string, @tracking_isdefaulted) unless @tracking.nil?
- XMLHelper.add_element(pv_system, 'ArrayOrientation', @array_orientation, :string) unless @array_orientation.nil?
- XMLHelper.add_element(pv_system, 'ArrayAzimuth', @array_azimuth, :integer) unless @array_azimuth.nil?
+ XMLHelper.add_element(pv_system, 'ArrayOrientation', @array_orientation, :string, @array_orientation_isdefaulted) unless @array_orientation.nil?
+ XMLHelper.add_element(pv_system, 'ArrayAzimuth', @array_azimuth, :integer, @array_azimuth_isdefaulted) unless @array_azimuth.nil?
XMLHelper.add_element(pv_system, 'ArrayTilt', @array_tilt, :float) unless @array_tilt.nil?
XMLHelper.add_element(pv_system, 'MaxPowerOutput', @max_power_output, :float) unless @max_power_output.nil?
XMLHelper.add_element(pv_system, 'NumberOfPanels', @number_of_panels, :integer) unless @number_of_panels.nil?
@@ -5469,6 +5563,8 @@ def check_for_errors()
# Check for errors across objects #
# ------------------------------- #
+ # FUTURE: Move these to EPvalidator.xml
+
# Check for globally unique SystemIdentifier IDs and empty IDs
sys_ids = {}
self.class::HPXML_ATTRS.each do |attribute|
@@ -5510,6 +5606,19 @@ def check_for_errors()
errors << "Expected FractionDHWLoadServed to sum to 1, but calculated sum is #{frac_dhw_load.round(2)}."
end
+ # Check sum of Ducts FractionDuctArea == 1
+ @hvac_distributions.each do |hvac_dist|
+ [HPXML::DuctTypeSupply, HPXML::DuctTypeReturn].each do |duct_type|
+ ducts_with_fractions = hvac_dist.ducts.select { |du| du.duct_type == duct_type && !du.duct_fraction_area.nil? }
+ next unless ducts_with_fractions.size > 0
+
+ ducts_frac_area = ducts_with_fractions.map { |du| Float(du.duct_fraction_area) }.sum()
+ if (ducts_frac_area < 0.99) || (ducts_frac_area > 1.01) # Use 0.99/1.01 in case of rounding
+ errors << "Expected FractionDuctArea for Ducts (of type #{duct_type}) to sum to 1, but calculated sum is #{ducts_frac_area.round(2)}."
+ end
+ end
+ end
+
# Check sum of lighting fractions in a location <= 1
ltg_fracs = {}
@lighting_groups.each do |lighting_group|
@@ -5629,6 +5738,10 @@ def self.conditioned_locations
HPXML::LocationOtherHousingUnit]
end
+ def self.is_conditioned(surface)
+ return conditioned_locations.include?(surface.interior_adjacent_to)
+ end
+
def self.is_adiabatic(surface)
if surface.exterior_adjacent_to == surface.interior_adjacent_to
# E.g., wall between unit crawlspace and neighboring unit crawlspace
diff --git a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb
index 6fd105c28e..c0a51b883c 100644
--- a/HPXMLtoOpenStudio/resources/hpxml_defaults.rb
+++ b/HPXMLtoOpenStudio/resources/hpxml_defaults.rb
@@ -15,6 +15,7 @@ def self.apply(hpxml, eri_version, weather, epw_file: nil, convert_shared_system
apply_header(hpxml, epw_file)
apply_site(hpxml)
+ apply_neighbor_buildings(hpxml)
apply_building_occupancy(hpxml, nbeds)
apply_building_construction(hpxml, cfa, nbeds)
apply_infiltration(hpxml)
@@ -24,9 +25,11 @@ def self.apply(hpxml, eri_version, weather, epw_file: nil, convert_shared_system
apply_rim_joists(hpxml)
apply_walls(hpxml)
apply_foundation_walls(hpxml)
+ apply_frame_floors(hpxml)
apply_slabs(hpxml)
apply_windows(hpxml)
apply_skylights(hpxml)
+ apply_doors(hpxml)
apply_hvac(hpxml, weather, convert_shared_systems)
apply_hvac_control(hpxml)
apply_hvac_distribution(hpxml, ncfl, ncfl_ag)
@@ -48,6 +51,42 @@ def self.apply(hpxml, eri_version, weather, epw_file: nil, convert_shared_system
apply_hvac_sizing(hpxml, weather, cfa, nbeds)
end
+ def self.get_default_azimuths(hpxml)
+ def self.sanitize_azimuth(azimuth)
+ # Ensure 0 <= orientation < 360
+ while azimuth < 0
+ azimuth += 360
+ end
+ while azimuth >= 360
+ azimuth -= 360
+ end
+ return azimuth
+ end
+
+ # Returns a list of four azimuths (facing each direction). Determined based
+ # on the primary azimuth, as defined by the azimuth with the largest surface
+ # area, plus azimuths that are offset by 90/180/270 degrees. Used for
+ # surfaces that may not have an azimuth defined (e.g., walls).
+ azimuth_areas = {}
+ (hpxml.roofs + hpxml.rim_joists + hpxml.walls + hpxml.foundation_walls +
+ hpxml.windows + hpxml.skylights + hpxml.doors).each do |surface|
+ az = surface.azimuth
+ next if az.nil?
+
+ azimuth_areas[az] = 0 if azimuth_areas[az].nil?
+ azimuth_areas[az] += surface.area
+ end
+ if azimuth_areas.empty?
+ primary_azimuth = 0
+ else
+ primary_azimuth = azimuth_areas.max_by { |k, v| v }[0]
+ end
+ return [primary_azimuth,
+ sanitize_azimuth(primary_azimuth + 90),
+ sanitize_azimuth(primary_azimuth + 180),
+ sanitize_azimuth(primary_azimuth + 270)].sort
+ end
+
private
def self.apply_header(hpxml, epw_file)
@@ -142,6 +181,19 @@ def self.apply_site(hpxml)
hpxml.site.additional_properties.aim2_shelter_coeff = Airflow.get_aim2_shelter_coefficient(hpxml.site.shielding_of_home)
end
+ def self.apply_neighbor_buildings(hpxml)
+ hpxml.neighbor_buildings.each do |neighbor_building|
+ if neighbor_building.azimuth.nil?
+ neighbor_building.azimuth = get_azimuth_from_orientation(neighbor_building.orientation)
+ neighbor_building.azimuth_isdefaulted = true
+ end
+ if neighbor_building.orientation.nil?
+ neighbor_building.orientation = get_orientation_from_azimuth(neighbor_building.azimuth)
+ neighbor_building.orientation_isdefaulted = true
+ end
+ end
+ end
+
def self.apply_building_occupancy(hpxml, nbeds)
if hpxml.building_occupancy.number_of_residents.nil?
hpxml.building_occupancy.number_of_residents = Geometry.get_occupancy_default_num(nbeds)
@@ -231,6 +283,7 @@ def self.apply_attics(hpxml)
default_ach = nil
hpxml.attics.each do |attic|
next unless attic.attic_type == HPXML::AtticTypeVented
+
# check existing sla and ach
default_sla = attic.vented_attic_sla unless attic.vented_attic_sla.nil?
default_ach = attic.vented_attic_ach unless attic.vented_attic_ach.nil?
@@ -245,6 +298,7 @@ def self.apply_attics(hpxml)
end
vented_attics.each do |vented_attic|
next unless (vented_attic.vented_attic_sla.nil? && vented_attic.vented_attic_ach.nil?)
+
if not default_ach.nil? # ACH specified
vented_attic.vented_attic_ach = default_ach
else # Use SLA
@@ -261,6 +315,7 @@ def self.apply_foundations(hpxml)
default_sla = Airflow.get_default_vented_crawl_sla()
hpxml.foundations.each do |foundation|
next unless foundation.foundation_type == HPXML::FoundationTypeCrawlspaceVented
+
# check existing sla
default_sla = foundation.vented_crawlspace_sla unless foundation.vented_crawlspace_sla.nil?
@@ -274,6 +329,7 @@ def self.apply_foundations(hpxml)
end
vented_crawls.each do |vented_crawl|
next unless vented_crawl.vented_crawlspace_sla.nil?
+
vented_crawl.vented_crawlspace_sla = default_sla
vented_crawl.vented_crawlspace_sla_isdefaulted = true
end
@@ -281,6 +337,14 @@ def self.apply_foundations(hpxml)
def self.apply_roofs(hpxml)
hpxml.roofs.each do |roof|
+ if roof.azimuth.nil?
+ roof.azimuth = get_azimuth_from_orientation(roof.orientation)
+ roof.azimuth_isdefaulted = true
+ end
+ if roof.orientation.nil?
+ roof.orientation = get_orientation_from_azimuth(roof.azimuth)
+ roof.orientation_isdefaulted = true
+ end
if roof.roof_type.nil?
roof.roof_type = HPXML::RoofTypeAsphaltShingles
roof.roof_type_isdefaulted = true
@@ -293,6 +357,14 @@ def self.apply_roofs(hpxml)
roof.radiant_barrier = false
roof.radiant_barrier_isdefaulted = true
end
+ if roof.radiant_barrier && roof.radiant_barrier_grade.nil?
+ roof.radiant_barrier_grade = 1
+ roof.radiant_barrier_grade_isdefaulted = true
+ end
+ if roof.roof_color.nil? && roof.solar_absorptance.nil?
+ roof.roof_color = HPXML::ColorMedium
+ roof.roof_color_isdefaulted = true
+ end
if roof.roof_color.nil?
roof.roof_color = Constructions.get_default_roof_color(roof.roof_type, roof.solar_absorptance)
roof.roof_color_isdefaulted = true
@@ -300,11 +372,34 @@ def self.apply_roofs(hpxml)
roof.solar_absorptance = Constructions.get_default_roof_solar_absorptance(roof.roof_type, roof.roof_color)
roof.solar_absorptance_isdefaulted = true
end
+ if roof.interior_finish_type.nil?
+ if [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? roof.interior_adjacent_to
+ roof.interior_finish_type = HPXML::InteriorFinishGypsumBoard
+ else
+ roof.interior_finish_type = HPXML::InteriorFinishNone
+ end
+ roof.interior_finish_type_isdefaulted = true
+ end
+ next unless roof.interior_finish_thickness.nil?
+
+ if roof.interior_finish_type != HPXML::InteriorFinishNone
+ roof.interior_finish_thickness = 0.5
+ roof.interior_finish_thickness_isdefaulted = true
+ end
end
end
def self.apply_rim_joists(hpxml)
hpxml.rim_joists.each do |rim_joist|
+ if rim_joist.azimuth.nil?
+ rim_joist.azimuth = get_azimuth_from_orientation(rim_joist.orientation)
+ rim_joist.azimuth_isdefaulted = true
+ end
+ if rim_joist.orientation.nil?
+ rim_joist.orientation = get_orientation_from_azimuth(rim_joist.azimuth)
+ rim_joist.orientation_isdefaulted = true
+ end
+
next unless rim_joist.is_exterior
if rim_joist.emittance.nil?
@@ -315,6 +410,10 @@ def self.apply_rim_joists(hpxml)
rim_joist.siding = HPXML::SidingTypeWood
rim_joist.siding_isdefaulted = true
end
+ if rim_joist.color.nil? && rim_joist.solar_absorptance.nil?
+ rim_joist.color = HPXML::ColorMedium
+ rim_joist.color_isdefaulted = true
+ end
if rim_joist.color.nil?
rim_joist.color = Constructions.get_default_wall_color(rim_joist.solar_absorptance)
rim_joist.color_isdefaulted = true
@@ -327,32 +426,122 @@ def self.apply_rim_joists(hpxml)
def self.apply_walls(hpxml)
hpxml.walls.each do |wall|
- next unless wall.is_exterior
+ if wall.azimuth.nil?
+ wall.azimuth = get_azimuth_from_orientation(wall.orientation)
+ wall.azimuth_isdefaulted = true
+ end
+ if wall.orientation.nil?
+ wall.orientation = get_orientation_from_azimuth(wall.azimuth)
+ wall.orientation_isdefaulted = true
+ end
- if wall.emittance.nil?
- wall.emittance = 0.90
- wall.emittance_isdefaulted = true
+ if wall.is_exterior
+ if wall.emittance.nil?
+ wall.emittance = 0.90
+ wall.emittance_isdefaulted = true
+ end
+ if wall.siding.nil?
+ wall.siding = HPXML::SidingTypeWood
+ wall.siding_isdefaulted = true
+ end
+ if wall.color.nil? && wall.solar_absorptance.nil?
+ wall.color = HPXML::ColorMedium
+ wall.color_isdefaulted = true
+ end
+ if wall.color.nil?
+ wall.color = Constructions.get_default_wall_color(wall.solar_absorptance)
+ wall.color_isdefaulted = true
+ elsif wall.solar_absorptance.nil?
+ wall.solar_absorptance = Constructions.get_default_wall_solar_absorptance(wall.color)
+ wall.solar_absorptance_isdefaulted = true
+ end
end
- if wall.siding.nil?
- wall.siding = HPXML::SidingTypeWood
- wall.siding_isdefaulted = true
+ if wall.interior_finish_type.nil?
+ if [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? wall.interior_adjacent_to
+ wall.interior_finish_type = HPXML::InteriorFinishGypsumBoard
+ else
+ wall.interior_finish_type = HPXML::InteriorFinishNone
+ end
+ wall.interior_finish_type_isdefaulted = true
end
- if wall.color.nil?
- wall.color = Constructions.get_default_wall_color(wall.solar_absorptance)
- wall.color_isdefaulted = true
- elsif wall.solar_absorptance.nil?
- wall.solar_absorptance = Constructions.get_default_wall_solar_absorptance(wall.color)
- wall.solar_absorptance_isdefaulted = true
+ next unless wall.interior_finish_thickness.nil?
+
+ if wall.interior_finish_type != HPXML::InteriorFinishNone
+ wall.interior_finish_thickness = 0.5
+ wall.interior_finish_thickness_isdefaulted = true
end
end
end
def self.apply_foundation_walls(hpxml)
hpxml.foundation_walls.each do |foundation_wall|
+ if foundation_wall.azimuth.nil?
+ foundation_wall.azimuth = get_azimuth_from_orientation(foundation_wall.orientation)
+ foundation_wall.azimuth_isdefaulted = true
+ end
+ if foundation_wall.orientation.nil?
+ foundation_wall.orientation = get_orientation_from_azimuth(foundation_wall.azimuth)
+ foundation_wall.orientation_isdefaulted = true
+ end
if foundation_wall.thickness.nil?
foundation_wall.thickness = 8.0
foundation_wall.thickness_isdefaulted = true
end
+ if foundation_wall.area.nil?
+ foundation_wall.area = foundation_wall.length * foundation_wall.height
+ foundation_wall.area_isdefaulted = true
+ end
+ if foundation_wall.interior_finish_type.nil?
+ if [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? foundation_wall.interior_adjacent_to
+ foundation_wall.interior_finish_type = HPXML::InteriorFinishGypsumBoard
+ else
+ foundation_wall.interior_finish_type = HPXML::InteriorFinishNone
+ end
+ foundation_wall.interior_finish_type_isdefaulted = true
+ end
+ if foundation_wall.insulation_interior_distance_to_top.nil?
+ foundation_wall.insulation_interior_distance_to_top = 0.0
+ foundation_wall.insulation_interior_distance_to_top_isdefaulted = true
+ end
+ if foundation_wall.insulation_interior_distance_to_bottom.nil?
+ foundation_wall.insulation_interior_distance_to_bottom = foundation_wall.height
+ foundation_wall.insulation_interior_distance_to_bottom_isdefaulted = true
+ end
+ if foundation_wall.insulation_exterior_distance_to_top.nil?
+ foundation_wall.insulation_exterior_distance_to_top = 0.0
+ foundation_wall.insulation_exterior_distance_to_top_isdefaulted = true
+ end
+ if foundation_wall.insulation_exterior_distance_to_bottom.nil?
+ foundation_wall.insulation_exterior_distance_to_bottom = foundation_wall.height
+ foundation_wall.insulation_exterior_distance_to_bottom_isdefaulted = true
+ end
+ next unless foundation_wall.interior_finish_thickness.nil?
+
+ if foundation_wall.interior_finish_type != HPXML::InteriorFinishNone
+ foundation_wall.interior_finish_thickness = 0.5
+ foundation_wall.interior_finish_thickness_isdefaulted = true
+ end
+ end
+ end
+
+ def self.apply_frame_floors(hpxml)
+ hpxml.frame_floors.each do |frame_floor|
+ if frame_floor.interior_finish_type.nil?
+ if frame_floor.is_floor
+ frame_floor.interior_finish_type = HPXML::InteriorFinishNone
+ elsif [HPXML::LocationLivingSpace, HPXML::LocationBasementConditioned].include? frame_floor.interior_adjacent_to
+ frame_floor.interior_finish_type = HPXML::InteriorFinishGypsumBoard
+ else
+ frame_floor.interior_finish_type = HPXML::InteriorFinishNone
+ end
+ frame_floor.interior_finish_type_isdefaulted = true
+ end
+ next unless frame_floor.interior_finish_thickness.nil?
+
+ if frame_floor.interior_finish_type != HPXML::InteriorFinishNone
+ frame_floor.interior_finish_thickness = 0.5
+ frame_floor.interior_finish_thickness_isdefaulted = true
+ end
end
end
@@ -379,6 +568,14 @@ def self.apply_slabs(hpxml)
def self.apply_windows(hpxml)
default_shade_summer, default_shade_winter = Constructions.get_default_interior_shading_factors()
hpxml.windows.each do |window|
+ if window.azimuth.nil?
+ window.azimuth = get_azimuth_from_orientation(window.orientation)
+ window.azimuth_isdefaulted = true
+ end
+ if window.orientation.nil?
+ window.orientation = get_orientation_from_azimuth(window.azimuth)
+ window.orientation_isdefaulted = true
+ end
if window.interior_shading_factor_summer.nil?
window.interior_shading_factor_summer = default_shade_summer
window.interior_shading_factor_summer_isdefaulted = true
@@ -404,6 +601,14 @@ def self.apply_windows(hpxml)
def self.apply_skylights(hpxml)
hpxml.skylights.each do |skylight|
+ if skylight.azimuth.nil?
+ skylight.azimuth = get_azimuth_from_orientation(skylight.orientation)
+ skylight.azimuth_isdefaulted = true
+ end
+ if skylight.orientation.nil?
+ skylight.orientation = get_orientation_from_azimuth(skylight.azimuth)
+ skylight.orientation_isdefaulted = true
+ end
if skylight.interior_shading_factor_summer.nil?
skylight.interior_shading_factor_summer = 1.0
skylight.interior_shading_factor_summer_isdefaulted = true
@@ -423,11 +628,105 @@ def self.apply_skylights(hpxml)
end
end
+ def self.apply_doors(hpxml)
+ hpxml.doors.each do |door|
+ if door.azimuth.nil?
+ door.azimuth = get_azimuth_from_orientation(door.orientation)
+ door.azimuth_isdefaulted = true
+ end
+ if door.orientation.nil?
+ door.orientation = get_orientation_from_azimuth(door.azimuth)
+ door.orientation_isdefaulted = true
+ end
+
+ next unless door.azimuth.nil?
+
+ if (not door.wall.nil?) && (not door.wall.azimuth.nil?)
+ door.azimuth = door.wall.azimuth
+ else
+ primary_azimuth = get_default_azimuths(hpxml)[0]
+ door.azimuth = primary_azimuth
+ door.azimuth_isdefaulted = true
+ end
+ end
+ end
+
def self.apply_hvac(hpxml, weather, convert_shared_systems)
if convert_shared_systems
HVAC.apply_shared_systems(hpxml)
end
+ # HVAC efficiencies (based on HEScore assumption)
+ hpxml.heating_systems.each do |heating_system|
+ year_installed = heating_system.year_installed
+ heating_system_type = heating_system.heating_system_type
+ heating_system_fuel = heating_system.heating_system_fuel
+
+ if [HPXML::HVACTypeBoiler, HPXML::HVACTypeFurnace, HPXML::HVACTypeWallFurnace, HPXML::HVACTypeFloorFurnace].include? heating_system_type
+ next unless heating_system.heating_efficiency_afue.nil?
+
+ if heating_system_fuel == HPXML::FuelTypeElectricity
+ heating_system.heating_efficiency_afue = 0.98
+ else
+ heating_system.heating_efficiency_afue = HVAC.get_default_hvac_efficiency_by_year_installed(year_installed, heating_system_type, heating_system_fuel, HPXML::UnitsAFUE)
+ end
+ heating_system.heating_efficiency_afue_isdefaulted = true
+ elsif [HPXML::HVACTypeElectricResistance].include? heating_system_type
+ next unless heating_system.heating_efficiency_percent.nil?
+
+ heating_system.heating_efficiency_percent = 1.0
+ heating_system.heating_efficiency_percent_isdefaulted = true
+ elsif [HPXML::HVACTypeStove, HPXML::HVACTypeFireplace, HPXML::HVACTypePortableHeater, HPXML::HVACTypeFixedHeater].include? heating_system_type
+ next unless heating_system.heating_efficiency_percent.nil?
+
+ if heating_system_fuel == HPXML::FuelTypeElectricity
+ heating_system.heating_efficiency_percent = 1.0
+ elsif heating_system_fuel == HPXML::FuelTypeWoodCord
+ heating_system.heating_efficiency_percent = 0.60 # HEScore assumption
+ elsif heating_system_fuel == HPXML::FuelTypeWoodPellets
+ heating_system.heating_efficiency_percent = 0.78 # HEScore assumption
+ else
+ heating_system.heating_efficiency_percent = 0.81 # https://www.lopistoves.com/products/ and https://www.kozyheat.com/products/
+ end
+ heating_system.heating_efficiency_percent_isdefaulted = true
+ end
+ end
+
+ hpxml.cooling_systems.each do |cooling_system|
+ year_installed = cooling_system.year_installed
+ cooling_system_type = cooling_system.cooling_system_type
+ cooling_system_fuel = HPXML::FuelTypeElectricity
+
+ if cooling_system_type == HPXML::HVACTypeCentralAirConditioner
+ next unless cooling_system.cooling_efficiency_seer.nil?
+
+ cooling_system.cooling_efficiency_seer = HVAC.get_default_hvac_efficiency_by_year_installed(year_installed, cooling_system_type, cooling_system_fuel, HPXML::UnitsSEER)
+ cooling_system.cooling_efficiency_seer_isdefaulted = true
+ elsif cooling_system_type == HPXML::HVACTypeRoomAirConditioner
+ next unless cooling_system.cooling_efficiency_eer.nil? && cooling_system.cooling_efficiency_ceer.nil?
+
+ cooling_system.cooling_efficiency_eer = HVAC.get_default_hvac_efficiency_by_year_installed(year_installed, cooling_system_type, cooling_system_fuel, HPXML::UnitsEER)
+ cooling_system.cooling_efficiency_eer_isdefaulted = true
+ end
+ end
+
+ hpxml.heat_pumps.each do |heat_pump|
+ year_installed = heat_pump.year_installed
+ heat_pump_type = heat_pump.heat_pump_type
+ heat_pump_fuel = HPXML::FuelTypeElectricity
+
+ next unless [HPXML::HVACTypeHeatPumpAirToAir].include? heat_pump_type
+
+ if heat_pump.cooling_efficiency_seer.nil?
+ heat_pump.cooling_efficiency_seer = HVAC.get_default_hvac_efficiency_by_year_installed(year_installed, heat_pump_type, heat_pump_fuel, HPXML::UnitsSEER)
+ heat_pump.cooling_efficiency_seer_isdefaulted = true
+ end
+ if heat_pump.heating_efficiency_hspf.nil?
+ heat_pump.heating_efficiency_hspf = HVAC.get_default_hvac_efficiency_by_year_installed(year_installed, heat_pump_type, heat_pump_fuel, HPXML::UnitsHSPF)
+ heat_pump.heating_efficiency_hspf_isdefaulted = true
+ end
+ end
+
# Default AC/HP compressor type
hpxml.cooling_systems.each do |cooling_system|
next unless cooling_system.compressor_type.nil?
@@ -445,6 +744,7 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
# Default boiler EAE
hpxml.heating_systems.each do |heating_system|
next unless heating_system.electric_auxiliary_energy.nil?
+
heating_system.electric_auxiliary_energy_isdefaulted = true
heating_system.electric_auxiliary_energy = HVAC.get_default_boiler_eae(heating_system)
heating_system.shared_loop_watts = nil
@@ -511,7 +811,6 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
cooling_system.charge_defect_ratio = 0.0
cooling_system.charge_defect_ratio_isdefaulted = true
- cooling_system.charge_not_tested = nil
end
hpxml.heat_pumps.each do |heat_pump|
next unless [HPXML::HVACTypeHeatPumpAirToAir,
@@ -521,7 +820,6 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
heat_pump.charge_defect_ratio = 0.0
heat_pump.charge_defect_ratio_isdefaulted = true
- heat_pump.charge_not_tested = nil
end
# Airflow defect ratio
@@ -531,38 +829,30 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
heating_system.airflow_defect_ratio = 0.0
heating_system.airflow_defect_ratio_isdefaulted = true
- heating_system.airflow_not_tested = nil
end
hpxml.cooling_systems.each do |cooling_system|
next unless [HPXML::HVACTypeCentralAirConditioner,
HPXML::HVACTypeMiniSplitAirConditioner].include? cooling_system.cooling_system_type
- if cooling_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner && cooling_system.distribution_system_idref.nil?
- next # Ducted mini-splits only
- end
next unless cooling_system.airflow_defect_ratio.nil?
cooling_system.airflow_defect_ratio = 0.0
cooling_system.airflow_defect_ratio_isdefaulted = true
- cooling_system.airflow_not_tested = nil
end
hpxml.heat_pumps.each do |heat_pump|
next unless [HPXML::HVACTypeHeatPumpAirToAir,
HPXML::HVACTypeHeatPumpGroundToAir,
HPXML::HVACTypeHeatPumpMiniSplit].include? heat_pump.heat_pump_type
- if heat_pump.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit && heat_pump.distribution_system_idref.nil?
- next # Ducted mini-splits only
- end
next unless heat_pump.airflow_defect_ratio.nil?
heat_pump.airflow_defect_ratio = 0.0
heat_pump.airflow_defect_ratio_isdefaulted = true
- heat_pump.airflow_not_tested = nil
end
# Fan power
psc_watts_per_cfm = 0.5 # W/cfm, PSC fan
ecm_watts_per_cfm = 0.375 # W/cfm, ECM fan
- mini_split_ducted_watts_per_cfm = 0.18 # W/cfm, ducted mini split
+ mini_split_ductless_watts_per_cfm = 0.07 # W/cfm
+ mini_split_ducted_watts_per_cfm = 0.18 # W/cfm
hpxml.heating_systems.each do |heating_system|
if [HPXML::HVACTypeFurnace].include? heating_system.heating_system_type
if heating_system.fan_watts_per_cfm.nil?
@@ -574,7 +864,6 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
heating_system.fan_watts_per_cfm = psc_watts_per_cfm
end
heating_system.fan_watts_per_cfm_isdefaulted = true
- heating_system.fan_power_not_tested = nil
end
elsif [HPXML::HVACTypeStove].include? heating_system.heating_system_type
if heating_system.fan_watts.nil?
@@ -598,7 +887,6 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
if (not cooling_system.attached_heating_system.nil?) && (not cooling_system.attached_heating_system.fan_watts_per_cfm.nil?)
cooling_system.fan_watts_per_cfm = cooling_system.attached_heating_system.fan_watts_per_cfm
cooling_system.fan_watts_per_cfm_isdefaulted = true
- cooling_system.fan_power_not_tested = nil
elsif [HPXML::HVACTypeCentralAirConditioner].include? cooling_system.cooling_system_type
if cooling_system.cooling_efficiency_seer > 13.5 # HEScore assumption
cooling_system.fan_watts_per_cfm = ecm_watts_per_cfm
@@ -606,13 +894,13 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
cooling_system.fan_watts_per_cfm = psc_watts_per_cfm
end
cooling_system.fan_watts_per_cfm_isdefaulted = true
- cooling_system.fan_power_not_tested = nil
elsif [HPXML::HVACTypeMiniSplitAirConditioner].include? cooling_system.cooling_system_type
if not cooling_system.distribution_system.nil?
cooling_system.fan_watts_per_cfm = mini_split_ducted_watts_per_cfm
+ else
+ cooling_system.fan_watts_per_cfm = mini_split_ductless_watts_per_cfm
end
cooling_system.fan_watts_per_cfm_isdefaulted = true
- cooling_system.fan_power_not_tested = nil
elsif [HPXML::HVACTypeEvaporativeCooler].include? cooling_system.cooling_system_type
# Depends on airflow rate, so defaulted in hvac_sizing.rb
end
@@ -627,7 +915,6 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
heat_pump.fan_watts_per_cfm = psc_watts_per_cfm
end
heat_pump.fan_watts_per_cfm_isdefaulted = true
- heat_pump.fan_power_not_tested = nil
elsif [HPXML::HVACTypeHeatPumpGroundToAir].include? heat_pump.heat_pump_type
if heat_pump.heating_efficiency_cop > 8.75 / 3.2 # HEScore assumption
heat_pump.fan_watts_per_cfm = ecm_watts_per_cfm
@@ -635,13 +922,13 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
heat_pump.fan_watts_per_cfm = psc_watts_per_cfm
end
heat_pump.fan_watts_per_cfm_isdefaulted = true
- heat_pump.fan_power_not_tested = nil
elsif [HPXML::HVACTypeHeatPumpMiniSplit].include? heat_pump.heat_pump_type
if not heat_pump.distribution_system.nil?
heat_pump.fan_watts_per_cfm = mini_split_ducted_watts_per_cfm
+ else
+ heat_pump.fan_watts_per_cfm = mini_split_ductless_watts_per_cfm
end
heat_pump.fan_watts_per_cfm_isdefaulted = true
- heat_pump.fan_power_not_tested = nil
end
end
@@ -693,6 +980,7 @@ def self.apply_hvac(hpxml, weather, convert_shared_systems)
HPXML::HVACTypeWallFurnace,
HPXML::HVACTypeFloorFurnace,
HPXML::HVACTypeFireplace].include? heating_system.heating_system_type
+
HVAC.set_heat_rated_cfm_per_ton(heating_system)
end
hpxml.heat_pumps.each do |heat_pump|
@@ -772,6 +1060,7 @@ def self.apply_hvac_control(hpxml)
end
next unless hvac_control.seasons_cooling_begin_month.nil? || hvac_control.seasons_cooling_begin_day.nil? || hvac_control.seasons_cooling_end_month.nil? || hvac_control.seasons_cooling_end_day.nil?
+
hvac_control.seasons_cooling_begin_month = 1
hvac_control.seasons_cooling_begin_day = 1
hvac_control.seasons_cooling_end_month = 12
@@ -784,15 +1073,6 @@ def self.apply_hvac_control(hpxml)
end
def self.apply_hvac_distribution(hpxml, ncfl, ncfl_ag)
- # Check either all ducts have location and surface area or all ducts have no location and surface area
- n_ducts = 0
- n_ducts_to_be_defaulted = 0
- hpxml.hvac_distributions.each do |hvac_distribution|
- n_ducts += hvac_distribution.ducts.size
- n_ducts_to_be_defaulted += hvac_distribution.ducts.select { |duct| duct.duct_surface_area.nil? && duct.duct_location.nil? }.size
- end
- fail if n_ducts_to_be_defaulted > 0 && (n_ducts != n_ducts_to_be_defaulted) # EPvalidator.xml should prevent this
-
hpxml.hvac_distributions.each do |hvac_distribution|
next unless [HPXML::HVACDistributionTypeAir].include? hvac_distribution.distribution_system_type
@@ -802,44 +1082,63 @@ def self.apply_hvac_distribution(hpxml, ncfl, ncfl_ag)
hvac_distribution.number_of_return_registers_isdefaulted = true
end
+ next if hvac_distribution.ducts.empty?
+
# Default ducts
+
cfa_served = hvac_distribution.conditioned_floor_area_served
n_returns = hvac_distribution.number_of_return_registers
-
supply_ducts = hvac_distribution.ducts.select { |duct| duct.duct_type == HPXML::DuctTypeSupply }
return_ducts = hvac_distribution.ducts.select { |duct| duct.duct_type == HPXML::DuctTypeReturn }
- [supply_ducts, return_ducts].each do |ducts|
- ducts.each do |duct|
- next unless duct.duct_surface_area.nil?
-
- primary_duct_area, secondary_duct_area = HVAC.get_default_duct_surface_area(duct.duct_type, ncfl_ag, cfa_served, n_returns).map { |area| area / ducts.size }
- primary_duct_location, secondary_duct_location = HVAC.get_default_duct_locations(hpxml)
- if primary_duct_location.nil? # If a home doesn't have any non-living spaces (outside living space), place all ducts in living space.
- duct.duct_surface_area = primary_duct_area + secondary_duct_area
- duct.duct_location = secondary_duct_location
- else
- duct.duct_surface_area = primary_duct_area
- duct.duct_location = primary_duct_location
- if secondary_duct_area > 0
- hvac_distribution.ducts.add(duct_type: duct.duct_type,
- duct_insulation_r_value: duct.duct_insulation_r_value,
- duct_location: secondary_duct_location,
- duct_location_isdefaulted: true,
- duct_surface_area: secondary_duct_area,
- duct_surface_area_isdefaulted: true)
+
+ if hvac_distribution.ducts[0].duct_location.nil?
+ # Default both duct location(s) and duct surface area(s)
+ [supply_ducts, return_ducts].each do |ducts|
+ ducts.each do |duct|
+ primary_duct_area, secondary_duct_area = HVAC.get_default_duct_surface_area(duct.duct_type, ncfl_ag, cfa_served, n_returns).map { |area| area / ducts.size }
+ primary_duct_location, secondary_duct_location = HVAC.get_default_duct_locations(hpxml)
+ if primary_duct_location.nil? # If a home doesn't have any non-living spaces (outside living space), place all ducts in living space.
+ duct.duct_surface_area = primary_duct_area + secondary_duct_area
+ duct.duct_surface_area_isdefaulted = true
+ duct.duct_location = secondary_duct_location
+ duct.duct_location_isdefaulted = true
+ else
+ duct.duct_surface_area = primary_duct_area
+ duct.duct_surface_area_isdefaulted = true
+ duct.duct_location = primary_duct_location
+ duct.duct_location_isdefaulted = true
+
+ if secondary_duct_area > 0
+ hvac_distribution.ducts.add(duct_type: duct.duct_type,
+ duct_insulation_r_value: duct.duct_insulation_r_value,
+ duct_location: secondary_duct_location,
+ duct_location_isdefaulted: true,
+ duct_surface_area: secondary_duct_area,
+ duct_surface_area_isdefaulted: true)
+ end
end
end
- duct.duct_surface_area_isdefaulted = true
- duct.duct_location_isdefaulted = true
+ end
+
+ elsif hvac_distribution.ducts[0].duct_surface_area.nil?
+ # Default duct surface area(s)
+ [supply_ducts, return_ducts].each do |ducts|
+ ducts.each do |duct|
+ total_duct_area = HVAC.get_default_duct_surface_area(duct.duct_type, ncfl_ag, cfa_served, n_returns).sum()
+ duct.duct_surface_area = total_duct_area * duct.duct_fraction_area
+ duct.duct_surface_area_isdefaulted = true
+ end
end
end
- # Also update FractionDuctArea for informational purposes
+ # Calculate FractionDuctArea from DuctSurfaceArea
supply_ducts = hvac_distribution.ducts.select { |duct| duct.duct_type == HPXML::DuctTypeSupply }
return_ducts = hvac_distribution.ducts.select { |duct| duct.duct_type == HPXML::DuctTypeReturn }
total_supply_area = supply_ducts.map { |d| d.duct_surface_area }.sum
total_return_area = return_ducts.map { |d| d.duct_surface_area }.sum
(supply_ducts + return_ducts).each do |duct|
+ next unless duct.duct_fraction_area.nil?
+
if duct.duct_type == HPXML::DuctTypeSupply
duct.duct_fraction_area = (duct.duct_surface_area / total_supply_area).round(3)
duct.duct_fraction_area_isdefaulted = true
@@ -864,6 +1163,10 @@ def self.apply_ventilation_fans(hpxml)
vent_fan.hours_in_operation = (vent_fan.fan_type == HPXML::MechVentTypeCFIS) ? 8.0 : 24.0
vent_fan.hours_in_operation_isdefaulted = true
end
+ if vent_fan.fan_power.nil?
+ flow_rate = [vent_fan.rated_flow_rate.to_f, vent_fan.tested_flow_rate.to_f].max
+ vent_fan.fan_power = flow_rate * Airflow.get_default_mech_vent_fan_power(vent_fan)
+ end
end
# Default kitchen fan
@@ -951,6 +1254,10 @@ def self.apply_water_heaters(hpxml, nbeds, eri_version)
water_heating_system.tank_volume = Waterheater.get_default_tank_volume(water_heating_system.fuel_type, nbeds, hpxml.building_construction.number_of_bathrooms)
water_heating_system.tank_volume_isdefaulted = true
end
+ if water_heating_system.energy_factor.nil? && water_heating_system.uniform_energy_factor.nil?
+ water_heating_system.energy_factor = Waterheater.get_default_water_heater_efficiency_by_year_installed(water_heating_system.year_installed, water_heating_system.fuel_type)
+ water_heating_system.energy_factor_isdefaulted = true
+ end
if water_heating_system.recovery_efficiency.nil?
water_heating_system.recovery_efficiency = Waterheater.get_default_recovery_efficiency(water_heating_system)
water_heating_system.recovery_efficiency_isdefaulted = true
@@ -960,6 +1267,14 @@ def self.apply_water_heaters(hpxml, nbeds, eri_version)
water_heating_system.location = Waterheater.get_default_location(hpxml, hpxml.climate_and_risk_zones.iecc_zone)
water_heating_system.location_isdefaulted = true
end
+ next unless water_heating_system.usage_bin.nil? && (not water_heating_system.uniform_energy_factor.nil?) # FHR & UsageBin only applies to UEF
+
+ if not water_heating_system.first_hour_rating.nil?
+ water_heating_system.usage_bin = Waterheater.get_usage_bin_from_first_hour_rating(water_heating_system.first_hour_rating)
+ else
+ water_heating_system.usage_bin = HPXML::WaterHeaterUsageBinMedium
+ end
+ water_heating_system.usage_bin_isdefaulted = true
end
end
@@ -1011,14 +1326,17 @@ def self.apply_water_fixtures(hpxml)
end
def self.apply_solar_thermal_systems(hpxml)
- return if hpxml.solar_thermal_systems.size == 0
-
- solar_thermal_system = hpxml.solar_thermal_systems[0]
- collector_area = solar_thermal_system.collector_area
-
- if not collector_area.nil? # Detailed solar water heater
- if solar_thermal_system.storage_volume.nil?
- solar_thermal_system.storage_volume = Waterheater.calc_default_solar_thermal_system_storage_volume(collector_area)
+ hpxml.solar_thermal_systems.each do |solar_thermal_system|
+ if solar_thermal_system.collector_azimuth.nil?
+ solar_thermal_system.collector_azimuth = get_azimuth_from_orientation(solar_thermal_system.collector_orientation)
+ solar_thermal_system.collector_azimuth_isdefaulted = true
+ end
+ if solar_thermal_system.collector_orientation.nil?
+ solar_thermal_system.collector_orientation = get_orientation_from_azimuth(solar_thermal_system.collector_azimuth)
+ solar_thermal_system.collector_orientation_isdefaulted = true
+ end
+ if solar_thermal_system.storage_volume.nil? && (not solar_thermal_system.collector_area.nil?) # Detailed solar water heater
+ solar_thermal_system.storage_volume = Waterheater.calc_default_solar_thermal_system_storage_volume(solar_thermal_system.collector_area)
solar_thermal_system.storage_volume_isdefaulted = true
end
end
@@ -1026,6 +1344,14 @@ def self.apply_solar_thermal_systems(hpxml)
def self.apply_pv_systems(hpxml)
hpxml.pv_systems.each do |pv_system|
+ if pv_system.array_azimuth.nil?
+ pv_system.array_azimuth = get_azimuth_from_orientation(pv_system.array_orientation)
+ pv_system.array_azimuth_isdefaulted = true
+ end
+ if pv_system.array_orientation.nil?
+ pv_system.array_orientation = get_orientation_from_azimuth(pv_system.array_azimuth)
+ pv_system.array_orientation_isdefaulted = true
+ end
if pv_system.is_shared_system.nil?
pv_system.is_shared_system = false
pv_system.is_shared_system_isdefaulted = true
@@ -1828,4 +2154,50 @@ def self.apply_hvac_sizing(hpxml, weather, cfa, nbeds)
clg_sys.cooling_airflow_cfm_isdefaulted = true
end
end
+
+ def self.get_azimuth_from_orientation(orientation)
+ return if orientation.nil?
+
+ if orientation == HPXML::OrientationNorth
+ return 0
+ elsif orientation == HPXML::OrientationNortheast
+ return 45
+ elsif orientation == HPXML::OrientationEast
+ return 90
+ elsif orientation == HPXML::OrientationSoutheast
+ return 135
+ elsif orientation == HPXML::OrientationSouth
+ return 180
+ elsif orientation == HPXML::OrientationSouthwest
+ return 225
+ elsif orientation == HPXML::OrientationWest
+ return 270
+ elsif orientation == HPXML::OrientationNorthwest
+ return 315
+ end
+
+ fail "Unexpected orientation: #{orientation}."
+ end
+
+ def self.get_orientation_from_azimuth(azimuth)
+ return if azimuth.nil?
+
+ if (azimuth >= 0.0 - 22.5 + 360.0) || (azimuth < 0.0 + 22.5)
+ return HPXML::OrientationNorth
+ elsif (azimuth >= 45.0 - 22.5) && (azimuth < 45.0 + 22.5)
+ return HPXML::OrientationNortheast
+ elsif (azimuth >= 90.0 - 22.5) && (azimuth < 90.0 + 22.5)
+ return HPXML::OrientationEast
+ elsif (azimuth >= 135.0 - 22.5) && (azimuth < 135.0 + 22.5)
+ return HPXML::OrientationSoutheast
+ elsif (azimuth >= 180.0 - 22.5) && (azimuth < 180.0 + 22.5)
+ return HPXML::OrientationSouth
+ elsif (azimuth >= 225.0 - 22.5) && (azimuth < 225.0 + 22.5)
+ return HPXML::OrientationSouthwest
+ elsif (azimuth >= 270.0 - 22.5) && (azimuth < 270.0 + 22.5)
+ return HPXML::OrientationWest
+ elsif (azimuth >= 315.0 - 22.5) && (azimuth < 315.0 + 22.5)
+ return HPXML::OrientationNorthwest
+ end
+ end
end
diff --git a/HPXMLtoOpenStudio/resources/hvac.rb b/HPXMLtoOpenStudio/resources/hvac.rb
index 3dda66ab86..f3e0df778c 100644
--- a/HPXMLtoOpenStudio/resources/hvac.rb
+++ b/HPXMLtoOpenStudio/resources/hvac.rb
@@ -60,17 +60,18 @@ def self.apply_central_air_conditioner_furnace(model, runner, cooling_system, he
else
num_speeds = 1
end
+ fan_cfms = []
if not heating_system.nil?
htg_cfm = heating_system.heating_airflow_cfm
+ fan_cfms << htg_cfm
end
if not cooling_system.nil?
clg_cfm = cooling_system.cooling_airflow_cfm
+ clg_ap.cool_fan_speed_ratios.each do |r|
+ fan_cfms << clg_cfm * r
+ end
end
- fan_cfm = [htg_cfm.to_f, clg_cfm.to_f].max
- if not cooling_system.nil?
- fan_cfm *= clg_ap.cool_fan_speed_ratios.max
- end
- fan = create_supply_fan(model, obj_name, num_speeds, fan_watts_per_cfm, fan_cfm)
+ fan = create_supply_fan(model, obj_name, fan_watts_per_cfm, fan_cfms)
if not cooling_system.nil?
hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
end
@@ -99,7 +100,7 @@ def self.apply_central_air_conditioner_furnace(model, runner, cooling_system, he
end
# Air Loop
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, fan_cfm)
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, [htg_cfm.to_f, clg_cfm.to_f].max)
if not cooling_system.nil?
hvac_map[cooling_system.id] << air_loop
end
@@ -134,7 +135,12 @@ def self.apply_room_air_conditioner(model, runner, cooling_system,
clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model, model.alwaysOnDiscreteSchedule, roomac_cap_ft_curve, roomac_cap_fff_curve, roomac_eir_ft_curve, roomcac_eir_fff_curve, roomac_plf_fplr_curve)
clg_coil.setName(obj_name + ' clg coil')
clg_coil.setRatedSensibleHeatRatio(cooling_system.cooling_shr)
- clg_coil.setRatedCOP(UnitConversions.convert(cooling_system.cooling_efficiency_eer, 'Btu/hr', 'W'))
+ if cooling_system.cooling_efficiency_ceer.nil?
+ ceer = calc_ceer_from_eer(cooling_system)
+ else
+ ceer = cooling_system.cooling_efficiency_ceer
+ end
+ clg_coil.setRatedCOP(UnitConversions.convert(ceer, 'Btu/hr', 'W'))
clg_coil.setRatedEvaporatorFanPowerPerVolumeFlowRate(773.3)
clg_coil.setEvaporativeCondenserEffectiveness(0.9)
clg_coil.setMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation(10)
@@ -145,7 +151,7 @@ def self.apply_room_air_conditioner(model, runner, cooling_system,
# Fan
clg_cfm = cooling_system.cooling_airflow_cfm
- fan = create_supply_fan(model, obj_name, 1, 0.0, clg_cfm) # Fan power included in EER (net COP) above
+ fan = create_supply_fan(model, obj_name, 0.0, [clg_cfm]) # Fan power included in EER (net COP) above
hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
# Heating Coil (none)
@@ -195,20 +201,8 @@ def self.apply_evaporative_cooler(model, runner, cooling_system,
hvac_map[cooling_system.id] << air_loop
# Fan
- # Use VariableVolume object
- fan = OpenStudio::Model::FanVariableVolume.new(model, model.alwaysOnDiscreteSchedule)
- fan.setName(obj_name + ' supply fan')
- fan.setEndUseSubcategory('supply fan')
- fan.setMotorEfficiency(1)
- fan.setMotorInAirstreamFraction(0)
- fan.setFanPowerCoefficient1(0)
- fan.setFanPowerCoefficient2(1)
- fan.setFanPowerCoefficient3(0)
- fan.setFanPowerCoefficient4(0)
- fan.setFanPowerCoefficient5(0)
- fan.setMaximumFlowRate(UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s'))
fan_watts_per_cfm = [2.79 * clg_cfm**-0.29, 0.6].min # W/cfm; fit of efficacy to air flow from the CEC listed equipment
- set_fan_power(fan, fan_watts_per_cfm)
+ fan = create_supply_fan(model, obj_name, fan_watts_per_cfm, [clg_cfm])
fan.addToNode(air_loop.supplyInletNode)
hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, evap_cooler, nil)
@@ -258,8 +252,14 @@ def self.apply_central_air_to_air_heat_pump(model, runner, heat_pump,
num_speeds = hp_ap.num_speeds
htg_cfm = heat_pump.heating_airflow_cfm
clg_cfm = heat_pump.cooling_airflow_cfm
- fan_cfm = hp_ap.cool_fan_speed_ratios.max * [htg_cfm, clg_cfm].max
- fan = create_supply_fan(model, obj_name, num_speeds, heat_pump.fan_watts_per_cfm, fan_cfm)
+ fan_cfms = []
+ hp_ap.heat_fan_speed_ratios.each do |r|
+ fan_cfms << htg_cfm * r
+ end
+ hp_ap.cool_fan_speed_ratios.each do |r|
+ fan_cfms << clg_cfm * r
+ end
+ fan = create_supply_fan(model, obj_name, heat_pump.fan_watts_per_cfm, fan_cfms)
hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
# Unitary System
@@ -278,7 +278,7 @@ def self.apply_central_air_to_air_heat_pump(model, runner, heat_pump,
end
# Air Loop
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, fan_cfm)
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, [htg_cfm, clg_cfm].max)
hvac_map[heat_pump.id] << air_loop
# HVAC Installation Quality
@@ -301,7 +301,11 @@ def self.apply_mini_split_air_conditioner(model, runner, cooling_system,
# Fan
num_speeds = clg_ap.num_speeds
clg_cfm = cooling_system.cooling_airflow_cfm
- fan = create_supply_fan(model, obj_name, num_speeds, cooling_system.fan_watts_per_cfm, clg_cfm)
+ fan_cfms = []
+ clg_ap.cool_fan_speed_ratios.each do |r|
+ fan_cfms << clg_cfm * r
+ end
+ fan = create_supply_fan(model, obj_name, cooling_system.fan_watts_per_cfm, fan_cfms)
hvac_map[cooling_system.id] += disaggregate_fan_or_pump(model, fan, nil, clg_coil, nil)
# Unitary System
@@ -350,8 +354,14 @@ def self.apply_mini_split_heat_pump(model, runner, heat_pump,
num_speeds = hp_ap.num_speeds
htg_cfm = heat_pump.heating_airflow_cfm
clg_cfm = heat_pump.cooling_airflow_cfm
- fan_cfm = hp_ap.cool_fan_speed_ratios.max * [htg_cfm, clg_cfm].max
- fan = create_supply_fan(model, obj_name, num_speeds, heat_pump.fan_watts_per_cfm, fan_cfm)
+ fan_cfms = []
+ hp_ap.heat_fan_speed_ratios.each do |r|
+ fan_cfms << htg_cfm * r
+ end
+ hp_ap.cool_fan_speed_ratios.each do |r|
+ fan_cfms << clg_cfm * r
+ end
+ fan = create_supply_fan(model, obj_name, heat_pump.fan_watts_per_cfm, fan_cfms)
hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
# Unitary System
@@ -368,7 +378,7 @@ def self.apply_mini_split_heat_pump(model, runner, heat_pump,
air_loop_unitary.setDesignSpecificationMultispeedObject(perf)
# Air Loop
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, fan_cfm)
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, [htg_cfm, clg_cfm].max)
hvac_map[heat_pump.id] << air_loop
# HVAC Installation Quality
@@ -392,9 +402,9 @@ def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
end
# Cooling Coil
- clg_total_cap_curve = create_curve_quad_linear(model, hp_ap.cool_cap_ft_spec[0], obj_name + ' clg total cap curve')
- clg_sens_cap_curve = create_curve_quint_linear(model, hp_ap.cool_sh_ft_spec[0], obj_name + ' clg sens cap curve')
- clg_power_curve = create_curve_quad_linear(model, hp_ap.cool_power_ft_spec[0], obj_name + ' clg power curve')
+ clg_total_cap_curve = create_curve_quad_linear(model, hp_ap.cool_cap_curve_spec[0], obj_name + ' clg total cap curve')
+ clg_sens_cap_curve = create_curve_quint_linear(model, hp_ap.cool_sh_curve_spec[0], obj_name + ' clg sens cap curve')
+ clg_power_curve = create_curve_quad_linear(model, hp_ap.cool_power_curve_spec[0], obj_name + ' clg power curve')
clg_coil = OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit.new(model, clg_total_cap_curve, clg_sens_cap_curve, clg_power_curve)
clg_coil.setName(obj_name + ' clg coil')
clg_coil.setRatedCoolingCoefficientofPerformance(1.0 / hp_ap.cool_rated_eirs[0])
@@ -407,8 +417,8 @@ def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
hvac_map[heat_pump.id] << clg_coil
# Heating Coil
- htg_cap_curve = create_curve_quad_linear(model, hp_ap.heat_cap_ft_spec[0], obj_name + ' htg cap curve')
- htg_power_curve = create_curve_quad_linear(model, hp_ap.heat_power_ft_spec[0], obj_name + ' htg power curve')
+ htg_cap_curve = create_curve_quad_linear(model, hp_ap.heat_cap_curve_spec[0], obj_name + ' htg cap curve')
+ htg_power_curve = create_curve_quad_linear(model, hp_ap.heat_power_curve_spec[0], obj_name + ' htg power curve')
htg_coil = OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit.new(model, htg_cap_curve, htg_power_curve)
htg_coil.setName(obj_name + ' htg coil')
htg_coil.setRatedHeatingCoefficientofPerformance(1.0 / hp_ap.heat_rated_eirs[0])
@@ -512,8 +522,7 @@ def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
demand_outlet_pipe.addToNode(plant_loop.demandOutletNode)
# Fan
- fan_cfm = [htg_cfm, clg_cfm].max
- fan = create_supply_fan(model, obj_name, 1, heat_pump.fan_watts_per_cfm, fan_cfm)
+ fan = create_supply_fan(model, obj_name, heat_pump.fan_watts_per_cfm, [htg_cfm, clg_cfm])
hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
# Unitary System
@@ -543,7 +552,7 @@ def self.apply_ground_to_air_heat_pump(model, runner, weather, heat_pump,
end
# Air Loop
- air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, fan_cfm)
+ air_loop = create_air_loop(model, obj_name, air_loop_unitary, control_zone, sequential_heat_load_fracs, sequential_cool_load_fracs, [htg_cfm, clg_cfm].max)
hvac_map[heat_pump.id] << air_loop
# HVAC Installation Quality
@@ -586,7 +595,7 @@ def self.apply_water_loop_to_air_heat_pump(model, runner, heat_pump,
# Fan
fan_power_installed = 0.0 # Use provided net COP
- fan = create_supply_fan(model, obj_name, 1, fan_power_installed, htg_cfm)
+ fan = create_supply_fan(model, obj_name, fan_power_installed, [htg_cfm])
hvac_map[heat_pump.id] += disaggregate_fan_or_pump(model, fan, htg_coil, clg_coil, htg_supp_coil)
# Unitary System
@@ -723,7 +732,7 @@ def self.apply_boiler(model, runner, heating_system,
if heating_system.distribution_system.air_type.to_s == HPXML::AirTypeFanCoil
# Fan
- fan = create_supply_fan(model, obj_name, 1, 0.0, fan_cfm) # fan energy included in above pump via Electric Auxiliary Energy (EAE)
+ fan = create_supply_fan(model, obj_name, 0.0, [fan_cfm]) # fan energy included in above pump via Electric Auxiliary Energy (EAE)
# Heating Coil
htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, model.alwaysOnDiscreteSchedule)
@@ -748,6 +757,7 @@ def self.apply_boiler(model, runner, heating_system,
# Fan Coil
zone_hvac = OpenStudio::Model::ZoneHVACFourPipeFanCoil.new(model, model.alwaysOnDiscreteSchedule, fan, clg_coil, htg_coil)
+ zone_hvac.setCapacityControlMethod('CyclingFan')
zone_hvac.setName(obj_name + ' fan coil')
zone_hvac.setMaximumSupplyAirTemperatureInHeatingMode(UnitConversions.convert(120.0, 'F', 'C'))
zone_hvac.setHeatingConvergenceTolerance(0.001)
@@ -832,7 +842,7 @@ def self.apply_unit_heater(model, runner, heating_system,
# Fan
htg_cfm = heating_system.heating_airflow_cfm
fan_watts_per_cfm = heating_system.fan_watts / htg_cfm
- fan = create_supply_fan(model, obj_name, 1, fan_watts_per_cfm, htg_cfm)
+ fan = create_supply_fan(model, obj_name, fan_watts_per_cfm, [htg_cfm])
hvac_map[heating_system.id] += disaggregate_fan_or_pump(model, fan, htg_coil, nil, nil)
# Unitary System
@@ -1132,7 +1142,7 @@ def self.set_cool_curves_ashp(heat_pump)
hp_ap.cool_rated_airflow_rate = 344.1 # cfm/ton
hp_ap.cool_capacity_ratios = [0.72, 1.0]
hp_ap.cool_fan_speed_ratios = [0.86, 1.0]
- hp_ap.cool_rated_shrs_net = [heat_pump.cooling_shr - 0.014, heat_pump.cooling_shr] # TODO: is the following assumption correct (revisit Dylan's data?)? OR should value from HPXML be used for both stages?
+ hp_ap.cool_rated_shrs_net = [heat_pump.cooling_shr - 0.014, heat_pump.cooling_shr]
hp_ap.cool_cap_ft_spec = [[3.998418659, -0.108728222, 0.001056818, 0.007512314, -0.0000139, -0.000164716],
[3.466810106, -0.091476056, 0.000901205, 0.004163355, -0.00000919, -0.000110829]]
hp_ap.cool_eir_ft_spec = [[-4.282911381, 0.181023691, -0.001357391, -0.026310378, 0.000333282, -0.000197405],
@@ -1308,9 +1318,9 @@ def self.set_curves_gshp(heat_pump)
# Coefficients generated by catalog data: https://files.climatemaster.com/Genesis-GS-Series-Product-Catalog.pdf, p180
# Data point taken as rated condition:
# EWT: 80F EAT:80/67F, AFR: 1200cfm, WFR: 4.5gpm
- hp_ap.cool_cap_ft_spec = [[-1.57177156131221, 4.60343712716819, -2.15976622898044, 0.0590964827802021, 0.0194696644460315]]
- hp_ap.cool_power_ft_spec = [[-4.42471086639888, 0.658017281046304, 4.37331801294626, 0.174096187531254, -0.0526514790164159]]
- hp_ap.cool_sh_ft_spec = [[4.54172823345154, 14.7653304889134, -18.3541272090485, -0.74401391092935, 0.545560799548833, 0.0182620032235494]]
+ hp_ap.cool_cap_curve_spec = [[-1.57177156131221, 4.60343712716819, -2.15976622898044, 0.0590964827802021, 0.0194696644460315]]
+ hp_ap.cool_power_curve_spec = [[-4.42471086639888, 0.658017281046304, 4.37331801294626, 0.174096187531254, -0.0526514790164159]]
+ hp_ap.cool_sh_curve_spec = [[4.54172823345154, 14.7653304889134, -18.3541272090485, -0.74401391092935, 0.545560799548833, 0.0182620032235494]]
hp_ap.cool_rated_shrs_gross = [heat_pump.cooling_shr]
# FUTURE: Reconcile these fan/pump adjustments with ANSI/RESNET/ICC 301-2019 Section 4.4.5
fan_adjust_kw = UnitConversions.convert(400.0, 'Btu/hr', 'ton') * UnitConversions.convert(1.0, 'cfm', 'm^3/s') * 1000.0 * 0.35 * 249.0 / 300.0 # Adjustment per ISO 13256-1 Internal pressure drop across heat pump assumed to be 0.5 in. w.g.
@@ -1321,8 +1331,8 @@ def self.set_curves_gshp(heat_pump)
# E+ equation fit coil coefficients from Tang's thesis:
# See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
# Coefficients generated by catalog data
- hp_ap.heat_cap_ft_spec = [[-5.12650150, -0.93997630, 7.21443206, 0.121065721, 0.051809805]]
- hp_ap.heat_power_ft_spec = [[-7.73235249, 6.43390775, 2.29152262, -0.175598629, 0.005888871]]
+ hp_ap.heat_cap_curve_spec = [[-5.12650150, -0.93997630, 7.21443206, 0.121065721, 0.051809805]]
+ hp_ap.heat_power_curve_spec = [[-7.73235249, 6.43390775, 2.29152262, -0.175598629, 0.005888871]]
heat_eir = (1.0 - heat_pump.heating_efficiency_cop * (fan_adjust_kw + pump_adjust_kw)) / (heat_pump.heating_efficiency_cop * (1.0 - fan_adjust_kw))
hp_ap.heat_rated_eirs = [heat_eir]
end
@@ -1477,7 +1487,7 @@ def self.disaggregate_fan_or_pump(model, fan_or_pump, htg_object, clg_object, ba
hvac_objects = []
- if fan_or_pump.is_a?(OpenStudio::Model::FanOnOff) || fan_or_pump.is_a?(OpenStudio::Model::FanVariableVolume)
+ if fan_or_pump.is_a? OpenStudio::Model::FanSystemModel
fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Fan #{EPlus::FuelTypeElectricity} Energy")
elsif fan_or_pump.is_a? OpenStudio::Model::PumpVariableSpeed
fan_or_pump_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Pump #{EPlus::FuelTypeElectricity} Energy")
@@ -1552,6 +1562,7 @@ def self.disaggregate_fan_or_pump(model, fan_or_pump, htg_object, clg_object, ba
if (sensors.size != 1) || (mode != 'primary_htg')
fail 'Unexpected situation.'
end
+
fan_or_pump_program.addLine(" Set #{fan_or_pump_var}_#{mode} = #{fan_or_pump_sensor.name}")
else
sensors.each do |mode, sensor|
@@ -1663,20 +1674,24 @@ def self.create_supp_heating_coil(model, obj_name, heat_pump)
return htg_supp_coil
end
- def self.create_supply_fan(model, obj_name, num_speeds, fan_watts_per_cfm, fan_cfm)
- if num_speeds == 1
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule)
- else
- fan_power_curve = create_curve_exponent(model, [0, 1, 3], obj_name + ' fan power curve', -100, 100)
- fan_eff_curve = create_curve_cubic(model, [0, 1, 0, 0], obj_name + ' fan eff curve', 0, 1, 0.01, 1)
- fan = OpenStudio::Model::FanOnOff.new(model, model.alwaysOnDiscreteSchedule, fan_power_curve, fan_eff_curve)
- end
+ def self.create_supply_fan(model, obj_name, fan_watts_per_cfm, fan_cfms)
+ # Note: fan_cfms should include all unique airflow rates (both heating and cooling, at all speeds)
+ fan = OpenStudio::Model::FanSystemModel.new(model)
+ fan.setSpeedControlMethod('Discrete')
+ fan.setDesignPowerSizingMethod('TotalEfficiencyAndPressure')
+ fan.setAvailabilitySchedule(model.alwaysOnDiscreteSchedule)
set_fan_power(fan, fan_watts_per_cfm)
fan.setName(obj_name + ' supply fan')
fan.setEndUseSubcategory('supply fan')
fan.setMotorEfficiency(1.0)
- fan.setMotorInAirstreamFraction(1.0)
- fan.setMaximumFlowRate(UnitConversions.convert(fan_cfm, 'cfm', 'm^3/s'))
+ fan.setMotorInAirStreamFraction(1.0)
+ max_fan_cfm = Float(fan_cfms.max) # Convert to float to prevent integer division below
+ fan.setDesignMaximumAirFlowRate(UnitConversions.convert(max_fan_cfm, 'cfm', 'm^3/s'))
+ fan_cfms.sort.each do |fan_cfm|
+ fan_ratio = fan_cfm / max_fan_cfm
+ power_fraction = fan_ratio**3 # fan power curve
+ fan.addSpeed(fan_ratio.round(5), power_fraction.round(5))
+ end
return fan
end
@@ -3077,19 +3092,22 @@ def self.set_heat_c_d(heating_system, num_speeds)
htg_ap.heat_plf_fplr_spec = [calc_plr_coefficients(htg_ap.heat_c_d)] * num_speeds
end
+ def self.calc_ceer_from_eer(cooling_system)
+ return if cooling_system.cooling_system_type != HPXML::HVACTypeRoomAirConditioner
+
+ # Reference: http://documents.dps.ny.gov/public/Common/ViewDoc.aspx?DocRefId=%7BB6A57FC0-6376-4401-92BD-D66EC1930DCF%7D
+ return cooling_system.cooling_efficiency_eer / 1.01
+ end
+
def self.set_fan_power_rated(hvac_system)
hvac_ap = hvac_system.additional_properties
- if (hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)) ||
- (hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit))
- if not hvac_system.distribution_system.nil?
- # Ducted, installed fan power may differ from rated fan power
- hvac_ap.fan_power_rated = 0.18 # W/cfm, ducted
- else
- # Ductless, installed and rated value should be equal
- hvac_ap.fan_power_rated = 0.07 # W/cfm
- hvac_system.fan_watts_per_cfm = hvac_ap.fan_power_rated # W/cfm
- end
+ if hvac_system.distribution_system.nil?
+ # Ductless, installed and rated value should be equal
+ hvac_ap.fan_power_rated = hvac_system.fan_watts_per_cfm # W/cfm
+ elsif (hvac_system.is_a?(HPXML::CoolingSystem) && (hvac_system.cooling_system_type == HPXML::HVACTypeMiniSplitAirConditioner)) ||
+ (hvac_system.is_a?(HPXML::HeatPump) && (hvac_system.heat_pump_type == HPXML::HVACTypeHeatPumpMiniSplit))
+ hvac_ap.fan_power_rated = 0.18 # W/cfm
elsif hvac_system.cooling_efficiency_seer <= 15
hvac_ap.fan_power_rated = 0.365 # W/cfm
else
@@ -3100,12 +3118,13 @@ def self.set_fan_power_rated(hvac_system)
def self.set_fan_power(fan, fan_watts_per_cfm)
if fan_watts_per_cfm > 0
fan_eff = 0.75 # Overall Efficiency of the Fan, Motor and Drive
- fan.setFanEfficiency(fan_eff)
- fan.setPressureRise(fan_eff * fan_watts_per_cfm / UnitConversions.convert(1.0, 'cfm', 'm^3/s')) # Pa
+ pressure_rise = fan_eff * fan_watts_per_cfm / UnitConversions.convert(1.0, 'cfm', 'm^3/s') # Pa
else
- fan.setFanEfficiency(1)
- fan.setPressureRise(0)
+ fan_eff = 1
+ pressure_rise = 0.000001
end
+ fan.setFanTotalEfficiency(fan_eff)
+ fan.setDesignPressureRise(pressure_rise)
end
def self.calc_pump_rated_flow_rate(pump_eff, pump_w, pump_head_pa)
@@ -3718,7 +3737,7 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
if (not clg_coil.nil?) && (cooling_system.fraction_cool_load_served > 0)
clg_ap = cooling_system.additional_properties
clg_cfm = cooling_system.cooling_airflow_cfm
- if clg_coil.to_CoilCoolingDXSingleSpeed.is_initialized
+ if clg_coil.to_CoilCoolingDXSingleSpeed.is_initialized || clg_coil.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized
cool_airflow_rated_defect_ratio = [UnitConversions.convert(clg_cfm, 'cfm', 'm^3/s') / clg_coil.ratedAirFlowRate.get - 1.0]
elsif clg_coil.to_CoilCoolingDXMultiSpeed.is_initialized
cool_airflow_rated_defect_ratio = clg_coil.stages.zip(clg_ap.cool_fan_speed_ratios).map { |stage, speed_ratio| UnitConversions.convert(clg_cfm * speed_ratio, 'cfm', 'm^3/s') / stage.ratedAirFlowRate.get - 1.0 }
@@ -3729,7 +3748,7 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
if (not htg_coil.nil?) && (heating_system.fraction_heat_load_served > 0)
htg_ap = heating_system.additional_properties
htg_cfm = heating_system.heating_airflow_cfm
- if htg_coil.to_CoilHeatingDXSingleSpeed.is_initialized
+ if htg_coil.to_CoilHeatingDXSingleSpeed.is_initialized || htg_coil.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized
heat_airflow_rated_defect_ratio = [UnitConversions.convert(htg_cfm, 'cfm', 'm^3/s') / htg_coil.ratedAirFlowRate.get - 1.0]
elsif htg_coil.to_CoilHeatingDXMultiSpeed.is_initialized
heat_airflow_rated_defect_ratio = htg_coil.stages.zip(htg_ap.heat_fan_speed_ratios).map { |stage, speed_ratio| UnitConversions.convert(htg_cfm * speed_ratio, 'cfm', 'm^3/s') / stage.ratedAirFlowRate.get - 1.0 }
@@ -3763,9 +3782,24 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
num_speeds = clg_coil.stages.size
cool_cap_fff_curves = clg_coil.stages.map { |stage| stage.totalCoolingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
cool_eir_fff_curves = clg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
+ elsif clg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit
+ num_speeds = 1
+ cool_cap_fff_curves = [clg_coil.totalCoolingCapacityCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
+ cool_eir_fff_curves = [clg_coil.coolingPowerConsumptionCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
+ # variables are the same for eir and cap curve
+ var1_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 1 Value')
+ var1_sensor.setName('Cool Cap Curve Var 1')
+ var1_sensor.setKeyName(cool_cap_fff_curves[0].name.to_s)
+ var2_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 2 Value')
+ var2_sensor.setName('Cool Cap Curve Var 2')
+ var2_sensor.setKeyName(cool_cap_fff_curves[0].name.to_s)
+ var4_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 4 Value')
+ var4_sensor.setName('Cool Cap Curve Var 4')
+ var4_sensor.setKeyName(cool_cap_fff_curves[0].name.to_s)
else
fail 'cooling coil not supported'
end
+
for speed in 0..(num_speeds - 1)
cool_cap_fff_curve = cool_cap_fff_curves[speed]
cool_cap_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(cool_cap_fff_curve, 'Curve', 'Curve Result')
@@ -3776,15 +3810,25 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
cool_eir_fff_act.setName("#{obj_name} eir clg act")
# NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
- fault_program.addLine("Set a1_AF_Qgr_c = #{cool_cap_fff_curve.coefficient1Constant}")
- fault_program.addLine("Set a2_AF_Qgr_c = #{cool_cap_fff_curve.coefficient2x}")
- fault_program.addLine("Set a3_AF_Qgr_c = #{cool_cap_fff_curve.coefficient3xPOW2}")
- fault_program.addLine("Set a1_AF_EIR_c = #{cool_eir_fff_curve.coefficient1Constant}")
- fault_program.addLine("Set a2_AF_EIR_c = #{cool_eir_fff_curve.coefficient2x}")
- fault_program.addLine("Set a3_AF_EIR_c = #{cool_eir_fff_curve.coefficient3xPOW2}")
+ if not clg_coil.is_a? OpenStudio::Model::CoilCoolingWaterToAirHeatPumpEquationFit
+ fault_program.addLine("Set a1_AF_Qgr_c = #{cool_cap_fff_curve.coefficient1Constant}")
+ fault_program.addLine("Set a2_AF_Qgr_c = #{cool_cap_fff_curve.coefficient2x}")
+ fault_program.addLine("Set a3_AF_Qgr_c = #{cool_cap_fff_curve.coefficient3xPOW2}")
+ fault_program.addLine("Set a1_AF_EIR_c = #{cool_eir_fff_curve.coefficient1Constant}")
+ fault_program.addLine("Set a2_AF_EIR_c = #{cool_eir_fff_curve.coefficient2x}")
+ fault_program.addLine("Set a3_AF_EIR_c = #{cool_eir_fff_curve.coefficient3xPOW2}")
+ else
+ fault_program.addLine("Set a1_AF_Qgr_c = #{cool_cap_fff_curve.coefficient1Constant} + (#{cool_cap_fff_curve.coefficient2w}*#{var1_sensor.name}) + (#{cool_cap_fff_curve.coefficient3x}*#{var2_sensor.name}) + (#{cool_cap_fff_curve.coefficient5z}*#{var4_sensor.name})")
+ fault_program.addLine("Set a2_AF_Qgr_c = #{cool_cap_fff_curve.coefficient4y}")
+ fault_program.addLine('Set a3_AF_Qgr_c = 0')
+ fault_program.addLine("Set a1_AF_EIR_c = #{cool_eir_fff_curve.coefficient1Constant} + (#{cool_eir_fff_curve.coefficient2w}*#{var1_sensor.name}) + (#{cool_eir_fff_curve.coefficient3x}*#{var2_sensor.name}) + (#{cool_eir_fff_curve.coefficient5z}*#{var4_sensor.name})")
+ fault_program.addLine("Set a2_AF_EIR_c = #{cool_eir_fff_curve.coefficient4y}")
+ fault_program.addLine('Set a3_AF_EIR_c = 0')
+ end
qgr_values, p_values, ff_chg_values = get_installation_quality_cooling_coeff(f_chg)
+ # charge defect impact
fault_program.addLine("Set a1_CH_Qgr_c = #{qgr_values[0]}")
fault_program.addLine("Set a2_CH_Qgr_c = #{qgr_values[1]}")
fault_program.addLine("Set a3_CH_Qgr_c = #{qgr_values[2]}")
@@ -3795,43 +3839,31 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
fault_program.addLine("Set a3_CH_P_c = #{p_values[2]}")
fault_program.addLine("Set a4_CH_P_c = #{p_values[3]}")
- ff_ch_c = 1.0 / (1.0 + (qgr_values[0] + (qgr_values[1] * ff_chg_values[0]) + (qgr_values[2] * ff_chg_values[1]) + (qgr_values[3] * f_chg)) * f_chg)
- fault_program.addLine("Set FF_CH_c = #{ff_ch_c.round(3)}")
-
fault_program.addLine('Set q0_CH = a1_CH_Qgr_c')
fault_program.addLine("Set q1_CH = a2_CH_Qgr_c*#{tin_sensor.name}")
fault_program.addLine("Set q2_CH = a3_CH_Qgr_c*#{tout_sensor.name}")
fault_program.addLine('Set q3_CH = a4_CH_Qgr_c*F_CH')
fault_program.addLine('Set Y_CH_Q_c = 1 + ((q0_CH+(q1_CH)+(q2_CH)+(q3_CH))*F_CH)')
- fault_program.addLine('Set q0_AF_CH = a1_AF_Qgr_c')
- fault_program.addLine('Set q1_AF_CH = a2_AF_Qgr_c*FF_CH_c')
- fault_program.addLine('Set q2_AF_CH = a3_AF_Qgr_c*FF_CH_c*FF_CH_c')
- fault_program.addLine('Set p_CH_Q_c = Y_CH_Q_c/(q0_AF_CH+(q1_AF_CH)+(q2_AF_CH))')
-
fault_program.addLine('Set p1_CH = a1_CH_P_c')
fault_program.addLine("Set p2_CH = a2_CH_P_c*#{tin_sensor.name}")
fault_program.addLine("Set p3_CH = a3_CH_P_c*#{tout_sensor.name}")
fault_program.addLine('Set p4_CH = a4_CH_P_c*F_CH')
fault_program.addLine('Set Y_CH_COP_c = Y_CH_Q_c/(1 + (p1_CH+(p2_CH)+(p3_CH)+(p4_CH))*F_CH)')
- fault_program.addLine('Set eir0_AF_CH = a1_AF_EIR_c')
- fault_program.addLine('Set eir1_AF_CH = a2_AF_EIR_c*FF_CH_c')
- fault_program.addLine('Set eir2_AF_CH = a3_AF_EIR_c*FF_CH_c*FF_CH_c')
- fault_program.addLine('Set p_CH_COP_c = Y_CH_COP_c*(eir0_AF_CH+(eir1_AF_CH)+(eir2_AF_CH))')
-
+ # air flow defect and charge defect combined to modify airflow curve output
+ ff_ch_c = 1.0 / (1.0 + (qgr_values[0] + (qgr_values[1] * ff_chg_values[0]) + (qgr_values[2] * ff_chg_values[1]) + (qgr_values[3] * f_chg)) * f_chg)
+ fault_program.addLine("Set FF_CH_c = #{ff_ch_c.round(3)}")
fault_program.addLine("Set FF_AF_c = 1.0 + #{cool_airflow_rated_defect_ratio[speed].round(3)}")
fault_program.addLine('Set FF_AF_comb_c = FF_CH_c * FF_AF_c')
- fault_program.addLine('Set q0_AF_comb = a1_AF_Qgr_c')
- fault_program.addLine('Set q1_AF_comb = a2_AF_Qgr_c*FF_AF_comb_c')
- fault_program.addLine('Set q2_AF_comb = a3_AF_Qgr_c*FF_AF_comb_c*FF_AF_comb_c')
- fault_program.addLine('Set p_AF_Q_c = q0_AF_comb+(q1_AF_comb)+(q2_AF_comb)')
+ fault_program.addLine('Set q_AF_CH = (a1_AF_Qgr_c) + (a2_AF_Qgr_c*FF_CH_c) + (a3_AF_Qgr_c*FF_CH_c*FF_CH_c)')
+ fault_program.addLine('Set eir_AF_CH = (a1_AF_EIR_c) + (a2_AF_EIR_c*FF_CH_c) + (a3_AF_EIR_c*FF_CH_c*FF_CH_c)')
+ fault_program.addLine('Set p_CH_Q_c = Y_CH_Q_c/q_AF_CH')
+ fault_program.addLine('Set p_CH_COP_c = Y_CH_COP_c*eir_AF_CH')
- fault_program.addLine('Set eir0_AF_comb = a1_AF_EIR_c')
- fault_program.addLine('Set eir1_AF_comb = a2_AF_EIR_c*FF_AF_comb_c')
- fault_program.addLine('Set eir2_AF_comb = a3_AF_EIR_c*FF_AF_comb_c*FF_AF_comb_c')
- fault_program.addLine('Set p_AF_COP_c = 1.0/(eir0_AF_comb+(eir1_AF_comb)+(eir2_AF_comb))')
+ fault_program.addLine('Set p_AF_Q_c = (a1_AF_Qgr_c) + (a2_AF_Qgr_c*FF_AF_comb_c) + (a3_AF_Qgr_c*FF_AF_comb_c*FF_AF_comb_c)')
+ fault_program.addLine('Set p_AF_COP_c = 1.0 / ((a1_AF_EIR_c) + (a2_AF_EIR_c*FF_AF_comb_c) + (a3_AF_EIR_c*FF_AF_comb_c*FF_AF_comb_c))')
fault_program.addLine("Set #{cool_cap_fff_act.name} = (p_CH_Q_c * p_AF_Q_c)")
fault_program.addLine("Set #{cool_eir_fff_act.name} = (1.0 / (p_CH_COP_c * p_AF_COP_c))")
@@ -3848,6 +3880,20 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
num_speeds = htg_coil.stages.size
heat_cap_fff_curves = htg_coil.stages.map { |stage| stage.heatingCapacityFunctionofFlowFractionCurve.to_CurveQuadratic.get }
heat_eir_fff_curves = htg_coil.stages.map { |stage| stage.energyInputRatioFunctionofFlowFractionCurve.to_CurveQuadratic.get }
+ elsif htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit
+ num_speeds = 1
+ heat_cap_fff_curves = [htg_coil.heatingCapacityCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
+ heat_eir_fff_curves = [htg_coil.heatingPowerConsumptionCurve.to_CurveQuadLinear.get] # quadlinear curve, only forth term is for airflow
+ # variables are the same for eir and cap curve
+ var1_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 1 Value')
+ var1_sensor.setName('Heat Cap Curve Var 1')
+ var1_sensor.setKeyName(heat_cap_fff_curves[0].name.to_s)
+ var2_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 2 Value')
+ var2_sensor.setName('Heat Cap Curve Var 2')
+ var2_sensor.setKeyName(heat_cap_fff_curves[0].name.to_s)
+ var4_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Performance Curve Input Variable 4 Value')
+ var4_sensor.setName('Heat Cap Curve Var 4')
+ var4_sensor.setKeyName(heat_cap_fff_curves[0].name.to_s)
else
fail 'heating coil not supported'
end
@@ -3860,15 +3906,26 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
heat_eir_fff_act = OpenStudio::Model::EnergyManagementSystemActuator.new(heat_eir_fff_curve, 'Curve', 'Curve Result')
heat_eir_fff_act.setName("#{obj_name} eir htg act")
- fault_program.addLine("Set a1_AF_Qgr_h = #{heat_cap_fff_curve.coefficient1Constant}")
- fault_program.addLine("Set a2_AF_Qgr_h = #{heat_cap_fff_curve.coefficient2x}")
- fault_program.addLine("Set a3_AF_Qgr_h = #{heat_cap_fff_curve.coefficient3xPOW2}")
- fault_program.addLine("Set a1_AF_EIR_h = #{heat_eir_fff_curve.coefficient1Constant}")
- fault_program.addLine("Set a2_AF_EIR_h = #{heat_eir_fff_curve.coefficient2x}")
- fault_program.addLine("Set a3_AF_EIR_h = #{heat_eir_fff_curve.coefficient3xPOW2}")
+ # NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
+ if not htg_coil.is_a? OpenStudio::Model::CoilHeatingWaterToAirHeatPumpEquationFit
+ fault_program.addLine("Set a1_AF_Qgr_h = #{heat_cap_fff_curve.coefficient1Constant}")
+ fault_program.addLine("Set a2_AF_Qgr_h = #{heat_cap_fff_curve.coefficient2x}")
+ fault_program.addLine("Set a3_AF_Qgr_h = #{heat_cap_fff_curve.coefficient3xPOW2}")
+ fault_program.addLine("Set a1_AF_EIR_h = #{heat_eir_fff_curve.coefficient1Constant}")
+ fault_program.addLine("Set a2_AF_EIR_h = #{heat_eir_fff_curve.coefficient2x}")
+ fault_program.addLine("Set a3_AF_EIR_h = #{heat_eir_fff_curve.coefficient3xPOW2}")
+ else
+ fault_program.addLine("Set a1_AF_Qgr_h = #{heat_cap_fff_curve.coefficient1Constant} + (#{heat_cap_fff_curve.coefficient2w}*#{var1_sensor.name}) + (#{heat_cap_fff_curve.coefficient3x}*#{var2_sensor.name}) + (#{heat_cap_fff_curve.coefficient5z}*#{var4_sensor.name})")
+ fault_program.addLine("Set a2_AF_Qgr_h = #{heat_cap_fff_curve.coefficient4y}")
+ fault_program.addLine('Set a3_AF_Qgr_h = 0')
+ fault_program.addLine("Set a1_AF_EIR_h = #{heat_eir_fff_curve.coefficient1Constant} + (#{heat_eir_fff_curve.coefficient2w}*#{var1_sensor.name}) + (#{heat_eir_fff_curve.coefficient3x}*#{var2_sensor.name}) + (#{heat_eir_fff_curve.coefficient5z}*#{var4_sensor.name})")
+ fault_program.addLine("Set a2_AF_EIR_h = #{heat_eir_fff_curve.coefficient4y}")
+ fault_program.addLine('Set a3_AF_EIR_h = 0')
+ end
qgr_values, p_values, ff_chg_values = get_installation_quality_heating_coeff(f_chg)
+ # charge defect impact
fault_program.addLine("Set a1_CH_Qgr_h = #{qgr_values[0]}")
fault_program.addLine("Set a2_CH_Qgr_h = #{qgr_values[1]}")
fault_program.addLine("Set a3_CH_Qgr_h = #{qgr_values[2]}")
@@ -3877,41 +3934,30 @@ def self.apply_installation_quality(model, heating_system, cooling_system, unita
fault_program.addLine("Set a2_CH_P_h = #{p_values[1]}")
fault_program.addLine("Set a3_CH_P_h = #{p_values[2]}")
- ff_ch_h = 1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_chg) * f_chg)
- fault_program.addLine("Set FF_CH_h = #{ff_ch_h.round(3)}")
-
fault_program.addLine('Set qh1_CH = a1_CH_Qgr_h')
fault_program.addLine("Set qh2_CH = a2_CH_Qgr_h*#{tout_sensor.name}")
fault_program.addLine('Set qh3_CH = a3_CH_Qgr_h*F_CH')
fault_program.addLine('Set Y_CH_Q_h = 1 + ((qh1_CH+(qh2_CH)+(qh3_CH))*F_CH)')
- fault_program.addLine('Set qh0_AF_CH = a1_AF_Qgr_h')
- fault_program.addLine('Set qh1_AF_CH = a2_AF_Qgr_h*FF_CH_h')
- fault_program.addLine('Set qh2_AF_CH = a3_AF_Qgr_h*FF_CH_h*FF_CH_h')
- fault_program.addLine('Set p_CH_Q_h = Y_CH_Q_h/(qh0_AF_CH + (qh1_AF_CH) +(qh2_AF_CH))')
-
fault_program.addLine('Set ph1_CH = a1_CH_P_h')
fault_program.addLine("Set ph2_CH = a2_CH_P_h*#{tout_sensor.name}")
fault_program.addLine('Set ph3_CH = a3_CH_P_h*F_CH')
fault_program.addLine('Set Y_CH_COP_h = Y_CH_Q_h/(1 + ((ph1_CH+(ph2_CH)+(ph3_CH))*F_CH))')
- fault_program.addLine('Set eirh0_AF_CH = a1_AF_EIR_h')
- fault_program.addLine('Set eirh1_AF_CH = a2_AF_EIR_h*FF_CH_h')
- fault_program.addLine('Set eirh2_AF_CH = a3_AF_EIR_h*FF_CH_h*FF_CH_h')
- fault_program.addLine('Set p_CH_COP_h = Y_CH_COP_h*(eirh0_AF_CH + (eirh1_AF_CH) + (eirh2_AF_CH))')
+ # air flow defect and charge defect combined to modify airflow curve output
+ ff_ch_h = 1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_chg) * f_chg)
+ fault_program.addLine("Set FF_CH_h = #{ff_ch_h.round(3)}")
fault_program.addLine("Set FF_AF_h = 1.0 + #{heat_airflow_rated_defect_ratio[speed].round(3)}")
fault_program.addLine('Set FF_AF_comb_h = FF_CH_h * FF_AF_h')
- fault_program.addLine('Set qh0_AF_comb = a1_AF_Qgr_h')
- fault_program.addLine('Set qh1_AF_comb = a2_AF_Qgr_h*FF_AF_comb_h')
- fault_program.addLine('Set qh2_AF_comb = a3_AF_Qgr_h*FF_AF_comb_h*FF_AF_comb_h')
- fault_program.addLine('Set p_AF_Q_h = qh0_AF_comb+(qh1_AF_comb)+(qh2_AF_comb)')
+ fault_program.addLine('Set qh_AF_CH = a1_AF_Qgr_h + (a2_AF_Qgr_h*FF_CH_h) + (a3_AF_Qgr_h*FF_CH_h*FF_CH_h)')
+ fault_program.addLine('Set eirh_AF_CH = a1_AF_EIR_h + (a2_AF_EIR_h*FF_CH_h) + (a3_AF_EIR_h*FF_CH_h*FF_CH_h)')
+ fault_program.addLine('Set p_CH_Q_h = Y_CH_Q_h / qh_AF_CH')
+ fault_program.addLine('Set p_CH_COP_h = Y_CH_COP_h * eirh_AF_CH')
- fault_program.addLine('Set eirh0_AF_comb = a1_AF_EIR_h')
- fault_program.addLine('Set eirh1_AF_comb = a2_AF_EIR_h*FF_AF_comb_h')
- fault_program.addLine('Set eirh2_AF_comb = a3_AF_EIR_h*FF_AF_comb_h*FF_AF_comb_h')
- fault_program.addLine('Set p_AF_COP_h = 1.0/(eirh0_AF_comb+(eirh1_AF_comb)+(eirh2_AF_comb))')
+ fault_program.addLine('Set p_AF_Q_h = a1_AF_Qgr_h + (a2_AF_Qgr_h*FF_AF_comb_h) + (a3_AF_Qgr_h*FF_AF_comb_h*FF_AF_comb_h)')
+ fault_program.addLine('Set p_AF_COP_h = 1.0 / ((a1_AF_EIR_h)+(a2_AF_EIR_h*FF_AF_comb_h)+(a3_AF_EIR_h*FF_AF_comb_h*FF_AF_comb_h))')
fault_program.addLine("Set #{heat_cap_fff_act.name} = (p_CH_Q_h * p_AF_Q_h)")
fault_program.addLine("Set #{heat_eir_fff_act.name} = 1.0 / (p_CH_COP_h * p_AF_COP_h)")
@@ -4151,6 +4197,7 @@ def self.get_hpxml_hvac_systems(hpxml)
if is_central_air_conditioner_and_furnace(hpxml, heating_system, heating_system.attached_cooling_system)
next # Already processed combined AC+furnace
end
+
hvac_systems << { cooling: nil,
heating: heating_system }
end
@@ -4205,4 +4252,44 @@ def self.get_dehumidifier_default_values(capacity)
return { rh_setpoint: rh_setpoint, ief: ief }
end
+
+ def self.get_default_hvac_efficiency_by_year_installed(year, hvac_type, fuel_type, units)
+ if [HPXML::HVACTypeWallFurnace, HPXML::HVACTypeFloorFurnace].include? hvac_type
+ # For wall/floor furnaces, map other fuel types to natural gas because the lookup table only provides efficiencies for natural gas.
+ fuel_type = HPXML::FuelTypeNaturalGas
+ end
+
+ type_id = { HPXML::HVACTypeCentralAirConditioner => 'split_dx',
+ HPXML::HVACTypeRoomAirConditioner => 'packaged_dx',
+ HPXML::HVACTypeHeatPumpAirToAir => 'heat_pump',
+ HPXML::HVACTypeFurnace => 'central_furnace',
+ HPXML::HVACTypeWallFurnace => 'wall_furnace',
+ HPXML::HVACTypeFloorFurnace => 'wall_furnace', # floor furnaces mapped to wall furnaces
+ HPXML::HVACTypeBoiler => 'boiler' }[hvac_type]
+
+ fuel_primary_id = { EPlus::FuelTypeElectricity => 'electric',
+ EPlus::FuelTypeNaturalGas => 'natural_gas',
+ EPlus::FuelTypeOil => 'fuel_oil',
+ EPlus::FuelTypeCoal => 'fuel_oil', # assumption
+ EPlus::FuelTypeWoodCord => 'fuel_oil', # assumption
+ EPlus::FuelTypeWoodPellets => 'fuel_oil', # assumption
+ EPlus::FuelTypePropane => 'lpg' }[EPlus.fuel_type(fuel_type)]
+
+ metric_id = units.downcase
+ value = nil
+ lookup_year = 0
+ CSV.foreach(File.join(File.dirname(__FILE__), 'lu_hvac_equipment_efficiency.csv'), headers: true) do |row|
+ next unless row['type_id'] == type_id
+ next unless row['fuel_primary_id'] == fuel_primary_id
+ next unless row['metric_id'] == metric_id
+
+ row_year = Integer(row['year'])
+ if (row_year - year).abs <= (lookup_year - year).abs
+ lookup_year = row_year
+ value = Float(row['value'])
+ end
+ end
+
+ return value
+ end
end
diff --git a/HPXMLtoOpenStudio/resources/hvac_sizing.rb b/HPXMLtoOpenStudio/resources/hvac_sizing.rb
index 157d7189c1..1ef225e803 100644
--- a/HPXMLtoOpenStudio/resources/hvac_sizing.rb
+++ b/HPXMLtoOpenStudio/resources/hvac_sizing.rb
@@ -1554,7 +1554,6 @@ def self.apply_hvac_equipment_adjustments(hvac_sizing_values, weather, hvac, cfa
elsif hvac.HeatType == HPXML::HVACTypeHeatPumpGroundToAir
if hvac_sizing_values.Cool_Capacity > 0
- coil_bf = gshp_coil_bf
hvac_sizing_values.Heat_Capacity = hvac_sizing_values.Heat_Load
hvac_sizing_values.Heat_Capacity_Supp = hvac_sizing_values.Heat_Load
@@ -1571,7 +1570,7 @@ def self.apply_hvac_equipment_adjustments(hvac_sizing_values, weather, hvac, cfa
hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
- (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
+ (1.0 + (1.0 - gshp_coil_bf * bypassFactor_CurveValue) *
(80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
else
@@ -1651,180 +1650,168 @@ def self.apply_hvac_installation_quality(hvac_sizing_values, weather, hvac)
tout_cool = UnitConversions.convert(weather.design.CoolingDrybulb, 'F', 'C')
tout_heat = UnitConversions.convert(weather.design.HeatingDrybulb, 'F', 'C')
- if hvac.CoolType == HPXML::HVACTypeHeatPumpGroundToAir
- if hvac.CoolingLoadFraction > 0
- # Cooling
- coil_bf = gshp_coil_bf
- # Calculate curve point w/ and w/o defect ratios
- design_wb_temp = UnitConversions.convert(@wetbulb_indoor_cooling, 'f', 'k')
- design_db_temp = UnitConversions.convert(@cool_setpoint, 'f', 'k')
- design_w_temp = UnitConversions.convert(hvac.GSHP_design_chw, 'f', 'k')
- design_vfr_air = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
- design_vfr_air_defect = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s') * (1 + hvac.AirflowDefectRatioCooling)
- # calculate water flow based on current capacity.
- loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
- loop_flow_m3s = UnitConversions.convert(loop_flow, 'gal/min', 'm^3/s')
-
- totalCap_CurveValue, sensibleCap_CurveValue = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, design_vfr_air, loop_flow_m3s)
- totalCap_CurveValue_d, sensibleCap_CurveValue_d = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, design_vfr_air_defect, loop_flow_m3s)
-
- cap_clg_ratio = 1 / (totalCap_CurveValue_d / totalCap_CurveValue)
- if cap_clg_ratio > 1
- hvac_sizing_values.Cool_Capacity *= cap_clg_ratio
- hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
- bypassFactor_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, @cool_setpoint, gshp_coil_bf_ft_spec)
+ f_ch = hvac.ChargeDefectRatio.round(3)
- cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
- (1.0 + (1.0 - coil_bf * bypassFactor_CurveValue) *
- (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
- hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
- end
- end
-
- # Heating
- if hvac.HeatingLoadFraction > 0
- # Calculate curve point w/ and w/o defect ratios
- design_db_temp = UnitConversions.convert(@heat_setpoint, 'f', 'k')
- design_w_temp = UnitConversions.convert(hvac.GSHP_design_chw, 'f', 'k')
- design_vfr_air = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s')
- design_vfr_air_defect = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s') * (1 + hvac.AirflowDefectRatioHeating)
- # calculate water flow based on current capacity.
- loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
- loop_flow_m3s = UnitConversions.convert(loop_flow, 'gal/min', 'm^3/s')
-
- totalCap_CurveValue = calc_gshp_htg_curve_value(hvac, design_db_temp, design_w_temp, design_vfr_air, loop_flow_m3s)
- totalCap_CurveValue_d = calc_gshp_htg_curve_value(hvac, design_db_temp, design_w_temp, design_vfr_air_defect, loop_flow_m3s)
+ # Cooling
+ if [HPXML::HVACTypeHeatPumpAirToAir,
+ HPXML::HVACTypeCentralAirConditioner,
+ HPXML::HVACTypeHeatPumpMiniSplit,
+ HPXML::HVACTypeMiniSplitAirConditioner,
+ HPXML::HVACTypeHeatPumpGroundToAir].include?(hvac.CoolType) && hvac.CoolingLoadFraction > 0
- cap_htg_ratio = 1 / (totalCap_CurveValue_d / totalCap_CurveValue)
- if cap_htg_ratio > 1
- hvac_sizing_values.Heat_Capacity *= cap_htg_ratio
- hvac_sizing_values.Heat_Airflow = calc_airflow_rate(hvac_sizing_values.Heat_Capacity, (hvac.SupplyAirTemp - @heat_setpoint))
- end
- end
- else
- f_ch = hvac.ChargeDefectRatio.round(3)
-
- # Cooling
- if [HPXML::HVACTypeHeatPumpAirToAir,
- HPXML::HVACTypeCentralAirConditioner,
- HPXML::HVACTypeHeatPumpMiniSplit,
- HPXML::HVACTypeMiniSplitAirConditioner].include?(hvac.CoolType) && hvac.CoolingLoadFraction > 0
- cool_airflow_rated_defect_ratio = []
- cool_airflow_rated_ratio = []
- cool_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
+ cool_airflow_rated_defect_ratio = []
+ cool_airflow_rated_ratio = []
+ cool_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s')
+ if hvac.CoolType != HPXML::HVACTypeHeatPumpGroundToAir
for speed in 0..(hvac.NumSpeedsCooling - 1)
cool_airflow_rated_ratio << cool_cfm_m3s / HVAC.calc_rated_airflow(hvac_sizing_values.Cool_Capacity, hvac.RatedCFMperTonCooling[speed], hvac.CapacityRatioCooling[speed])
cool_airflow_rated_defect_ratio << cool_cfm_m3s * (1 + hvac.AirflowDefectRatioCooling) / HVAC.calc_rated_airflow(hvac_sizing_values.Cool_Capacity, hvac.RatedCFMperTonCooling[speed], hvac.CapacityRatioCooling[speed])
end
- if not cool_airflow_rated_defect_ratio.empty?
- cap_clg_ratios = []
- for speed in 0..(hvac.NumSpeedsCooling - 1)
- # NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
+ else
+ cool_airflow_rated_ratio = [1.0] # actual air flow is equal to rated (before applying defect ratio) in current methodology
+ cool_airflow_rated_defect_ratio = [1 + hvac.AirflowDefectRatioCooling]
+ end
+ if not cool_airflow_rated_defect_ratio.empty?
+ cap_clg_ratios = []
+ for speed in 0..(hvac.NumSpeedsCooling - 1)
+ # NOTE: heat pump (cooling) curves don't exhibit expected trends at extreme faults;
+ if hvac.CoolType != HPXML::HVACTypeHeatPumpGroundToAir
a1_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][0]
a2_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][1]
a3_AF_Qgr_c = hvac.COOL_CAP_FFLOW_SPEC[speed][2]
+ else
+ a1_AF_Qgr_c = 1 - hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][3]
+ a2_AF_Qgr_c = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][3]
+ a3_AF_Qgr_c = 0
+ end
- p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_cooling_coeff(f_ch)
+ p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_cooling_coeff(f_ch)
- a1_CH_Qgr_c = qgr_values[0]
- a2_CH_Qgr_c = qgr_values[1]
- a3_CH_Qgr_c = qgr_values[2]
- a4_CH_Qgr_c = qgr_values[3]
+ a1_CH_Qgr_c = qgr_values[0]
+ a2_CH_Qgr_c = qgr_values[1]
+ a3_CH_Qgr_c = qgr_values[2]
+ a4_CH_Qgr_c = qgr_values[3]
- ff_ch_c = (1.0 / (1.0 + (qgr_values[0] + (qgr_values[1] * ff_chg_values[0]) + (qgr_values[2] * ff_chg_values[1]) + (qgr_values[3] * f_ch)) * f_ch)).round(3)
+ q0_CH = a1_CH_Qgr_c
+ q1_CH = a2_CH_Qgr_c * tin_cool
+ q2_CH = a3_CH_Qgr_c * tout_cool
+ q3_CH = a4_CH_Qgr_c * f_ch
+ y_CH_Q_c = 1 + ((q0_CH + q1_CH + q2_CH + q3_CH) * f_ch)
- q0_CH = a1_CH_Qgr_c
- q1_CH = a2_CH_Qgr_c * tin_cool
- q2_CH = a3_CH_Qgr_c * tout_cool
- q3_CH = a4_CH_Qgr_c * f_ch
- y_CH_Q_c = 1 + ((q0_CH + q1_CH + q2_CH + q3_CH) * f_ch)
+ ff_ch_c = (1.0 / (1.0 + (qgr_values[0] + (qgr_values[1] * ff_chg_values[0]) + (qgr_values[2] * ff_chg_values[1]) + (qgr_values[3] * f_ch)) * f_ch)).round(3)
+ ff_AF_c = cool_airflow_rated_defect_ratio[speed].round(3)
+ ff_AF_comb_c = ff_ch_c * ff_AF_c
- q0_AF_CH = a1_AF_Qgr_c
- q1_AF_CH = a2_AF_Qgr_c * ff_ch_c
- q2_AF_CH = a3_AF_Qgr_c * ff_ch_c * ff_ch_c
- p_CH_Q_c = y_CH_Q_c / (q0_AF_CH + q1_AF_CH + q2_AF_CH)
+ q_AF_CH = a1_AF_Qgr_c + (a2_AF_Qgr_c * ff_ch_c) + (a3_AF_Qgr_c * ff_ch_c * ff_ch_c)
+ p_CH_Q_c = y_CH_Q_c / q_AF_CH
- ff_AF_c = cool_airflow_rated_defect_ratio[speed].round(3)
- ff_AF_c_nodefect = cool_airflow_rated_ratio[speed].round(3)
- ff_AF_comb_c = ff_ch_c * ff_AF_c
+ p_AF_Q_c = a1_AF_Qgr_c + (a2_AF_Qgr_c * ff_AF_comb_c) + (a3_AF_Qgr_c * ff_AF_comb_c * ff_AF_comb_c)
- q0_AF_comb = a1_AF_Qgr_c
- q1_AF_comb = a2_AF_Qgr_c * ff_AF_comb_c
- q2_AF_comb = a3_AF_Qgr_c * ff_AF_comb_c * ff_AF_comb_c
- p_AF_Q_c = q0_AF_comb + q1_AF_comb + q2_AF_comb
+ cool_cap_fff = (p_CH_Q_c * p_AF_Q_c)
- cool_cap_fff = (p_CH_Q_c * p_AF_Q_c)
+ # calculate the capacity impact by defects
+ ff_AF_c_nodefect = cool_airflow_rated_ratio[speed].round(3)
+ if hvac.CoolType != HPXML::HVACTypeHeatPumpGroundToAir
cool_cap_fff_nodefect = a1_AF_Qgr_c + a2_AF_Qgr_c * ff_AF_c_nodefect + a3_AF_Qgr_c * ff_AF_c_nodefect * ff_AF_c_nodefect
- cap_clg_ratio = 1 / (cool_cap_fff / cool_cap_fff_nodefect)
- cap_clg_ratios << cap_clg_ratio
+ else
+ cool_cap_fff_nodefect = 1
end
- prev_capacity = hvac_sizing_values.Cool_Capacity
- hvac_sizing_values.Cool_Capacity *= cap_clg_ratios.max
- hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
+ cap_clg_ratio = 1 / (cool_cap_fff / cool_cap_fff_nodefect)
+ cap_clg_ratios << cap_clg_ratio
+ end
+
+ prev_capacity = hvac_sizing_values.Cool_Capacity
+ hvac_sizing_values.Cool_Capacity *= cap_clg_ratios.max
+ hvac_sizing_values.Cool_Capacity_Sens = hvac_sizing_values.Cool_Capacity * hvac.SHRRated[hvac.SizingSpeed]
+ if hvac.CoolType != HPXML::HVACTypeHeatPumpGroundToAir
if prev_capacity > 0 # Preserve cfm/ton
hvac_sizing_values.Cool_Airflow = hvac_sizing_values.Cool_Airflow * hvac_sizing_values.Cool_Capacity / prev_capacity
else
hvac_sizing_values.Cool_Airflow = 0.0
end
+ else
+ design_wb_temp = UnitConversions.convert(@wetbulb_indoor_cooling, 'f', 'k')
+ design_db_temp = UnitConversions.convert(@cool_setpoint, 'f', 'k')
+ design_w_temp = UnitConversions.convert(hvac.GSHP_design_chw, 'f', 'k')
+ # calculate water flow based on current capacity.
+ loop_flow = [1.0, UnitConversions.convert([hvac_sizing_values.Heat_Capacity, hvac_sizing_values.Cool_Capacity].max, 'Btu/hr', 'ton')].max.floor * 3.0
+ sensibleCap_CurveValue = calc_gshp_clg_curve_value(hvac, design_wb_temp, design_db_temp, design_w_temp, UnitConversions.convert(hvac_sizing_values.Cool_Airflow, 'cfm', 'm^3/s'), UnitConversions.convert(loop_flow, 'gal/min', 'm^3/s'))[1]
+ bypassFactor_CurveValue = MathTools.biquadratic(@wetbulb_indoor_cooling, @cool_setpoint, gshp_coil_bf_ft_spec)
+ cool_Load_SensCap_Design = (hvac_sizing_values.Cool_Capacity_Sens * sensibleCap_CurveValue /
+ (1.0 + (1.0 - gshp_coil_bf * bypassFactor_CurveValue) *
+ (80.0 - @cool_setpoint) / (@cool_setpoint - hvac.LeavingAirTemp)))
+ hvac_sizing_values.Cool_Airflow = calc_airflow_rate(cool_Load_SensCap_Design, (@cool_setpoint - hvac.LeavingAirTemp))
end
end
+ end
- # Heating
- if [HPXML::HVACTypeHeatPumpAirToAir,
- HPXML::HVACTypeHeatPumpMiniSplit].include?(hvac.HeatType) && hvac.HeatingLoadFraction > 0
- heat_airflow_rated_defect_ratio = []
- heat_airflow_rated_ratio = []
- heat_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s')
+ # Heating
+ if [HPXML::HVACTypeHeatPumpAirToAir,
+ HPXML::HVACTypeHeatPumpMiniSplit,
+ HPXML::HVACTypeHeatPumpGroundToAir].include?(hvac.HeatType) && hvac.HeatingLoadFraction > 0
+ heat_airflow_rated_defect_ratio = []
+ heat_airflow_rated_ratio = []
+ heat_cfm_m3s = UnitConversions.convert(hvac_sizing_values.Heat_Airflow, 'cfm', 'm^3/s')
+ if hvac.HeatType != HPXML::HVACTypeHeatPumpGroundToAir
for speed in 0..(hvac.NumSpeedsHeating - 1)
heat_airflow_rated_ratio << heat_cfm_m3s / HVAC.calc_rated_airflow(hvac_sizing_values.Heat_Capacity, hvac.RatedCFMperTonHeating[speed], hvac.CapacityRatioHeating[speed])
heat_airflow_rated_defect_ratio << heat_cfm_m3s * (1 + hvac.AirflowDefectRatioHeating) / HVAC.calc_rated_airflow(hvac_sizing_values.Heat_Capacity, hvac.RatedCFMperTonHeating[speed], hvac.CapacityRatioHeating[speed])
end
- if not heat_airflow_rated_defect_ratio.empty?
- cap_htg_ratios = []
- for speed in 0..(hvac.NumSpeedsHeating - 1)
+ else
+ heat_airflow_rated_ratio = [1.0] # actual air flow is equal to rated (before applying defect ratio) in current methodology
+ heat_airflow_rated_defect_ratio = [1 + hvac.AirflowDefectRatioHeating]
+ end
+ if not heat_airflow_rated_defect_ratio.empty?
+ cap_htg_ratios = []
+ for speed in 0..(hvac.NumSpeedsHeating - 1)
+ if hvac.HeatType != HPXML::HVACTypeHeatPumpGroundToAir
a1_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][0]
a2_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][1]
a3_AF_Qgr_h = hvac.HEAT_CAP_FFLOW_SPEC[speed][2]
+ else
+ a1_AF_Qgr_h = 1 - hvac.HEAT_CAP_CURVE_SPEC[hvac.SizingSpeed][3]
+ a2_AF_Qgr_h = hvac.HEAT_CAP_CURVE_SPEC[hvac.SizingSpeed][3]
+ a3_AF_Qgr_h = 0
+ end
- p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_heating_coeff(f_ch)
+ p_values, qgr_values, ff_chg_values = HVAC.get_installation_quality_heating_coeff(f_ch)
- a1_CH_Qgr_h = qgr_values[0]
- a2_CH_Qgr_h = qgr_values[1]
- a3_CH_Qgr_h = qgr_values[2]
+ a1_CH_Qgr_h = qgr_values[0]
+ a2_CH_Qgr_h = qgr_values[1]
+ a3_CH_Qgr_h = qgr_values[2]
- ff_ch_h = (1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_ch) * f_ch)).round(3)
+ qh1_CH = a1_CH_Qgr_h
+ qh2_CH = a2_CH_Qgr_h * tout_heat
+ qh3_CH = a3_CH_Qgr_h * f_ch
+ y_CH_Q_h = 1 + ((qh1_CH + qh2_CH + qh3_CH) * f_ch)
- qh1_CH = a1_CH_Qgr_h
- qh2_CH = a2_CH_Qgr_h * tout_heat
- qh3_CH = a3_CH_Qgr_h * f_ch
- y_CH_Q_h = 1 + ((qh1_CH + qh2_CH + qh3_CH) * f_ch)
+ ff_ch_h = (1 / (1 + (qgr_values[0] + qgr_values[1] * ff_chg_values[0] + qgr_values[2] * f_ch) * f_ch)).round(3)
+ ff_AF_h = heat_airflow_rated_defect_ratio[speed].round(3)
+ ff_AF_comb_h = ff_ch_h * ff_AF_h
- qh0_AF_CH = a1_AF_Qgr_h
- qh1_AF_CH = a2_AF_Qgr_h * ff_ch_h
- qh2_AF_CH = a3_AF_Qgr_h * ff_ch_h * ff_ch_h
- p_CH_Q_h = y_CH_Q_h / (qh0_AF_CH + qh1_AF_CH + qh2_AF_CH)
+ qh_AF_CH = a1_AF_Qgr_h + (a2_AF_Qgr_h * ff_ch_h) + (a3_AF_Qgr_h * ff_ch_h * ff_ch_h)
+ p_CH_Q_h = y_CH_Q_h / qh_AF_CH
- ff_AF_h = heat_airflow_rated_defect_ratio[speed].round(3)
- ff_AF_h_nodefect = heat_airflow_rated_ratio[speed].round(3)
- ff_AF_comb_h = ff_ch_h * ff_AF_h
+ p_AF_Q_h = a1_AF_Qgr_h + (a2_AF_Qgr_h * ff_AF_comb_h) + (a3_AF_Qgr_h * ff_AF_comb_h * ff_AF_comb_h)
- qh0_AF_comb = a1_AF_Qgr_h
- qh1_AF_comb = a2_AF_Qgr_h * ff_AF_comb_h
- qh2_AF_comb = a3_AF_Qgr_h * ff_AF_comb_h * ff_AF_comb_h
- p_AF_Q_h = qh0_AF_comb + qh1_AF_comb + qh2_AF_comb
+ heat_cap_fff = (p_CH_Q_h * p_AF_Q_h)
- heat_cap_fff = (p_CH_Q_h * p_AF_Q_h)
+ # calculate the capacity impact by defects
+ ff_AF_h_nodefect = heat_airflow_rated_ratio[speed].round(3)
+ if hvac.HeatType != HPXML::HVACTypeHeatPumpGroundToAir
heat_cap_fff_nodefect = a1_AF_Qgr_h + a2_AF_Qgr_h * ff_AF_h_nodefect + a3_AF_Qgr_h * ff_AF_h_nodefect * ff_AF_h_nodefect
- cap_htg_ratio = 1 / (heat_cap_fff / heat_cap_fff_nodefect)
- cap_htg_ratios << cap_htg_ratio
- end
- prev_capacity = hvac_sizing_values.Heat_Capacity
- hvac_sizing_values.Heat_Capacity *= cap_htg_ratios.max
- if prev_capacity > 0 # Preserve cfm/ton
- hvac_sizing_values.Heat_Airflow = hvac_sizing_values.Heat_Airflow * hvac_sizing_values.Heat_Capacity / prev_capacity
else
- hvac_sizing_values.Heat_Airflow = 0.0
+ heat_cap_fff_nodefect = 1
end
+ cap_htg_ratio = 1 / (heat_cap_fff / heat_cap_fff_nodefect)
+ cap_htg_ratios << cap_htg_ratio
+ end
+ prev_capacity = hvac_sizing_values.Heat_Capacity
+ hvac_sizing_values.Heat_Capacity *= cap_htg_ratios.max
+ if prev_capacity > 0 # Preserve cfm/ton
+ hvac_sizing_values.Heat_Airflow = hvac_sizing_values.Heat_Airflow * hvac_sizing_values.Heat_Capacity / prev_capacity
+ else
+ hvac_sizing_values.Heat_Airflow = 0.0
end
end
end
@@ -2059,24 +2046,29 @@ def self.calc_airflow_rate(load_or_capacity, deltaT)
return load_or_capacity / (1.1 * @acf * deltaT)
end
- def self.calc_gshp_clg_curve_value(hvac, wb_temp, db_temp, w_temp, vfr_air, loop_flow)
+ def self.calc_gshp_clg_curve_value(hvac, wb_temp, db_temp, w_temp, vfr_air, loop_flow = nil, rated_vfr_air = nil)
# Reference conditions in thesis with largest capacity:
# See Appendix B Figure B.3 of https://hvac.okstate.edu/sites/default/files/pubs/theses/MS/27-Tang_Thesis_05.pdf
ref_temp = 283 # K
- ref_vfr_air = UnitConversions.convert(1200, 'cfm', 'm^3/s')
+ if rated_vfr_air.nil?
+ # rated volume flow rate used to fit the curve
+ ref_vfr_air = UnitConversions.convert(1200, 'cfm', 'm^3/s')
+ else
+ ref_vfr_air = UnitConversions.convert(rated_vfr_air, 'cfm', 'm^3/s')
+ end
ref_vfr_water = 0.000284
- a_1 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][0]
- a_2 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][1]
- a_3 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][2]
- a_4 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][3]
- a_5 = hvac.COOL_CAP_FT_SPEC[hvac.SizingSpeed][4]
- b_1 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][0]
- b_2 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][1]
- b_3 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][2]
- b_4 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][3]
- b_5 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][4]
- b_6 = hvac.COOL_SH_FT_SPEC[hvac.SizingSpeed][5]
+ a_1 = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][0]
+ a_2 = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][1]
+ a_3 = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][2]
+ a_4 = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][3]
+ a_5 = hvac.COOL_CAP_CURVE_SPEC[hvac.SizingSpeed][4]
+ b_1 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][0]
+ b_2 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][1]
+ b_3 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][2]
+ b_4 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][3]
+ b_5 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][4]
+ b_6 = hvac.COOL_SH_CURVE_SPEC[hvac.SizingSpeed][5]
if not loop_flow.nil?
totalCap_CurveValue = a_1 + wb_temp / ref_temp * a_2 + w_temp / ref_temp * a_3 + vfr_air / ref_vfr_air * a_4 + loop_flow / ref_vfr_water * a_5
@@ -2405,6 +2397,15 @@ def self.get_hvac_information(hvac_system)
if hpxml_hvac_ap.respond_to? :heat_cap_fflow_spec
hvac.HEAT_CAP_FFLOW_SPEC = hpxml_hvac_ap.heat_cap_fflow_spec
end
+ if hpxml_hvac_ap.respond_to? :cool_cap_curve_spec
+ hvac.COOL_CAP_CURVE_SPEC = hpxml_hvac_ap.cool_cap_curve_spec
+ end
+ if hpxml_hvac_ap.respond_to? :cool_sh_curve_spec
+ hvac.COOL_SH_CURVE_SPEC = hpxml_hvac_ap.cool_sh_curve_spec
+ end
+ if hpxml_hvac_ap.respond_to? :heat_cap_curve_spec
+ hvac.HEAT_CAP_CURVE_SPEC = hpxml_hvac_ap.heat_cap_curve_spec
+ end
# WLHP
if hpxml_hvac.respond_to? :heating_efficiency_cop
@@ -2442,6 +2443,7 @@ def self.get_hvac_information(hvac_system)
# FUTURE: Consolidate w/ ducts code in measure.rb
hvac.Ducts = []
next unless not hpxml_hvac.distribution_system.nil?
+
lto = { supply_percent: nil, supply_cfm25: nil, return_percent: nil, return_cfm25: nil }
hpxml_hvac.distribution_system.duct_leakage_measurements.each do |m|
next unless m.duct_leakage_total_or_to_outside == 'to outside'
@@ -2491,6 +2493,7 @@ def self.get_hvac_information(hvac_system)
hvac.Ducts << d
end
next unless (lto[:return_percent].to_f + lto[:return_cfm25].to_f) > 0 && total_uncond_return_area == 0
+
d = DuctInfo.new
d.Side = HPXML::DuctTypeReturn
d.Location = HPXML::LocationOutside
@@ -3372,6 +3375,7 @@ def initialize
:RatedCFMperTonCooling, :RatedCFMperTonHeating, :ChargeDefectRatio,
:COOL_CAP_FT_SPEC, :HEAT_CAP_FT_SPEC, :COOL_SH_FT_SPEC,
:COOL_CAP_FFLOW_SPEC, :HEAT_CAP_FFLOW_SPEC,
+ :COOL_CAP_CURVE_SPEC, :COOL_SH_CURVE_SPEC, :HEAT_CAP_CURVE_SPEC,
:SHRRated, :CapacityRatioCooling, :CapacityRatioHeating,
:OverSizeLimit, :OverSizeDelta,
:HeatingEIR, :CoolingEIR, :SizingSpeed, :HeatingCOP,
diff --git a/HPXMLtoOpenStudio/resources/lu_hvac_equipment_efficiency.csv b/HPXMLtoOpenStudio/resources/lu_hvac_equipment_efficiency.csv
new file mode 100644
index 0000000000..7d148573d0
--- /dev/null
+++ b/HPXMLtoOpenStudio/resources/lu_hvac_equipment_efficiency.csv
@@ -0,0 +1,493 @@
+year,performance_id,category_id,type_id,region_id,fuel_primary_id,metric_id,units_id,value
+1970,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1971,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1972,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1973,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1974,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1975,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1976,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1977,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1978,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1979,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1980,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1981,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1982,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1983,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1984,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1985,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1986,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1987,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1988,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1989,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1990,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1991,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1992,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1993,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.05
+1994,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9
+1995,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.03
+1996,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.08
+1997,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.09
+1998,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.08
+1999,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.07
+2000,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.3
+2001,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.63
+2002,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.75
+2003,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.75
+2004,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.71
+2005,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.95
+2006,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,10.02
+2007,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.81
+2008,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.93
+2009,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.93
+2010,shipment_weighted,cooling,packaged_dx,,electric,eer,btu/wh,9.93
+1970,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1971,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1972,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1973,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1974,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1975,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1976,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1977,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1978,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1979,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1980,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1981,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8
+1982,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.31
+1983,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.43
+1984,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.66
+1985,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.82
+1986,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.87
+1987,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,8.97
+1988,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,9.11
+1989,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,9.25
+1990,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,9.31
+1991,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,9.49
+1992,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.46
+1993,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.56
+1994,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.61
+1995,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.68
+1996,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.68
+1997,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.66
+1998,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.92
+1999,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.96
+2000,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,10.95
+2001,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,11.07
+2002,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,11.07
+2003,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,11.19
+2004,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,11.29
+2005,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,11.32
+2006,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,13.17
+2007,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,13.66
+2008,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,13.76
+2009,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,13.76
+2010,shipment_weighted,cooling,split_dx,,electric,seer,btu/wh,13.76
+1970,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1971,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1972,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1973,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1974,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1975,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1976,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1977,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1978,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1979,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1980,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1981,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1982,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1983,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1984,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1985,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1986,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1987,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9
+1988,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9.13
+1989,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9.26
+1990,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9.46
+1991,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,9.77
+1992,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,10.6
+1993,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,10.86
+1994,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,10.94
+1995,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,10.97
+1996,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11
+1997,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,10.97
+1998,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.29
+1999,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.29
+2000,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.21
+2001,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.3
+2002,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.31
+2003,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.46
+2004,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.56
+2005,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,11.6
+2006,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,13.17
+2007,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,13.66
+2008,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,13.76
+2009,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,13.76
+2010,shipment_weighted,cooling,heat_pump,,electric,seer,btu/wh,13.76
+1970,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1971,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1972,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1973,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1974,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1975,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1976,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1977,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1978,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1979,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1980,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1981,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1982,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1983,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.72
+1984,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.726
+1985,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.729
+1986,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.737
+1987,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.743
+1988,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.749
+1989,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.747
+1990,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.767
+1991,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.775
+1992,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.821
+1993,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.824
+1994,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.824
+1995,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.823
+1996,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.827
+1997,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.829
+1998,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.826
+1999,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.826
+2000,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.826
+2001,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.831
+2002,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.831
+2003,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.835
+2004,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.836
+2005,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.839
+2006,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.84
+2007,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.841
+2008,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.848
+2009,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.848
+2010,shipment_weighted,heating,central_furnace,,natural_gas,afue,btu/btu,0.848
+1970,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1971,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1972,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1973,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1974,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1975,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1976,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1977,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1978,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1979,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1980,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1981,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1982,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1983,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1984,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1985,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1986,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1987,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1988,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1989,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1990,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1991,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1992,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1993,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1994,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1995,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1996,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1997,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1998,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1999,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2000,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2001,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2002,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2003,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2004,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2005,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2006,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2007,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2008,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2009,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+2010,shipment_weighted,heating,central_furnace,,electric,afue,btu/btu,0.98
+1970,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.72
+1971,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.72
+1972,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.736
+1973,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.736
+1974,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.736
+1975,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.736
+1976,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.741
+1977,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.745
+1978,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.75
+1979,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.755
+1980,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.76
+1981,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.768
+1982,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.775
+1983,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.783
+1984,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.786
+1985,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.786
+1986,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.796
+1987,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.798
+1988,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.804
+1989,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.804
+1990,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.803
+1991,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.808
+1992,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.808
+1993,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1994,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1995,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1996,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1997,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1998,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1999,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2000,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2001,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2002,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2003,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2004,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2005,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2006,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2007,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2008,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2009,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+2010,shipment_weighted,heating,central_furnace,,fuel_oil,afue,btu/btu,0.809
+1970,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1971,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1972,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1973,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1974,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1975,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1976,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1977,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1978,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1979,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1980,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1981,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1982,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1983,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.72
+1984,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.73
+1985,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.738
+1986,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.743
+1987,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.751
+1988,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.758
+1989,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.755
+1990,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.757
+1991,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.769
+1992,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.832
+1993,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.838
+1994,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.839
+1995,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+1996,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+1997,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+1998,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+1999,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2000,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2001,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2002,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2003,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2004,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2005,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2006,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2007,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2008,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2009,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+2010,shipment_weighted,heating,central_furnace,,lpg,afue,btu/btu,0.841
+1970,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.5
+1971,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.548
+1972,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1973,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1974,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1975,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1976,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1977,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1978,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1979,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1980,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.595
+1981,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.631
+1982,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.631
+1983,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.631
+1984,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.631
+1985,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.631
+1986,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.642
+1987,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.642
+1988,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.642
+1989,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1990,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1991,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1992,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1993,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1994,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1995,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1996,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1997,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1998,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1999,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2000,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2001,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2002,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2003,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2004,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2005,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2006,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2007,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2008,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2009,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+2010,shipment_weighted,heating,wall_furnace,,natural_gas,afue,btu/btu,0.656
+1970,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.7
+1971,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.712
+1972,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1973,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1974,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1975,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1976,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1977,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1978,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1979,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1980,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.723
+1981,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.774
+1982,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.774
+1983,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.774
+1984,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.774
+1985,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.774
+1986,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.782
+1987,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.782
+1988,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.782
+1989,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1990,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1991,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1992,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1993,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1994,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1995,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1996,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1997,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1998,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1999,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2000,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2001,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2002,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2003,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2004,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2005,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2006,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2007,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2008,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2009,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+2010,shipment_weighted,heating,boiler,,natural_gas,afue,btu/btu,0.797
+1970,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.72
+1971,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.736
+1972,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1973,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1974,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1975,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1976,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1977,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1978,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1979,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1980,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.752
+1981,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.774
+1982,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.774
+1983,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.774
+1984,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.774
+1985,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.774
+1986,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.816
+1987,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.816
+1988,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.816
+1989,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1990,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1991,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1992,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1993,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1994,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1995,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1996,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1997,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1998,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1999,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2000,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2001,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2002,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2003,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2004,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2005,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2006,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2007,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2008,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2009,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+2010,shipment_weighted,heating,boiler,,fuel_oil,afue,btu/btu,0.831
+1970,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.72
+1971,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.736
+1972,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1973,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1974,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1975,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1976,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1977,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1978,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1979,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1980,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.752
+1981,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.774
+1982,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.774
+1983,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.774
+1984,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.774
+1985,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.774
+1986,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.816
+1987,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.816
+1988,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.816
+1989,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1990,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1991,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1992,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1993,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1994,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1995,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1996,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1997,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1998,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1999,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2000,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2001,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2002,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2003,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2004,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2005,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2006,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2007,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2008,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2009,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+2010,shipment_weighted,heating,boiler,,lpg,afue,btu/btu,0.831
+1970,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1971,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1972,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1973,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1974,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1975,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1976,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1977,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1978,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1979,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1980,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1981,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1982,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1983,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1984,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1985,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.5
+1986,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.55
+1987,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.71
+1988,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.88
+1989,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,6.92
+1990,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.03
+1991,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.06
+1992,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.1
+1993,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.1
+1994,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.1
+1995,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.1
+1996,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+1997,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.1
+1998,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+1999,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2000,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2001,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2002,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2003,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2004,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2005,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.4
+2006,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.9
+2007,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.9
+2008,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.9
+2009,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.9
+2010,shipment_weighted,heating,heat_pump,,electric,hspf,btu/wh,7.9
diff --git a/HPXMLtoOpenStudio/resources/lu_water_heater_efficiency.csv b/HPXMLtoOpenStudio/resources/lu_water_heater_efficiency.csv
new file mode 100644
index 0000000000..30933e665e
--- /dev/null
+++ b/HPXMLtoOpenStudio/resources/lu_water_heater_efficiency.csv
@@ -0,0 +1,157 @@
+year,performance_id,type_id,fuel_primary_id,metric_id,units_id,value
+1972,shipment_weighted,storage,electric,EF,none,0.798
+1973,shipment_weighted,storage,electric,EF,none,0.798
+1974,shipment_weighted,storage,electric,EF,none,0.798
+1975,shipment_weighted,storage,electric,EF,none,0.798
+1976,shipment_weighted,storage,electric,EF,none,0.799
+1977,shipment_weighted,storage,electric,EF,none,0.799
+1978,shipment_weighted,storage,electric,EF,none,0.8
+1979,shipment_weighted,storage,electric,EF,none,0.801
+1980,shipment_weighted,storage,electric,EF,none,0.802
+1981,shipment_weighted,storage,electric,EF,none,0.803
+1982,shipment_weighted,storage,electric,EF,none,0.804
+1983,shipment_weighted,storage,electric,EF,none,0.806
+1984,shipment_weighted,storage,electric,EF,none,0.809
+1985,shipment_weighted,storage,electric,EF,none,0.812
+1986,shipment_weighted,storage,electric,EF,none,0.815
+1987,shipment_weighted,storage,electric,EF,none,0.819
+1988,shipment_weighted,storage,electric,EF,none,0.823
+1989,shipment_weighted,storage,electric,EF,none,0.828
+1990,shipment_weighted,storage,electric,EF,none,0.832
+1991,shipment_weighted,storage,electric,EF,none,0.837
+1992,shipment_weighted,storage,electric,EF,none,0.842
+1993,shipment_weighted,storage,electric,EF,none,0.846
+1994,shipment_weighted,storage,electric,EF,none,0.85
+1995,shipment_weighted,storage,electric,EF,none,0.854
+1996,shipment_weighted,storage,electric,EF,none,0.857
+1997,shipment_weighted,storage,electric,EF,none,0.857
+1998,shipment_weighted,storage,electric,EF,none,0.857
+1999,shipment_weighted,storage,electric,EF,none,0.857
+2000,shipment_weighted,storage,electric,EF,none,0.857
+2001,shipment_weighted,storage,electric,EF,none,0.857
+2002,shipment_weighted,storage,electric,EF,none,0.857
+2003,shipment_weighted,storage,electric,EF,none,0.857
+2004,shipment_weighted,storage,electric,EF,none,0.9
+2005,shipment_weighted,storage,electric,EF,none,0.9
+2006,shipment_weighted,storage,electric,EF,none,0.9
+2007,shipment_weighted,storage,electric,EF,none,0.9
+2008,shipment_weighted,storage,electric,EF,none,0.9
+2009,shipment_weighted,storage,electric,EF,none,0.9
+2010,shipment_weighted,storage,electric,EF,none,0.9
+1972,shipment_weighted,storage,natural_gas,EF,none,0.474
+1973,shipment_weighted,storage,natural_gas,EF,none,0.474
+1974,shipment_weighted,storage,natural_gas,EF,none,0.474
+1975,shipment_weighted,storage,natural_gas,EF,none,0.474
+1976,shipment_weighted,storage,natural_gas,EF,none,0.475
+1977,shipment_weighted,storage,natural_gas,EF,none,0.475
+1978,shipment_weighted,storage,natural_gas,EF,none,0.476
+1979,shipment_weighted,storage,natural_gas,EF,none,0.476
+1980,shipment_weighted,storage,natural_gas,EF,none,0.477
+1981,shipment_weighted,storage,natural_gas,EF,none,0.478
+1982,shipment_weighted,storage,natural_gas,EF,none,0.479
+1983,shipment_weighted,storage,natural_gas,EF,none,0.48
+1984,shipment_weighted,storage,natural_gas,EF,none,0.481
+1985,shipment_weighted,storage,natural_gas,EF,none,0.483
+1986,shipment_weighted,storage,natural_gas,EF,none,0.484
+1987,shipment_weighted,storage,natural_gas,EF,none,0.486
+1988,shipment_weighted,storage,natural_gas,EF,none,0.488
+1989,shipment_weighted,storage,natural_gas,EF,none,0.49
+1990,shipment_weighted,storage,natural_gas,EF,none,0.492
+1991,shipment_weighted,storage,natural_gas,EF,none,0.494
+1992,shipment_weighted,storage,natural_gas,EF,none,0.496
+1993,shipment_weighted,storage,natural_gas,EF,none,0.498
+1994,shipment_weighted,storage,natural_gas,EF,none,0.499
+1995,shipment_weighted,storage,natural_gas,EF,none,0.5
+1996,shipment_weighted,storage,natural_gas,EF,none,0.501
+1997,shipment_weighted,storage,natural_gas,EF,none,0.501
+1998,shipment_weighted,storage,natural_gas,EF,none,0.501
+1999,shipment_weighted,storage,natural_gas,EF,none,0.501
+2000,shipment_weighted,storage,natural_gas,EF,none,0.501
+2001,shipment_weighted,storage,natural_gas,EF,none,0.501
+2002,shipment_weighted,storage,natural_gas,EF,none,0.501
+2003,shipment_weighted,storage,natural_gas,EF,none,0.501
+2004,shipment_weighted,storage,natural_gas,EF,none,0.55
+2005,shipment_weighted,storage,natural_gas,EF,none,0.55
+2006,shipment_weighted,storage,natural_gas,EF,none,0.55
+2007,shipment_weighted,storage,natural_gas,EF,none,0.55
+2008,shipment_weighted,storage,natural_gas,EF,none,0.55
+2009,shipment_weighted,storage,natural_gas,EF,none,0.55
+2010,shipment_weighted,storage,natural_gas,EF,none,0.55
+1972,shipment_weighted,storage,lpg,EF,none,0.474
+1973,shipment_weighted,storage,lpg,EF,none,0.474
+1974,shipment_weighted,storage,lpg,EF,none,0.474
+1975,shipment_weighted,storage,lpg,EF,none,0.474
+1976,shipment_weighted,storage,lpg,EF,none,0.475
+1977,shipment_weighted,storage,lpg,EF,none,0.475
+1978,shipment_weighted,storage,lpg,EF,none,0.476
+1979,shipment_weighted,storage,lpg,EF,none,0.476
+1980,shipment_weighted,storage,lpg,EF,none,0.477
+1981,shipment_weighted,storage,lpg,EF,none,0.478
+1982,shipment_weighted,storage,lpg,EF,none,0.479
+1983,shipment_weighted,storage,lpg,EF,none,0.48
+1984,shipment_weighted,storage,lpg,EF,none,0.481
+1985,shipment_weighted,storage,lpg,EF,none,0.483
+1986,shipment_weighted,storage,lpg,EF,none,0.484
+1987,shipment_weighted,storage,lpg,EF,none,0.486
+1988,shipment_weighted,storage,lpg,EF,none,0.488
+1989,shipment_weighted,storage,lpg,EF,none,0.49
+1990,shipment_weighted,storage,lpg,EF,none,0.492
+1991,shipment_weighted,storage,lpg,EF,none,0.494
+1992,shipment_weighted,storage,lpg,EF,none,0.496
+1993,shipment_weighted,storage,lpg,EF,none,0.498
+1994,shipment_weighted,storage,lpg,EF,none,0.499
+1995,shipment_weighted,storage,lpg,EF,none,0.5
+1996,shipment_weighted,storage,lpg,EF,none,0.501
+1997,shipment_weighted,storage,lpg,EF,none,0.501
+1998,shipment_weighted,storage,lpg,EF,none,0.501
+1999,shipment_weighted,storage,lpg,EF,none,0.501
+2000,shipment_weighted,storage,lpg,EF,none,0.501
+2001,shipment_weighted,storage,lpg,EF,none,0.501
+2002,shipment_weighted,storage,lpg,EF,none,0.501
+2003,shipment_weighted,storage,lpg,EF,none,0.501
+2004,shipment_weighted,storage,lpg,EF,none,0.55
+2005,shipment_weighted,storage,lpg,EF,none,0.55
+2006,shipment_weighted,storage,lpg,EF,none,0.55
+2007,shipment_weighted,storage,lpg,EF,none,0.55
+2008,shipment_weighted,storage,lpg,EF,none,0.55
+2009,shipment_weighted,storage,lpg,EF,none,0.55
+2010,shipment_weighted,storage,lpg,EF,none,0.55
+1972,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1973,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1974,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1975,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1976,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1977,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1978,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1979,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1980,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1981,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1982,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1983,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1984,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1985,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1986,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1987,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1988,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1989,shipment_weighted,storage,fuel_oil,EF,none,0.54
+1990,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1991,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1992,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1993,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1994,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1995,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1996,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1997,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1998,shipment_weighted,storage,fuel_oil,EF,none,0.59
+1999,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2000,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2001,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2002,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2003,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2004,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2005,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2006,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2007,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2008,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2009,shipment_weighted,storage,fuel_oil,EF,none,0.59
+2010,shipment_weighted,storage,fuel_oil,EF,none,0.59
diff --git a/HPXMLtoOpenStudio/resources/materials.rb b/HPXMLtoOpenStudio/resources/materials.rb
index 49a821c18c..b7f0ca0d3d 100644
--- a/HPXMLtoOpenStudio/resources/materials.rb
+++ b/HPXMLtoOpenStudio/resources/materials.rb
@@ -1,13 +1,15 @@
# frozen_string_literal: true
class Material
+ # name - Material name
# thick_in - Thickness [in]
# mat_base - Material object that defines k, rho, and cp. Can be overridden with values for those arguments.
# k_in - Conductivity [Btu-in/h-ft^2-F]
# rho - Density [lb/ft^3]
# cp - Specific heat [Btu/lb*F]
- # rvalue - R-value [h-ft^2-F/Btu]
- def initialize(name = nil, thick_in = nil, mat_base = nil, k_in = nil, rho = nil, cp = nil, tAbs = nil, sAbs = nil, vAbs = nil, rvalue = nil)
+ # tAbs - thermal absorptance (emittance); 0.9 is EnergyPlus default
+ # sAbs - solar absorptance; 0.7 is EnergyPlus default
+ def initialize(name: nil, thick_in: nil, mat_base: nil, k_in: nil, rho: nil, cp: nil, tAbs: 0.9, sAbs: 0.7)
@name = name
if not thick_in.nil?
@@ -45,7 +47,6 @@ def initialize(name = nil, thick_in = nil, mat_base = nil, k_in = nil, rho = nil
@tAbs = tAbs
@sAbs = sAbs
- @vAbs = vAbs
# Calculate R-value
if not rvalue.nil?
@@ -59,19 +60,19 @@ def initialize(name = nil, thick_in = nil, mat_base = nil, k_in = nil, rho = nil
end
end
- attr_accessor :name, :thick, :thick_in, :k, :k_in, :rho, :cp, :rvalue, :tAbs, :sAbs, :vAbs
+ attr_accessor :name, :thick, :thick_in, :k, :k_in, :rho, :cp, :rvalue, :tAbs, :sAbs
def self.AirCavityClosed(thick_in)
- rvalue = Gas.AirGapRvalue
- return new(name = nil, thick_in = thick_in, mat_base = nil, k_in = thick_in / rvalue, rho = Gas.Air.rho, cp = Gas.Air.cp)
+ rvalue = 1.0 # hr*ft*F/Btu (Assume for all air gap configurations since there is no correction for direction of heat flow in the simulation tools)
+ return new(thick_in: thick_in, k_in: thick_in / rvalue, rho: Gas.Air.rho, cp: Gas.Air.cp)
end
def self.AirCavityOpen(thick_in)
- return new(name = nil, thick_in = thick_in, mat_base = nil, k_in = 10000000.0, rho = Gas.Air.rho, cp = Gas.Air.cp)
+ return new(thick_in: thick_in, k_in: 10000000.0, rho: Gas.Air.rho, cp: Gas.Air.cp)
end
def self.AirFilm(rvalue)
- return new(name = Constants.AirFilm, thick_in = 1.0, mat_base = nil, k_in = 1.0 / rvalue)
+ return new(name: Constants.AirFilm, thick_in: 1.0, k_in: 1.0 / rvalue)
end
def self.AirFilmOutside
@@ -186,70 +187,79 @@ def self.AirFilmRoofASHRAE140
def self.CoveringBare(floorFraction = 0.8, rvalue = 2.08)
# Combined layer of, e.g., carpet and bare floor
- thickness = 0.5 # in
- return new(name = 'Floor Covering', thick_in = thickness, mat_base = nil, k_in = thickness / (rvalue * floorFraction), rho = 3.4, cp = 0.32, tAbs = 0.9, sAbs = 0.9, vAbs = 0.9)
+ thick_in = 0.5 # in
+ return new(name: 'floor covering', thick_in: thick_in, k_in: thick_in / (rvalue * floorFraction), rho: 3.4, cp: 0.32, tAbs: 0.9, sAbs: 0.9)
end
def self.Concrete(thick_in)
- return new(name = "Concrete #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Concrete, k_in = nil, rho = nil, cp = nil, tAbs = 0.9)
+ return new(name: "concrete #{thick_in} in.", thick_in: thick_in, mat_base: BaseMaterial.Concrete, tAbs: 0.9)
end
- def self.ExteriorFinishMaterial(siding, emittance, solar_absorptance, thick_in = nil)
- if siding == HPXML::SidingTypeWood
+ def self.ExteriorFinishMaterial(type, thick_in = nil)
+ if (type == HPXML::SidingTypeNone) || (!thick_in.nil? && thick_in <= 0)
+ return
+ elsif type == HPXML::SidingTypeWood
thick_in = 1.0 if thick_in.nil?
- return new(siding, thick_in, nil, 0.71, 34.0, 0.28, emittance, solar_absorptance, solar_absorptance)
- elsif siding == HPXML::SidingTypeVinyl
+ return new(name: type, thick_in: thick_in, k_in: 0.71, rho: 34.0, cp: 0.28)
+ elsif type == HPXML::SidingTypeVinyl
thick_in = 0.375 if thick_in.nil?
- return new(siding, thick_in, BaseMaterial.Vinyl, nil, nil, nil, emittance, solar_absorptance, solar_absorptance)
- elsif siding == HPXML::SidingTypeStucco
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Vinyl)
+ elsif type == HPXML::SidingTypeStucco
thick_in = 1.0 if thick_in.nil?
- return new(siding, thick_in, BaseMaterial.Stucco, nil, nil, nil, emittance, solar_absorptance, solar_absorptance)
- elsif siding == HPXML::SidingTypeFiberCement
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Stucco)
+ elsif type == HPXML::SidingTypeFiberCement
thick_in = 0.375 if thick_in.nil?
- return new(siding, thick_in, nil, 1.79, 21.7, 0.24, emittance, solar_absorptance, solar_absorptance)
- elsif siding == HPXML::SidingTypeBrick
+ return new(name: type, thick_in: thick_in, k_in: 1.79, rho: 21.7, cp: 0.24)
+ elsif type == HPXML::SidingTypeBrick
thick_in = 4.0 if thick_in.nil?
- return new(siding, thick_in, BaseMaterial.Brick, nil, nil, nil, emittance, solar_absorptance, solar_absorptance)
- elsif siding == HPXML::SidingTypeAluminum
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Brick)
+ elsif type == HPXML::SidingTypeAluminum
thick_in = 0.375 if thick_in.nil?
- return new(siding, thick_in, BaseMaterial.Aluminum, nil, nil, nil, emittance, solar_absorptance, solar_absorptance)
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Aluminum)
end
- end
- def self.FloorWood
- return Material.new(name = 'Wood Floor', thick_in = 0.625, mat_base = nil, k_in = 0.8004, rho = 34.0, cp = 0.29)
+ fail "Unexpected type: #{type}."
end
- def self.GypsumWall(thick_in)
- return new(name = "Drywall #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Gypsum, k_in = nil, rho = nil, cp = nil, tAbs = 0.9, sAbs = 0.5, vAbs = 0.1)
- end
+ def self.InteriorFinishMaterial(type, thick_in = nil)
+ if (type == HPXML::InteriorFinishNone) || (!thick_in.nil? && thick_in <= 0)
+ return
+ else
+ thick_in = 0.5 if thick_in.nil?
+ if [HPXML::InteriorFinishGypsumBoard,
+ HPXML::InteriorFinishGypsumCompositeBoard,
+ HPXML::InteriorFinishPlaster].include? type
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Gypsum)
+ elsif [HPXML::InteriorFinishWood].include? type
+ return new(name: type, thick_in: thick_in, mat_base: BaseMaterial.Wood)
+ end
+ end
- def self.GypsumCeiling(thick_in)
- return new(name = "Drywall #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Gypsum, k_in = nil, rho = nil, cp = nil, tAbs = 0.9, sAbs = 0.3, vAbs = 0.1)
+ fail "Unexpected type: #{type}."
end
def self.Soil(thick_in)
- return new(name = "Soil #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Soil)
+ return new(name: "soil #{thick_in} in.", thick_in: thick_in, mat_base: BaseMaterial.Soil)
end
def self.Stud2x(thick_in)
- return new(name = "Stud 2x #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Wood)
+ return new(name: "stud 2x #{thick_in} in.", thick_in: thick_in, mat_base: BaseMaterial.Wood)
end
def self.Stud2x4
- return new(name = 'Stud 2x4', thick_in = 3.5, mat_base = BaseMaterial.Wood)
+ return new(name: 'stud 2x4', thick_in: 3.5, mat_base: BaseMaterial.Wood)
end
def self.Stud2x6
- return new(name = 'Stud 2x6', thick_in = 5.5, mat_base = BaseMaterial.Wood)
+ return new(name: 'stud 2x6', thick_in: 5.5, mat_base: BaseMaterial.Wood)
end
def self.Stud2x8
- return new(name = 'Stud 2x8', thick_in = 7.25, mat_base = BaseMaterial.Wood)
+ return new(name: 'stud 2x8', thick_in: 7.25, mat_base: BaseMaterial.Wood)
end
- def self.Plywood(thick_in)
- return new(name = "Plywood #{thick_in} in.", thick_in = thick_in, mat_base = BaseMaterial.Wood)
+ def self.OSBSheathing(thick_in)
+ return new(name: "osb sheathing #{thick_in} in.", thick_in: thick_in, mat_base: BaseMaterial.Wood)
end
def self.RadiantBarrier(grade)
@@ -264,16 +274,17 @@ def self.RadiantBarrier(grade)
rb_emittance = 0.05
non_rb_emittance = 0.90
emittance = rb_emittance * (1.0 - gap_frac) + non_rb_emittance * gap_frac
- return new(name = 'Radiant Barrier', thick_in = 0.0084, mat_base = nil, k_in = 1629.6, rho = 168.6, cp = 0.22, tAbs = emittance, sAbs = 0.05, vAbs = 0.05)
+ return new(name: 'radiant barrier', thick_in: 0.0084, k_in: 1629.6, rho: 168.6, cp: 0.22, tAbs: emittance, sAbs: 0.05)
end
- def self.RoofMaterial(name, emissivity, absorptivity)
- return new(name = name, thick_in = 0.375, mat_base = nil, k_in = 1.128, rho = 70, cp = 0.35, tAbs = emissivity, sAbs = absorptivity, vAbs = absorptivity)
+ def self.RoofMaterial(type, thick_in = nil)
+ thick_in = 0.375 if thick_in.nil?
+ return new(name: type, thick_in: thick_in, k_in: 1.128, rho: 70, cp: 0.35)
end
end
class BaseMaterial
- def initialize(rho, cp, k_in)
+ def initialize(rho:, cp:, k_in: nil)
@rho = rho
@cp = cp
@k_in = k_in
@@ -282,94 +293,81 @@ def initialize(rho, cp, k_in)
attr_accessor :rho, :cp, :k_in
def self.Gypsum
- return new(rho = 50.0, cp = 0.2, k_in = 1.1112)
+ return new(rho: 50.0, cp: 0.2, k_in: 1.1112)
end
def self.Wood
- return new(rho = 32.0, cp = 0.29, k_in = 0.8004)
+ return new(rho: 32.0, cp: 0.29, k_in: 0.8004)
end
def self.Concrete
- return new(rho = 140.0, cp = 0.2, k_in = 12.5)
+ return new(rho: 140.0, cp: 0.2, k_in: 12.5)
end
def self.Gypcrete
# http://www.maxxon.com/gyp-crete/data
- return new(rho = 100.0, cp = 0.223, k_in = 4.7424)
+ return new(rho: 100.0, cp: 0.223, k_in: 4.7424)
end
def self.InsulationRigid
- return new(rho = 2.0, cp = 0.29, k_in = 0.204)
+ return new(rho: 2.0, cp: 0.29, k_in: 0.204)
end
def self.InsulationCelluloseDensepack
- return new(rho = 3.5, cp = 0.25, k_in = nil)
+ return new(rho: 3.5, cp: 0.25)
end
def self.InsulationCelluloseLoosefill
- return new(rho = 1.5, cp = 0.25, k_in = nil)
+ return new(rho: 1.5, cp: 0.25)
end
def self.InsulationFiberglassDensepack
- return new(rho = 2.2, cp = 0.25, k_in = nil)
+ return new(rho: 2.2, cp: 0.25)
end
def self.InsulationFiberglassLoosefill
- return new(rho = 0.5, cp = 0.25, k_in = nil)
+ return new(rho: 0.5, cp: 0.25)
end
def self.InsulationGenericDensepack
- return new(rho = (self.InsulationFiberglassDensepack.rho + self.InsulationCelluloseDensepack.rho) / 2.0, cp = 0.25, k_in = nil)
+ return new(rho: (self.InsulationFiberglassDensepack.rho + self.InsulationCelluloseDensepack.rho) / 2.0, cp: 0.25)
end
def self.InsulationGenericLoosefill
- return new(rho = (self.InsulationFiberglassLoosefill.rho + self.InsulationCelluloseLoosefill.rho) / 2.0, cp = 0.25, k_in = nil)
+ return new(rho: (self.InsulationFiberglassLoosefill.rho + self.InsulationCelluloseLoosefill.rho) / 2.0, cp: 0.25)
end
def self.Soil
- return new(rho = 115.0, cp = 0.1, k_in = 12.0)
+ return new(rho: 115.0, cp: 0.1, k_in: 12.0)
end
def self.Brick
- return new(rho = 110.0, cp = 0.19, k_in = 5.5)
+ return new(rho: 110.0, cp: 0.19, k_in: 5.5)
end
def self.Vinyl
- return new(rho = 11.1, cp = 0.25, k_in = 0.62)
+ return new(rho: 11.1, cp: 0.25, k_in: 0.62)
end
def self.Aluminum
- return new(rho = 10.9, cp = 0.29, k_in = 0.61)
+ return new(rho: 10.9, cp: 0.29, k_in: 0.61)
end
def self.Stucco
- return new(rho = 80.0, cp = 0.21, k_in = 4.5)
+ return new(rho: 80.0, cp: 0.21, k_in: 4.5)
end
def self.Stone
- return new(rho = 140.0, cp = 0.2, k_in = 12.5)
+ return new(rho: 140.0, cp: 0.2, k_in: 12.5)
end
def self.StrawBale
- return new(rho = 11.1652, cp = 0.2991, k_in = 0.4164)
- end
-end
-
-class SimpleMaterial
- def initialize(name = nil, rvalue = nil)
- @name = name
- @rvalue = rvalue
- end
-
- attr_accessor :name, :rvalue
-
- def self.Adiabatic
- return new(name = 'Adiabatic', rvalue = 1000)
+ return new(rho: 11.1652, cp: 0.2991, k_in: 0.4164)
end
end
class GlazingMaterial
- def initialize(name = nil, ufactor = nil, shgc = nil)
+ def initialize(name:, ufactor:, shgc:)
@name = name
@ufactor = ufactor
@shgc = shgc
@@ -379,37 +377,33 @@ def initialize(name = nil, ufactor = nil, shgc = nil)
end
class Liquid
- def initialize(rho, cp, k, mu, h_fg, t_frz, t_boil, t_crit)
- @rho = rho # Density (lb/ft3)
- @cp = cp # Specific Heat (Btu/lbm-R)
- @k = k # Thermal Conductivity (Btu/h-ft-R)
- @mu = mu # Dynamic Viscosity (lbm/ft-h)
- @h_fg = h_fg # Latent Heat of Vaporization (Btu/lbm)
- @t_frz = t_frz # Freezing Temperature (degF)
- @t_boil = t_boil # Boiling Temperature (degF)
- @t_crit = t_crit # Critical Temperature (degF)
+ def initialize(rho: nil, cp: nil, k: nil, h_fg: nil, t_frz: nil)
+ @rho = rho # Density (lb/ft3)
+ @cp = cp # Specific Heat (Btu/lbm-R)
+ @k = k # Thermal Conductivity (Btu/h-ft-R)
+ @h_fg = h_fg # Latent Heat of Vaporization (Btu/lbm)
+ @t_frz = t_frz # Freezing Temperature (degF)
end
- attr_accessor :rho, :cp, :k, :mu, :h_fg, :t_frz, :t_boil, :t_crit
+ attr_accessor :rho, :cp, :k, :mu, :h_fg, :t_frz
def self.H2O_l
# From EES at STP
- return new(62.32, 0.9991, 0.3386, 2.424, 1055, 32.0, 212.0, nil)
+ return new(rho: 62.32, cp: 0.9991, k: 0.3386, h_fg: 1055, t_frz: 32.0)
end
def self.R22_l
# Converted from EnthDR22 f77 in ResAC (Brandemuehl)
- return new(nil, 0.2732, nil, nil, 100.5, nil, -41.35, 204.9)
+ return new(cp: 0.2732, h_fg: 100.5)
end
end
class Gas
- def initialize(rho, cp, k, mu, m)
+ def initialize(rho: nil, cp: nil, k: nil, m: nil)
@rho = rho # Density (lb/ft3)
- @cp = cp # Specific Heat (Btu/lbm-R)
- @k = k # Thermal Conductivity (Btu/h-ft-R)
- @mu = mu # Dynamic Viscosity (lbm/ft-h)
- @m = m # Molecular Weight (lbm/lbmol)
+ @cp = cp # Specific Heat (Btu/lbm-R)
+ @k = k # Thermal Conductivity (Btu/h-ft-R)
+ @m = m # Molecular Weight (lbm/lbmol)
if @m
gas_constant = 1.9858 # Gas Constant (Btu/lbmol-R)
@r = gas_constant / m # Gas Constant (Btu/lbm-R)
@@ -418,25 +412,21 @@ def initialize(rho, cp, k, mu, m)
end
end
- attr_accessor :rho, :cp, :k, :mu, :m, :r
+ attr_accessor :rho, :cp, :k, :m, :r
def self.Air
# From EES at STP
- return new(0.07518, 0.2399, 0.01452, 0.04415, 28.97)
- end
-
- def self.AirGapRvalue
- return 1.0 # hr*ft*F/Btu (Assume for all air gap configurations since there is no correction for direction of heat flow in the simulation tools)
+ return new(rho: 0.07518, cp: 0.2399, k: 0.01452, m: 28.97)
end
def self.H2O_v
# From EES at STP
- return new(nil, 0.4495, nil, nil, 18.02)
+ return new(cp: 0.4495, m: 18.02)
end
def self.R22_v
# Converted from EnthDR22 f77 in ResAC (Brandemuehl)
- return new(nil, 0.1697, nil, nil, nil)
+ return new(cp: 0.1697)
end
def self.PsychMassRat
diff --git a/HPXMLtoOpenStudio/resources/meta_measure.rb b/HPXMLtoOpenStudio/resources/meta_measure.rb
index 8b02b8b059..3c8ade3013 100644
--- a/HPXMLtoOpenStudio/resources/meta_measure.rb
+++ b/HPXMLtoOpenStudio/resources/meta_measure.rb
@@ -425,7 +425,6 @@ def report_os_warnings(os_log, rundir)
next if s.logMessage.include? 'WorkflowStepResult value called with undefined stepResult'
next if s.logMessage.include?("Object of type 'Schedule:Constant' and named 'Always") && s.logMessage.include?('points to an object named') && s.logMessage.include?('but that object cannot be located')
next if s.logMessage.include? 'Appears there are no design condition fields in the EPW file'
- next if s.logMessage.include?('Using EnergyPlusVersion version') && s.logMessage.include?("which should have 'Year' field, but it's always zero")
f << "OS Message: #{s.logMessage}\n"
end
diff --git a/HPXMLtoOpenStudio/resources/minitest_helper.rb b/HPXMLtoOpenStudio/resources/minitest_helper.rb
index e60e49dbf4..cb14b6ac9d 100644
--- a/HPXMLtoOpenStudio/resources/minitest_helper.rb
+++ b/HPXMLtoOpenStudio/resources/minitest_helper.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-$VERBOSE = nil # Prevents ruby warnings, see https://github.com/NREL/OpenStudio/issues/4301
-
called_from_cli = true
begin
OpenStudio.getOpenStudioCLI
diff --git a/HPXMLtoOpenStudio/resources/schedules.rb b/HPXMLtoOpenStudio/resources/schedules.rb
index 9bea96a90d..017202241d 100644
--- a/HPXMLtoOpenStudio/resources/schedules.rb
+++ b/HPXMLtoOpenStudio/resources/schedules.rb
@@ -1002,6 +1002,7 @@ def self.create_ruleset_from_daily_season(model, values)
values.each_with_index do |value, i|
i += 1
next unless value != start_value || i == values.length
+
rule = OpenStudio::Model::ScheduleRule.new(s)
set_weekday_rule(rule)
set_weekend_rule(rule)
diff --git a/HPXMLtoOpenStudio/resources/version.rb b/HPXMLtoOpenStudio/resources/version.rb
index da107e988a..fde9466ab6 100644
--- a/HPXMLtoOpenStudio/resources/version.rb
+++ b/HPXMLtoOpenStudio/resources/version.rb
@@ -2,7 +2,7 @@
class Version
OS_HPXML_Version = '1.2.0' # Version of the OS-HPXML workflow
- OS_Version = '3.2.0' # Required version of OpenStudio (can be 'X.X' or 'X.X.X')
+ OS_Version = '3.2.1' # Required version of OpenStudio (can be 'X.X' or 'X.X.X')
HPXML_Version = '3.0' # HPXML schemaVersion
def self.check_openstudio_version
diff --git a/HPXMLtoOpenStudio/resources/waterheater.rb b/HPXMLtoOpenStudio/resources/waterheater.rb
index a10c3690b7..4a17a92c5b 100644
--- a/HPXMLtoOpenStudio/resources/waterheater.rb
+++ b/HPXMLtoOpenStudio/resources/waterheater.rb
@@ -761,13 +761,13 @@ def self.setup_hpwh_dxcoil(model, hpwh, water_heating_system, weather, obj_name_
cop = 1.174536058 * uef # Based on simulation of the UEF test procedure at varying COPs
elsif not water_heating_system.uniform_energy_factor.nil?
uef = water_heating_system.uniform_energy_factor
- if water_heating_system.first_hour_rating < 18.0
- fail 'It is unlikely that a heat pump water heater falls into the very small bin of the First Hour Rating (FHR) test. Double check FHR input.'
- elsif water_heating_system.first_hour_rating < 51.0 # Includes 18 gal up to (but not including) 51
+ if water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinVerySmall
+ fail 'It is unlikely that a heat pump water heater falls into the very small bin of the First Hour Rating (FHR) test. Double check input.'
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinLow
cop = 1.0005 * uef - 0.0789
- elsif water_heating_system.first_hour_rating < 75.0
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinMedium
cop = 1.0909 * uef - 0.0868
- else
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinHigh
cop = 1.1022 * uef - 0.0877
end
end
@@ -853,7 +853,7 @@ def self.setup_hpwh_stratified_tank(hpwh, water_heating_system, obj_name_hpwh, h
def self.setup_hpwh_fan(hpwh, obj_name_hpwh, airflow_rate)
fan_power = 0.0462 # W/cfm, Based on 1st gen AO Smith HPWH, could be updated but pretty minor impact
- fan = hpwh.fan.to_FanOnOff.get
+ fan = hpwh.fan.to_FanOnOff.get # TOOD: Update reporting measure if this changes to FanSystemModel per https://github.com/NREL/OpenStudio/issues/4334
fan.setName("#{obj_name_hpwh} fan")
fan.setFanEfficiency(65.0 / fan_power * UnitConversions.convert(1.0, 'ft^3/min', 'm^3/s'))
fan.setPressureRise(65.0)
@@ -1462,13 +1462,13 @@ def self.calc_tank_UA(act_vol, water_heating_system, solar_fraction)
volume_drawn = 64.3 # gal/day
elsif not water_heating_system.uniform_energy_factor.nil?
t = 125.0 # F
- if water_heating_system.first_hour_rating < 18.0
+ if water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinVerySmall
volume_drawn = 10.0 # gal
- elsif water_heating_system.first_hour_rating < 51.0 # Includes 18 gal up to (but not including) 51
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinLow
volume_drawn = 38.0 # gal
- elsif water_heating_system.first_hour_rating < 75.0
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinMedium
volume_drawn = 55.0 # gal
- else
+ elsif water_heating_system.usage_bin == HPXML::WaterHeaterUsageBinHigh
volume_drawn = 84.0 # gal
end
end
@@ -1729,4 +1729,40 @@ def self.get_water_heater_solar_fraction(water_heating_system, solar_thermal_sys
end
return solar_fraction.to_f
end
+
+ def self.get_default_water_heater_efficiency_by_year_installed(year, fuel_type)
+ fuel_primary_id = { EPlus::FuelTypeElectricity => 'electric',
+ EPlus::FuelTypeNaturalGas => 'natural_gas',
+ EPlus::FuelTypeOil => 'fuel_oil',
+ EPlus::FuelTypeCoal => 'fuel_oil', # assumption
+ EPlus::FuelTypeWoodCord => 'fuel_oil', # assumption
+ EPlus::FuelTypeWoodPellets => 'fuel_oil', # assumption
+ EPlus::FuelTypePropane => 'lpg' }[EPlus.fuel_type(fuel_type)]
+
+ value = nil
+ lookup_year = 0
+ CSV.foreach(File.join(File.dirname(__FILE__), 'lu_water_heater_efficiency.csv'), headers: true) do |row|
+ next unless row['fuel_primary_id'] == fuel_primary_id
+
+ row_year = Integer(row['year'])
+ if (row_year - year).abs <= (lookup_year - year).abs
+ lookup_year = row_year
+ value = Float(row['value'])
+ end
+ end
+
+ return value
+ end
+
+ def self.get_usage_bin_from_first_hour_rating(fhr)
+ if fhr < 18.0
+ return HPXML::WaterHeaterUsageBinVerySmall
+ elsif fhr < 51.0
+ return HPXML::WaterHeaterUsageBinLow
+ elsif fhr < 75.0
+ return HPXML::WaterHeaterUsageBinMedium
+ else
+ return HPXML::WaterHeaterUsageBinHigh
+ end
+ end
end
diff --git a/HPXMLtoOpenStudio/resources/xmlhelper.rb b/HPXMLtoOpenStudio/resources/xmlhelper.rb
index c26c9bbb17..696766b43d 100644
--- a/HPXMLtoOpenStudio/resources/xmlhelper.rb
+++ b/HPXMLtoOpenStudio/resources/xmlhelper.rb
@@ -49,10 +49,10 @@ def self.create_elements_as_needed(parent, element_names)
# Deletes the child element with element_name. Returns the deleted element.
def self.delete_element(parent, element_name)
element = nil
- begin
+ while !parent.at_xpath(element_name).nil?
last_element = element
element = parent.at_xpath(element_name).remove
- end while !parent.at_xpath(element_name).nil?
+ end
return last_element
end
diff --git a/HPXMLtoOpenStudio/tests/test_airflow.rb b/HPXMLtoOpenStudio/tests/test_airflow.rb
index 3d74db1510..ea6604d44b 100644
--- a/HPXMLtoOpenStudio/tests/test_airflow.rb
+++ b/HPXMLtoOpenStudio/tests/test_airflow.rb
@@ -493,14 +493,14 @@ def test_infiltration_compartmentalization_area
# Base
hpxml = HPXML.new(hpxml_path: File.absolute_path(File.join(sample_files_dir, 'base.xml')))
total_area, exterior_area = hpxml.compartmentalization_boundary_areas
- assert_equal(5216, exterior_area)
- assert_equal(5216, total_area)
+ assert_in_delta(5216, exterior_area, 1.0)
+ assert_in_delta(5216, total_area, 1.0)
# Test adjacent garage
hpxml = HPXML.new(hpxml_path: File.absolute_path(File.join(sample_files_dir, 'base-enclosure-garage.xml')))
total_area, exterior_area = hpxml.compartmentalization_boundary_areas
- assert_equal(4976, exterior_area)
- assert_equal(5216, total_area)
+ assert_in_delta(4976, exterior_area, 1.0)
+ assert_in_delta(5216, total_area, 1.0)
# Test unvented attic/crawlspace within infiltration volume
hpxml = HPXML.new(hpxml_path: File.absolute_path(File.join(sample_files_dir, 'base-foundation-unvented-crawlspace.xml')))
@@ -511,8 +511,8 @@ def test_infiltration_compartmentalization_area
foundation.within_infiltration_volume = true
end
total_area, exterior_area = hpxml.compartmentalization_boundary_areas
- assert_equal(5066, exterior_area)
- assert_equal(5066, total_area)
+ assert_in_delta(5066, exterior_area, 1.0)
+ assert_in_delta(5066, total_area, 1.0)
# Test unvented attic/crawlspace not within infiltration volume
hpxml = HPXML.new(hpxml_path: File.absolute_path(File.join(sample_files_dir, 'base-foundation-unvented-crawlspace.xml')))
@@ -523,14 +523,14 @@ def test_infiltration_compartmentalization_area
foundation.within_infiltration_volume = false
end
total_area, exterior_area = hpxml.compartmentalization_boundary_areas
- assert_equal(3900, exterior_area)
- assert_equal(3900, total_area)
+ assert_in_delta(3900, exterior_area, 1.0)
+ assert_in_delta(3900, total_area, 1.0)
# Test multifamily
hpxml = HPXML.new(hpxml_path: File.absolute_path(File.join(sample_files_dir, 'base-bldgtype-multifamily.xml')))
total_area, exterior_area = hpxml.compartmentalization_boundary_areas
- assert_equal(686, exterior_area)
- assert_equal(2780, total_area)
+ assert_in_delta(686, exterior_area, 1.0)
+ assert_in_delta(2780, total_area, 1.0)
end
def test_infiltration_assumed_height
diff --git a/HPXMLtoOpenStudio/tests/test_defaults.rb b/HPXMLtoOpenStudio/tests/test_defaults.rb
index 3d2b5934f8..910083f64a 100644
--- a/HPXMLtoOpenStudio/tests/test_defaults.rb
+++ b/HPXMLtoOpenStudio/tests/test_defaults.rb
@@ -104,6 +104,29 @@ def test_site
_test_default_site_values(hpxml_default, HPXML::SiteTypeSuburban, HPXML::ShieldingNormal)
end
+ def test_neighbor_buildings
+ # Test inputs not overridden by defaults
+ hpxml = _create_hpxml('base-misc-neighbor-shading.xml')
+ hpxml.neighbor_buildings[0].azimuth = 123
+ hpxml.neighbor_buildings[1].azimuth = 321
+ hpxml.walls[0].azimuth = 123
+ hpxml.walls[1].azimuth = 321
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_neighbor_building_values(hpxml_default, [123, 321])
+
+ # Test defaults
+ hpxml.neighbor_buildings[0].azimuth = nil
+ hpxml.neighbor_buildings[1].azimuth = nil
+ hpxml.neighbor_buildings[0].orientation = HPXML::OrientationEast
+ hpxml.neighbor_buildings[1].orientation = HPXML::OrientationNorth
+ hpxml.walls[0].azimuth = 90
+ hpxml.walls[1].azimuth = 0
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_neighbor_building_values(hpxml_default, [90, 0])
+ end
+
def test_occupancy
# Test inputs not overridden by defaults
hpxml = _create_hpxml('base.xml')
@@ -159,20 +182,20 @@ def test_infiltration
hpxml.air_infiltration_measurements[0].infiltration_volume = 25000
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_infiltration_values(hpxml_default, 25000)
+ _test_default_infiltration_values(hpxml_default.air_infiltration_measurements[0], 25000)
# Test defaults w/ conditioned basement
hpxml.air_infiltration_measurements[0].infiltration_volume = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_infiltration_values(hpxml_default, 2700 * 8)
+ _test_default_infiltration_values(hpxml_default.air_infiltration_measurements[0], 2700 * 8)
# Test defaults w/o conditioned basement
hpxml = _create_hpxml('base-foundation-slab.xml')
hpxml.air_infiltration_measurements[0].infiltration_volume = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_infiltration_values(hpxml_default, 1350 * 8)
+ _test_default_infiltration_values(hpxml_default.air_infiltration_measurements[0], 1350 * 8)
end
def test_attics
@@ -181,13 +204,13 @@ def test_attics
hpxml.attics[0].vented_attic_sla = 0.001
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_attic_values(hpxml_default, 0.001)
+ _test_default_attic_values(hpxml_default.attics[0], 0.001)
# Test defaults
hpxml.attics[0].vented_attic_sla = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_attic_values(hpxml_default, 1.0 / 300.0)
+ _test_default_attic_values(hpxml_default.attics[0], 1.0 / 300.0)
end
def test_foundations
@@ -196,13 +219,13 @@ def test_foundations
hpxml.foundations[0].vented_crawlspace_sla = 0.001
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_foundation_values(hpxml_default, 0.001)
+ _test_default_foundation_values(hpxml_default.foundations[0], 0.001)
# Test defaults
hpxml.foundations[0].vented_crawlspace_sla = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_foundation_values(hpxml_default, 1.0 / 150.0)
+ _test_default_foundation_values(hpxml_default.foundations[0], 1.0 / 150.0)
end
def test_roofs
@@ -212,26 +235,55 @@ def test_roofs
hpxml.roofs[0].solar_absorptance = 0.77
hpxml.roofs[0].roof_color = HPXML::ColorDark
hpxml.roofs[0].emittance = 0.88
+ hpxml.roofs[0].interior_finish_type = HPXML::InteriorFinishPlaster
+ hpxml.roofs[0].interior_finish_thickness = 0.25
+ hpxml.roofs[0].azimuth = 123
+ hpxml.roofs[0].radiant_barrier_grade = 3
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_roof_values(hpxml_default, HPXML::RoofTypeMetal, 0.77, HPXML::ColorDark, 0.88, true)
+ _test_default_roof_values(hpxml_default.roofs[0], HPXML::RoofTypeMetal, 0.77, HPXML::ColorDark, 0.88, true, 3, HPXML::InteriorFinishPlaster, 0.25, 123)
# Test defaults w/ RoofColor
hpxml.roofs[0].roof_type = nil
hpxml.roofs[0].solar_absorptance = nil
hpxml.roofs[0].roof_color = HPXML::ColorLight
hpxml.roofs[0].emittance = nil
- hpxml.roofs[0].radiant_barrier = nil
+ hpxml.roofs[0].interior_finish_thickness = nil
+ hpxml.roofs[0].orientation = HPXML::OrientationNortheast
+ hpxml.roofs[0].azimuth = nil
+ hpxml.roofs[0].radiant_barrier_grade = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_roof_values(hpxml_default, HPXML::RoofTypeAsphaltShingles, 0.75, HPXML::ColorLight, 0.90, false)
+ _test_default_roof_values(hpxml_default.roofs[0], HPXML::RoofTypeAsphaltShingles, 0.75, HPXML::ColorLight, 0.90, true, 1, HPXML::InteriorFinishPlaster, 0.5, 45)
# Test defaults w/ SolarAbsorptance
hpxml.roofs[0].solar_absorptance = 0.99
hpxml.roofs[0].roof_color = nil
+ hpxml.roofs[0].interior_finish_type = nil
+ hpxml.roofs[0].radiant_barrier = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_roof_values(hpxml_default.roofs[0], HPXML::RoofTypeAsphaltShingles, 0.99, HPXML::ColorDark, 0.90, false, nil, HPXML::InteriorFinishNone, nil, 45)
+
+ # Test defaults w/o RoofColor & SolarAbsorptance
+ hpxml.roofs[0].solar_absorptance = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_roof_values(hpxml_default, HPXML::RoofTypeAsphaltShingles, 0.99, HPXML::ColorDark, 0.90, false)
+ _test_default_roof_values(hpxml_default.roofs[0], HPXML::RoofTypeAsphaltShingles, 0.85, HPXML::ColorMedium, 0.90, false, nil, HPXML::InteriorFinishNone, nil, 45)
+
+ # Test defaults w/ conditioned space
+ hpxml = _create_hpxml('base-atticroof-cathedral.xml')
+ hpxml.roofs[0].roof_type = nil
+ hpxml.roofs[0].solar_absorptance = nil
+ hpxml.roofs[0].roof_color = HPXML::ColorLight
+ hpxml.roofs[0].emittance = nil
+ hpxml.roofs[0].interior_finish_type = nil
+ hpxml.roofs[0].interior_finish_thickness = nil
+ hpxml.roofs[0].orientation = HPXML::OrientationNortheast
+ hpxml.roofs[0].azimuth = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_roof_values(hpxml_default.roofs[0], HPXML::RoofTypeAsphaltShingles, 0.75, HPXML::ColorLight, 0.90, false, nil, HPXML::InteriorFinishGypsumBoard, 0.5, 45)
end
def test_rim_joists
@@ -241,25 +293,34 @@ def test_rim_joists
hpxml.rim_joists[0].solar_absorptance = 0.55
hpxml.rim_joists[0].color = HPXML::ColorLight
hpxml.rim_joists[0].emittance = 0.88
+ hpxml.rim_joists[0].azimuth = 123
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_rim_joist_values(hpxml_default, HPXML::SidingTypeBrick, 0.55, HPXML::ColorLight, 0.88)
+ _test_default_rim_joist_values(hpxml_default.rim_joists[0], HPXML::SidingTypeBrick, 0.55, HPXML::ColorLight, 0.88, 123)
# Test defaults w/ Color
hpxml.rim_joists[0].siding = nil
hpxml.rim_joists[0].solar_absorptance = nil
hpxml.rim_joists[0].color = HPXML::ColorDark
hpxml.rim_joists[0].emittance = nil
+ hpxml.rim_joists[0].orientation = HPXML::OrientationNorthwest
+ hpxml.rim_joists[0].azimuth = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_rim_joist_values(hpxml_default, HPXML::SidingTypeWood, 0.95, HPXML::ColorDark, 0.90)
+ _test_default_rim_joist_values(hpxml_default.rim_joists[0], HPXML::SidingTypeWood, 0.95, HPXML::ColorDark, 0.90, 315)
# Test defaults w/ SolarAbsorptance
hpxml.rim_joists[0].solar_absorptance = 0.99
hpxml.rim_joists[0].color = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_rim_joist_values(hpxml_default, HPXML::SidingTypeWood, 0.99, HPXML::ColorDark, 0.90)
+ _test_default_rim_joist_values(hpxml_default.rim_joists[0], HPXML::SidingTypeWood, 0.99, HPXML::ColorDark, 0.90, 315)
+
+ # Test defaults w/o Color & SolarAbsorptance
+ hpxml.rim_joists[0].solar_absorptance = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_rim_joist_values(hpxml_default.rim_joists[0], HPXML::SidingTypeWood, 0.7, HPXML::ColorMedium, 0.90, 315)
end
def test_walls
@@ -269,40 +330,127 @@ def test_walls
hpxml.walls[0].solar_absorptance = 0.66
hpxml.walls[0].color = HPXML::ColorDark
hpxml.walls[0].emittance = 0.88
+ hpxml.walls[0].interior_finish_type = HPXML::InteriorFinishWood
+ hpxml.walls[0].interior_finish_thickness = 0.75
+ hpxml.walls[0].azimuth = 123
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_wall_values(hpxml_default, HPXML::SidingTypeFiberCement, 0.66, HPXML::ColorDark, 0.88)
+ _test_default_wall_values(hpxml_default.walls[0], HPXML::SidingTypeFiberCement, 0.66, HPXML::ColorDark, 0.88, HPXML::InteriorFinishWood, 0.75, 123)
- # Test defaults W/ Color
+ # Test defaults w/ Color
hpxml.walls[0].siding = nil
hpxml.walls[0].solar_absorptance = nil
hpxml.walls[0].color = HPXML::ColorLight
hpxml.walls[0].emittance = nil
+ hpxml.walls[0].interior_finish_type = HPXML::InteriorFinishWood
+ hpxml.walls[0].interior_finish_thickness = nil
+ hpxml.walls[0].orientation = HPXML::OrientationSouth
+ hpxml.walls[0].azimuth = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_wall_values(hpxml_default, HPXML::SidingTypeWood, 0.5, HPXML::ColorLight, 0.90)
+ _test_default_wall_values(hpxml_default.walls[0], HPXML::SidingTypeWood, 0.5, HPXML::ColorLight, 0.90, HPXML::InteriorFinishWood, 0.5, 180)
- # Test defaults W/ SolarAbsorptance
+ # Test defaults w/ SolarAbsorptance
hpxml.walls[0].solar_absorptance = 0.99
hpxml.walls[0].color = nil
+ hpxml.walls[0].interior_finish_type = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_wall_values(hpxml_default.walls[0], HPXML::SidingTypeWood, 0.99, HPXML::ColorDark, 0.90, HPXML::InteriorFinishGypsumBoard, 0.5, 180)
+
+ # Test defaults w/o Color & SolarAbsorptance
+ hpxml.walls[0].solar_absorptance = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_wall_values(hpxml_default.walls[0], HPXML::SidingTypeWood, 0.7, HPXML::ColorMedium, 0.90, HPXML::InteriorFinishGypsumBoard, 0.5, 180)
+
+ # Test defaults w/ unconditioned space
+ hpxml.walls[1].siding = nil
+ hpxml.walls[1].solar_absorptance = nil
+ hpxml.walls[1].color = HPXML::ColorLight
+ hpxml.walls[1].emittance = nil
+ hpxml.walls[1].interior_finish_type = nil
+ hpxml.walls[1].interior_finish_thickness = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_wall_values(hpxml_default, HPXML::SidingTypeWood, 0.99, HPXML::ColorDark, 0.90)
+ _test_default_wall_values(hpxml_default.walls[1], HPXML::SidingTypeWood, 0.5, HPXML::ColorLight, 0.90, HPXML::InteriorFinishNone, nil, 180)
end
def test_foundation_walls
# Test inputs not overridden by defaults
hpxml = _create_hpxml('base.xml')
hpxml.foundation_walls[0].thickness = 7.0
+ hpxml.foundation_walls[0].interior_finish_type = HPXML::InteriorFinishGypsumCompositeBoard
+ hpxml.foundation_walls[0].interior_finish_thickness = 0.625
+ hpxml.foundation_walls[0].azimuth = 123
+ hpxml.foundation_walls[0].area = 789
+ hpxml.foundation_walls[0].insulation_interior_distance_to_top = 0.5
+ hpxml.foundation_walls[0].insulation_interior_distance_to_bottom = 7.75
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_top = 0.75
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = 7.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_foundation_wall_values(hpxml_default, 7.0)
+ _test_default_foundation_wall_values(hpxml_default.foundation_walls[0], 7.0, HPXML::InteriorFinishGypsumCompositeBoard, 0.625, 123,
+ 789, 0.5, 7.75, 0.75, 7.5)
# Test defaults
hpxml.foundation_walls[0].thickness = nil
+ hpxml.foundation_walls[0].interior_finish_type = nil
+ hpxml.foundation_walls[0].interior_finish_thickness = nil
+ hpxml.foundation_walls[0].orientation = HPXML::OrientationSoutheast
+ hpxml.foundation_walls[0].azimuth = nil
+ hpxml.foundation_walls[0].area = nil
+ hpxml.foundation_walls[0].length = 100
+ hpxml.foundation_walls[0].insulation_interior_distance_to_bottom = nil
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_foundation_wall_values(hpxml_default.foundation_walls[0], 8.0, HPXML::InteriorFinishGypsumBoard, 0.5, 135,
+ 800, 0.5, 8.0, 0.75, 8.0)
+
+ # Test defaults w/ unconditioned surfaces
+ hpxml = _create_hpxml('base-foundation-unconditioned-basement.xml')
+ hpxml.foundation_walls[0].thickness = nil
+ hpxml.foundation_walls[0].interior_finish_type = nil
+ hpxml.foundation_walls[0].interior_finish_thickness = nil
+ hpxml.foundation_walls[0].orientation = HPXML::OrientationSoutheast
+ hpxml.foundation_walls[0].azimuth = nil
+ hpxml.foundation_walls[0].area = nil
+ hpxml.foundation_walls[0].length = 100
+ hpxml.foundation_walls[0].height = 10
+ hpxml.foundation_walls[0].insulation_interior_distance_to_top = nil
+ hpxml.foundation_walls[0].insulation_interior_distance_to_bottom = nil
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_top = nil
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_foundation_wall_values(hpxml_default, 8.0)
+ _test_default_foundation_wall_values(hpxml_default.foundation_walls[0], 8.0, HPXML::InteriorFinishNone, nil, 135,
+ 1000, 0.0, 10.0, 0.0, 10.0)
+ end
+
+ def test_frame_floors
+ # Test inputs not overridden by defaults
+ hpxml = _create_hpxml('base.xml')
+ hpxml.frame_floors[0].interior_finish_type = HPXML::InteriorFinishWood
+ hpxml.frame_floors[0].interior_finish_thickness = 0.375
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_frame_floor_values(hpxml_default.frame_floors[0], HPXML::InteriorFinishWood, 0.375)
+
+ # Test defaults w/ ceiling
+ hpxml.frame_floors[0].interior_finish_type = nil
+ hpxml.frame_floors[0].interior_finish_thickness = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_frame_floor_values(hpxml_default.frame_floors[0], HPXML::InteriorFinishGypsumBoard, 0.5)
+
+ # Test defaults w/ floor
+ hpxml = _create_hpxml('base-foundation-vented-crawlspace.xml')
+ hpxml.frame_floors[1].interior_finish_type = nil
+ hpxml.frame_floors[1].interior_finish_thickness = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_frame_floor_values(hpxml_default.frame_floors[1], HPXML::InteriorFinishNone, nil)
end
def test_slabs
@@ -313,7 +461,7 @@ def test_slabs
hpxml.slabs[0].carpet_fraction = 0.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_slab_values(hpxml_default, 7.0, 1.1, 0.5)
+ _test_default_slab_values(hpxml_default.slabs[0], 7.0, 1.1, 0.5)
# Test defaults w/ conditioned basement
hpxml.slabs[0].thickness = nil
@@ -321,7 +469,7 @@ def test_slabs
hpxml.slabs[0].carpet_fraction = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_slab_values(hpxml_default, 4.0, 2.0, 0.8)
+ _test_default_slab_values(hpxml_default.slabs[0], 4.0, 2.0, 0.8)
# Test defaults w/ crawlspace
hpxml = _create_hpxml('base-foundation-unvented-crawlspace.xml')
@@ -330,7 +478,7 @@ def test_slabs
hpxml.slabs[0].carpet_fraction = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_slab_values(hpxml_default, 0.0, 0.0, 0.0)
+ _test_default_slab_values(hpxml_default.slabs[0], 0.0, 0.0, 0.0)
end
def test_windows
@@ -342,11 +490,12 @@ def test_windows
window.exterior_shading_factor_winter = 0.55
window.interior_shading_factor_summer = 0.66
window.interior_shading_factor_winter = 0.77
+ window.azimuth = 123
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
n_windows = hpxml_default.windows.size
- _test_default_window_values(hpxml_default, [0.44] * n_windows, [0.55] * n_windows, [0.66] * n_windows, [0.77] * n_windows, [0.5] * n_windows)
+ _test_default_window_values(hpxml_default, [0.44] * n_windows, [0.55] * n_windows, [0.66] * n_windows, [0.77] * n_windows, [0.5] * n_windows, [123] * n_windows)
# Test defaults
hpxml.windows.each do |window|
@@ -355,11 +504,13 @@ def test_windows
window.exterior_shading_factor_winter = nil
window.interior_shading_factor_summer = nil
window.interior_shading_factor_winter = nil
+ window.orientation = HPXML::OrientationSouthwest
+ window.azimuth = nil
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
n_windows = hpxml_default.windows.size
- _test_default_window_values(hpxml_default, [1.0] * n_windows, [1.0] * n_windows, [0.7] * n_windows, [0.85] * n_windows, [0.67] * n_windows)
+ _test_default_window_values(hpxml_default, [1.0] * n_windows, [1.0] * n_windows, [0.7] * n_windows, [0.85] * n_windows, [0.67] * n_windows, [225] * n_windows)
end
def test_skylights
@@ -370,11 +521,12 @@ def test_skylights
skylight.exterior_shading_factor_winter = 0.55
skylight.interior_shading_factor_summer = 0.66
skylight.interior_shading_factor_winter = 0.77
+ skylight.azimuth = 123
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
n_skylights = hpxml_default.skylights.size
- _test_default_skylight_values(hpxml_default, [0.44] * n_skylights, [0.55] * n_skylights, [0.66] * n_skylights, [0.77] * n_skylights)
+ _test_default_skylight_values(hpxml_default, [0.44] * n_skylights, [0.55] * n_skylights, [0.66] * n_skylights, [0.77] * n_skylights, [123] * n_skylights)
# Test defaults
hpxml.skylights.each do |skylight|
@@ -382,11 +534,47 @@ def test_skylights
skylight.exterior_shading_factor_winter = nil
skylight.interior_shading_factor_summer = nil
skylight.interior_shading_factor_winter = nil
+ skylight.orientation = HPXML::OrientationWest
+ skylight.azimuth = nil
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
n_skylights = hpxml_default.skylights.size
- _test_default_skylight_values(hpxml_default, [1.0] * n_skylights, [1.0] * n_skylights, [1.0] * n_skylights, [1.0] * n_skylights)
+ _test_default_skylight_values(hpxml_default, [1.0] * n_skylights, [1.0] * n_skylights, [1.0] * n_skylights, [1.0] * n_skylights, [270] * n_skylights)
+ end
+
+ def test_doors
+ # Test inputs not overridden by defaults
+ hpxml = _create_hpxml('base.xml')
+ hpxml.doors.each_with_index do |door, i|
+ door.azimuth = 35 * (i + 1)
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_door_values(hpxml_default, [35, 70])
+
+ # Test defaults w/ AttachedToWall azimuth
+ hpxml.walls[0].azimuth = 89
+ hpxml.doors.each do |door|
+ door.azimuth = nil
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_door_values(hpxml_default, [89, 89])
+
+ # Test defaults w/o AttachedToWall azimuth
+ hpxml.walls[0].azimuth = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_door_values(hpxml_default, [0, 0])
+
+ # Test defaults w/ Orientation
+ hpxml.doors.each do |door|
+ door.orientation = HPXML::OrientationEast
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_door_values(hpxml_default, [90, 90])
end
def test_central_air_conditioners
@@ -398,9 +586,11 @@ def test_central_air_conditioners
hpxml.cooling_systems[0].charge_defect_ratio = -0.11
hpxml.cooling_systems[0].airflow_defect_ratio = -0.22
hpxml.cooling_systems[0].cooling_capacity = 12345
+ hpxml.cooling_systems[0].cooling_efficiency_seer = 12.5
+ hpxml.cooling_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_central_air_conditioner_values(hpxml_default, 0.88, HPXML::HVACCompressorTypeVariableSpeed, 0.66, -0.11, -0.22, 12345)
+ _test_default_central_air_conditioner_values(hpxml_default.cooling_systems[0], 0.88, HPXML::HVACCompressorTypeVariableSpeed, 0.66, -0.11, -0.22, 12345, 12.5)
# Test defaults
hpxml.cooling_systems[0].cooling_shr = nil
@@ -409,9 +599,11 @@ def test_central_air_conditioners
hpxml.cooling_systems[0].charge_defect_ratio = nil
hpxml.cooling_systems[0].airflow_defect_ratio = nil
hpxml.cooling_systems[0].cooling_capacity = nil
+ hpxml.cooling_systems[0].cooling_efficiency_seer = nil
+ hpxml.cooling_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_central_air_conditioner_values(hpxml_default, 0.73, HPXML::HVACCompressorTypeSingleStage, 0.5, 0, 0, nil)
+ _test_default_central_air_conditioner_values(hpxml_default.cooling_systems[0], 0.73, HPXML::HVACCompressorTypeSingleStage, 0.375, 0, 0, nil, 13.76)
end
def test_room_air_conditioners
@@ -419,16 +611,20 @@ def test_room_air_conditioners
hpxml = _create_hpxml('base-hvac-room-ac-only.xml')
hpxml.cooling_systems[0].cooling_shr = 0.88
hpxml.cooling_systems[0].cooling_capacity = 12345
+ hpxml.cooling_systems[0].cooling_efficiency_eer = 12.5
+ hpxml.cooling_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_room_air_conditioner_values(hpxml_default, 0.88, 12345)
+ _test_default_room_air_conditioner_values(hpxml_default.cooling_systems[0], 0.88, 12345, 12.5)
# Test defaults
hpxml.cooling_systems[0].cooling_shr = nil
hpxml.cooling_systems[0].cooling_capacity = nil
+ hpxml.cooling_systems[0].cooling_efficiency_eer = nil
+ hpxml.cooling_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_room_air_conditioner_values(hpxml_default, 0.65, nil)
+ _test_default_room_air_conditioner_values(hpxml_default.cooling_systems[0], 0.65, nil, 9.93)
end
def test_evaporative_coolers
@@ -437,13 +633,13 @@ def test_evaporative_coolers
hpxml.cooling_systems[0].cooling_capacity = 12345
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_evap_cooler_values(hpxml_default, 12345)
+ _test_default_evap_cooler_values(hpxml_default.cooling_systems[0], 12345)
# Test defaults
hpxml.cooling_systems[0].cooling_capacity = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_evap_cooler_values(hpxml_default, nil)
+ _test_default_evap_cooler_values(hpxml_default.cooling_systems[0], nil)
end
def test_mini_split_air_conditioners
@@ -456,7 +652,7 @@ def test_mini_split_air_conditioners
hpxml.cooling_systems[0].cooling_capacity = 12345
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mini_split_air_conditioner_values(hpxml_default, 0.78, 0.66, -0.11, -0.22, 12345)
+ _test_default_mini_split_air_conditioner_values(hpxml_default.cooling_systems[0], 0.78, 0.66, -0.11, -0.22, 12345)
# Test defaults
hpxml.cooling_systems[0].cooling_shr = nil
@@ -466,7 +662,30 @@ def test_mini_split_air_conditioners
hpxml.cooling_systems[0].cooling_capacity = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mini_split_air_conditioner_values(hpxml_default, 0.73, 0.18, 0, 0, nil)
+ _test_default_mini_split_air_conditioner_values(hpxml_default.cooling_systems[0], 0.73, 0.18, 0, 0, nil)
+
+ # Test defaults w/ ductless
+ hpxml.cooling_systems[0].distribution_system.delete
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_mini_split_air_conditioner_values(hpxml_default.cooling_systems[0], 0.73, 0.07, 0, 0, nil)
+ end
+
+ def test_elec_resistance
+ # Test inputs not overridden by defaults
+ hpxml = _create_hpxml('base-hvac-elec-resistance-only.xml')
+ hpxml.heating_systems[0].heating_efficiency_percent = 0.98
+ hpxml.heating_systems[0].year_installed = 2010
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_elec_resistance(hpxml_default.heating_systems[0], 0.98)
+
+ # Test defaults
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 2010
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_elec_resistance(hpxml_default.heating_systems[0], 1.0)
end
def test_furnaces
@@ -475,17 +694,21 @@ def test_furnaces
hpxml.heating_systems[0].fan_watts_per_cfm = 0.66
hpxml.heating_systems[0].airflow_defect_ratio = -0.22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.85
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_furnace_values(hpxml_default, 0.66, -0.22, 12345)
+ _test_default_furnace_values(hpxml_default.heating_systems[0], 0.66, -0.22, 12345, 0.85)
# Test defaults
hpxml.heating_systems[0].fan_watts_per_cfm = nil
hpxml.heating_systems[0].airflow_defect_ratio = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_furnace_values(hpxml_default, 0.375, 0, nil)
+ _test_default_furnace_values(hpxml_default.heating_systems[0], 0.5, 0, nil, 0.848)
# Test defaults w/ gravity distribution system
hpxml = _create_hpxml('base-hvac-furnace-gas-only.xml')
@@ -493,9 +716,10 @@ def test_furnaces
hpxml.heating_systems[0].fan_watts_per_cfm = nil
hpxml.heating_systems[0].airflow_defect_ratio = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_furnace_values(hpxml_default, 0.0, 0, nil)
+ _test_default_furnace_values(hpxml_default.heating_systems[0], 0.0, 0, nil, 0.92)
end
def test_wall_furnaces
@@ -503,16 +727,20 @@ def test_wall_furnaces
hpxml = _create_hpxml('base-hvac-wall-furnace-elec-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.60
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_wall_furnace_values(hpxml_default, 22, 12345)
+ _test_default_wall_furnace_values(hpxml_default.heating_systems[0], 22, 12345, 0.60)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_wall_furnace_values(hpxml_default, 0, nil)
+ _test_default_wall_furnace_values(hpxml_default.heating_systems[0], 0, nil, 0.98)
end
def test_floor_furnaces
@@ -520,15 +748,19 @@ def test_floor_furnaces
hpxml = _create_hpxml('base-hvac-floor-furnace-propane-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.60
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_floor_furnace_values(hpxml_default, 22, 12345)
+ _test_default_floor_furnace_values(hpxml_default.heating_systems[0], 22, 12345, 0.60)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_floor_furnace_values(hpxml_default, 0, nil)
+ _test_default_floor_furnace_values(hpxml_default.heating_systems[0], 0, nil, 0.595)
end
def test_boilers
@@ -536,30 +768,38 @@ def test_boilers
hpxml = _create_hpxml('base-hvac-boiler-gas-only.xml')
hpxml.heating_systems[0].electric_auxiliary_energy = 99.9
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.85
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_boiler_values(hpxml_default, 99.9, 12345)
+ _test_default_boiler_values(hpxml_default.heating_systems[0], 99.9, 12345, 0.85)
# Test defaults w/ in-unit boiler
hpxml.heating_systems[0].electric_auxiliary_energy = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_boiler_values(hpxml_default, 170.0, nil)
+ _test_default_boiler_values(hpxml_default.heating_systems[0], 170.0, nil, 0.797)
# Test inputs not overridden by defaults (shared boiler)
hpxml = _create_hpxml('base-bldgtype-multifamily-shared-boiler-only-baseboard.xml')
hpxml.heating_systems[0].shared_loop_watts = nil
hpxml.heating_systems[0].electric_auxiliary_energy = 99.9
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.85
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_boiler_values(hpxml_default, 99.9, nil)
+ _test_default_boiler_values(hpxml_default.heating_systems[0], 99.9, nil, 0.85)
# Test defaults w/ shared boiler
hpxml.heating_systems[0].electric_auxiliary_energy = nil
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_boiler_values(hpxml_default, 220.0, nil)
+ _test_default_boiler_values(hpxml_default.heating_systems[0], 220.0, nil, 0.723)
end
def test_stoves
@@ -567,16 +807,20 @@ def test_stoves
hpxml = _create_hpxml('base-hvac-stove-oil-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_percent = 0.70
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_stove_values(hpxml_default, 22, 12345)
+ _test_default_stove_values(hpxml_default.heating_systems[0], 22, 12345, 0.70)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 1980
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_stove_values(hpxml_default, 40, nil)
+ _test_default_stove_values(hpxml_default.heating_systems[0], 40, nil, 0.81)
end
def test_portable_heaters
@@ -584,16 +828,20 @@ def test_portable_heaters
hpxml = _create_hpxml('base-hvac-portable-heater-gas-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_percent = 0.65
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_portable_heater_values(hpxml_default, 22, 12345)
+ _test_default_portable_heater_values(hpxml_default.heating_systems[0], 22, 12345, 0.65)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_portable_heater_values(hpxml_default, 0, nil)
+ _test_default_portable_heater_values(hpxml_default.heating_systems[0], 0, nil, 0.81)
end
def test_fixed_heaters
@@ -601,16 +849,20 @@ def test_fixed_heaters
hpxml = _create_hpxml('base-hvac-fixed-heater-gas-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_percent = 0.60
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_fixed_heater_values(hpxml_default, 22, 12345)
+ _test_default_fixed_heater_values(hpxml_default.heating_systems[0], 22, 12345, 0.60)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_fixed_heater_values(hpxml_default, 0, nil)
+ _test_default_fixed_heater_values(hpxml_default.heating_systems[0], 0, nil, 0.81)
end
def test_fireplaces
@@ -618,16 +870,30 @@ def test_fireplaces
hpxml = _create_hpxml('base-hvac-fireplace-wood-only.xml')
hpxml.heating_systems[0].fan_watts = 22
hpxml.heating_systems[0].heating_capacity = 12345
+ hpxml.heating_systems[0].heating_efficiency_percent = 0.50
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_fireplace_values(hpxml_default, 22, 12345)
+ _test_default_fireplace_values(hpxml_default.heating_systems[0], 22, 12345, 0.50)
# Test defaults
hpxml.heating_systems[0].fan_watts = nil
hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_fireplace_values(hpxml_default, 0, nil)
+ _test_default_fireplace_values(hpxml_default.heating_systems[0], 0, nil, 0.60)
+
+ # Test defaults with electric fireplace
+ hpxml.heating_systems[0].heating_system_fuel = HPXML::FuelTypeElectricity
+ hpxml.heating_systems[0].fan_watts = nil
+ hpxml.heating_systems[0].heating_capacity = nil
+ hpxml.heating_systems[0].heating_efficiency_percent = nil
+ hpxml.heating_systems[0].year_installed = 2010
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_fireplace_values(hpxml_default.heating_systems[0], 0, nil, 1.0)
end
def test_air_source_heat_pumps
@@ -642,9 +908,12 @@ def test_air_source_heat_pumps
hpxml.heat_pumps[0].heating_capacity = 23456
hpxml.heat_pumps[0].heating_capacity_17F = 9876
hpxml.heat_pumps[0].backup_heating_capacity = 34567
+ hpxml.heat_pumps[0].cooling_efficiency_seer = 14.0
+ hpxml.heat_pumps[0].heating_efficiency_hspf = 8.0
+ hpxml.heat_pumps[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_air_to_air_heat_pump_values(hpxml_default, 0.88, HPXML::HVACCompressorTypeVariableSpeed, 0.66, -0.11, -0.22, 12345, 23456, 9876, 34567)
+ _test_default_air_to_air_heat_pump_values(hpxml_default.heat_pumps[0], 0.88, HPXML::HVACCompressorTypeVariableSpeed, 0.66, -0.11, -0.22, 12345, 23456, 9876, 34567, 14.0, 8.0)
# Test defaults
hpxml.heat_pumps[0].cooling_shr = nil
@@ -656,9 +925,12 @@ def test_air_source_heat_pumps
hpxml.heat_pumps[0].heating_capacity = nil
hpxml.heat_pumps[0].heating_capacity_17F = nil
hpxml.heat_pumps[0].backup_heating_capacity = nil
+ hpxml.heat_pumps[0].cooling_efficiency_seer = nil
+ hpxml.heat_pumps[0].heating_efficiency_hspf = nil
+ hpxml.heat_pumps[0].year_installed = 2010
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_air_to_air_heat_pump_values(hpxml_default, 0.73, HPXML::HVACCompressorTypeSingleStage, 0.5, 0, 0, nil, nil, nil, nil)
+ _test_default_air_to_air_heat_pump_values(hpxml_default.heat_pumps[0], 0.73, HPXML::HVACCompressorTypeSingleStage, 0.5, 0, 0, nil, nil, nil, nil, 13.76, 7.9)
end
def test_mini_split_heat_pumps
@@ -674,7 +946,7 @@ def test_mini_split_heat_pumps
hpxml.heat_pumps[0].backup_heating_capacity = 34567
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mini_split_heat_pump_values(hpxml_default, 0.78, 0.66, -0.11, -0.22, 12345, 23456, 9876, 34567)
+ _test_default_mini_split_heat_pump_values(hpxml_default.heat_pumps[0], 0.78, 0.66, -0.11, -0.22, 12345, 23456, 9876, 34567)
# Test defaults
hpxml.heat_pumps[0].cooling_shr = nil
@@ -687,7 +959,13 @@ def test_mini_split_heat_pumps
hpxml.heat_pumps[0].backup_heating_capacity = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mini_split_heat_pump_values(hpxml_default, 0.73, 0.18, 0, 0, nil, nil, nil, nil)
+ _test_default_mini_split_heat_pump_values(hpxml_default.heat_pumps[0], 0.73, 0.18, 0, 0, nil, nil, nil, nil)
+
+ # Test defaults w/ ductless
+ hpxml.heat_pumps[0].distribution_system.delete
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_mini_split_heat_pump_values(hpxml_default.heat_pumps[0], 0.73, 0.07, 0, 0, nil, nil, nil, nil)
end
def test_ground_source_heat_pumps
@@ -701,7 +979,7 @@ def test_ground_source_heat_pumps
hpxml.heat_pumps[0].backup_heating_capacity = 34567
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_ground_to_air_heat_pump_values(hpxml_default, 9.9, 0.66, -0.22, 12345, 23456, 34567)
+ _test_default_ground_to_air_heat_pump_values(hpxml_default.heat_pumps[0], 9.9, 0.66, -0.22, 12345, 23456, 34567)
# Test defaults
hpxml.heat_pumps[0].pump_watts_per_ton = nil
@@ -712,7 +990,7 @@ def test_ground_source_heat_pumps
hpxml.heat_pumps[0].backup_heating_capacity = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_ground_to_air_heat_pump_values(hpxml_default, 30.0, 0.375, 0, nil, nil, nil)
+ _test_default_ground_to_air_heat_pump_values(hpxml_default.heat_pumps[0], 30.0, 0.375, 0, nil, nil, nil)
end
def test_hvac_increased_hardsized_equipment
@@ -759,7 +1037,7 @@ def test_hvac_controls
hpxml.hvac_controls[0].seasons_cooling_end_day = 31
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_hvac_control_values(hpxml_default, 12, 12, 1, 1, 6, 30, 7, 1, 12, 31)
+ _test_default_hvac_control_values(hpxml_default.hvac_controls[0], 12, 12, 1, 1, 6, 30, 7, 1, 12, 31)
# Test defaults
hpxml.hvac_controls[0].heating_setback_start_hour = nil
@@ -774,7 +1052,7 @@ def test_hvac_controls
hpxml.hvac_controls[0].seasons_cooling_end_day = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_hvac_control_values(hpxml_default, 23, 9, 1, 1, 12, 31, 1, 1, 12, 31)
+ _test_default_hvac_control_values(hpxml_default.hvac_controls[0], 23, 9, 1, 1, 12, 31, 1, 1, 12, 31)
end
def test_hvac_distribution
@@ -786,10 +1064,11 @@ def test_hvac_distribution
expected_return_locations = ['attic - unvented']
expected_supply_areas = [150.0]
expected_return_areas = [50.0]
- expected_area_fracs = [1.0]
+ expected_supply_fracs = [1.0]
+ expected_return_fracs = [1.0]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ conditioned basement
hpxml.hvac_distributions[0].number_of_return_registers = nil
@@ -805,10 +1084,11 @@ def test_hvac_distribution
expected_return_locations = ['basement - conditioned']
expected_supply_areas = [729.0]
expected_return_areas = [270.0]
- expected_area_fracs = [1.0]
+ expected_supply_fracs = [1.0]
+ expected_return_fracs = [1.0]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ multiple foundations
hpxml = _create_hpxml('base-foundation-multiple.xml')
@@ -824,10 +1104,11 @@ def test_hvac_distribution
expected_return_locations = ['basement - unconditioned']
expected_supply_areas = [364.5]
expected_return_areas = [67.5]
- expected_area_fracs = [1.0]
+ expected_supply_fracs = [1.0]
+ expected_return_fracs = [1.0]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ foundation exposed to ambient
hpxml = _create_hpxml('base-foundation-ambient.xml')
@@ -843,10 +1124,11 @@ def test_hvac_distribution
expected_return_locations = ['attic - unvented']
expected_supply_areas = [364.5]
expected_return_areas = [67.5]
- expected_area_fracs = [1.0]
+ expected_supply_fracs = [1.0]
+ expected_return_fracs = [1.0]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ building/unit adjacent to other housing unit
hpxml = _create_hpxml('base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml')
@@ -862,10 +1144,11 @@ def test_hvac_distribution
expected_return_locations = ['living space']
expected_supply_areas = [243.0]
expected_return_areas = [45.0]
- expected_area_fracs = [1.0]
+ expected_supply_fracs = [1.0]
+ expected_return_fracs = [1.0]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ 2-story building
hpxml = _create_hpxml('base-enclosure-2stories.xml')
@@ -877,14 +1160,15 @@ def test_hvac_distribution
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- expected_supply_locations = ['basement - conditioned', 'living space']
- expected_return_locations = ['basement - conditioned', 'living space']
- expected_supply_areas = [820.13, 273.38]
- expected_return_areas = [455.63, 151.88]
- expected_area_fracs = [0.75, 0.25]
+ expected_supply_locations = ['basement - conditioned', 'basement - conditioned', 'living space', 'living space']
+ expected_return_locations = ['basement - conditioned', 'basement - conditioned', 'living space', 'living space']
+ expected_supply_areas = [410.06, 410.06, 136.69, 136.69]
+ expected_return_areas = [227.82, 227.82, 75.94, 75.94]
+ expected_supply_fracs = [0.375, 0.375, 0.125, 0.125]
+ expected_return_fracs = [0.375, 0.375, 0.125, 0.125]
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ 1-story building & multiple HVAC systems
hpxml = _create_hpxml('base-hvac-multiple.xml')
@@ -900,10 +1184,11 @@ def test_hvac_distribution
expected_return_locations = ['basement - conditioned', 'basement - conditioned'] * hpxml_default.hvac_distributions.size
expected_supply_areas = [36.45, 36.45] * hpxml_default.hvac_distributions.size
expected_return_areas = [13.5, 13.5] * hpxml_default.hvac_distributions.size
- expected_area_fracs = [0.5, 0.5] * hpxml_default.hvac_distributions.size
+ expected_supply_fracs = [0.5, 0.5] * hpxml_default.hvac_distributions.size
+ expected_return_fracs = [0.5, 0.5] * hpxml_default.hvac_distributions.size
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
# Test defaults w/ 2-story building & multiple HVAC systems
hpxml = _create_hpxml('base-hvac-multiple.xml')
@@ -920,14 +1205,43 @@ def test_hvac_distribution
expected_return_locations = ['basement - conditioned', 'basement - conditioned', 'living space', 'living space'] * hpxml_default.hvac_distributions.size
expected_supply_areas = [27.34, 27.34, 9.11, 9.11] * hpxml_default.hvac_distributions.size
expected_return_areas = [10.13, 10.13, 3.38, 3.38] * hpxml_default.hvac_distributions.size
- expected_area_fracs = [0.375, 0.375, 0.125, 0.125] * hpxml_default.hvac_distributions.size
+ expected_supply_fracs = [0.375, 0.375, 0.125, 0.125] * hpxml_default.hvac_distributions.size
+ expected_return_fracs = [0.375, 0.375, 0.125, 0.125] * hpxml_default.hvac_distributions.size
expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
_test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
- expected_area_fracs, expected_n_return_registers)
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
+
+ # Test defaults w/ 2-story building & multiple HVAC systems & duct area fractions
+ hpxml = _create_hpxml('base-hvac-multiple.xml')
+ hpxml.building_construction.number_of_conditioned_floors_above_grade = 2
+ hpxml.hvac_distributions.each do |hvac_distribution|
+ next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
+
+ hvac_distribution.ducts[0].duct_fraction_area = 0.75
+ hvac_distribution.ducts[1].duct_fraction_area = 0.25
+ hvac_distribution.ducts[2].duct_fraction_area = 0.5
+ hvac_distribution.ducts[3].duct_fraction_area = 0.5
+ end
+ hpxml.hvac_distributions.each do |hvac_distribution|
+ hvac_distribution.ducts.each do |duct|
+ duct.duct_surface_area = nil
+ end
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ expected_supply_locations = ['attic - unvented', 'outside', 'attic - unvented', 'outside'] * hpxml_default.hvac_distributions.size
+ expected_return_locations = ['attic - unvented', 'outside', 'attic - unvented', 'outside'] * hpxml_default.hvac_distributions.size
+ expected_supply_areas = [54.68, 18.23] * hpxml_default.hvac_distributions.size
+ expected_return_areas = [13.5, 13.5] * hpxml_default.hvac_distributions.size
+ expected_supply_fracs = [0.75, 0.25] * hpxml_default.hvac_distributions.size
+ expected_return_fracs = [0.5, 0.5] * hpxml_default.hvac_distributions.size
+ expected_n_return_registers = hpxml_default.building_construction.number_of_conditioned_floors
+ _test_default_duct_values(hpxml_default, expected_supply_locations, expected_return_locations, expected_supply_areas, expected_return_areas,
+ expected_supply_fracs, expected_return_fracs, expected_n_return_registers)
end
def test_mech_ventilation_fans
- # Test inputs not overridden by defaults
+ # Test inputs not overridden by defaults w/ shared exhaust system
hpxml = _create_hpxml('base-mechvent-exhaust.xml')
hpxml.building_construction.residential_facility_type = HPXML::ResidentialTypeSFA
vent_fan = hpxml.ventilation_fans.select { |f| f.used_for_whole_building_ventilation }[0]
@@ -935,9 +1249,10 @@ def test_mech_ventilation_fans
vent_fan.fraction_recirculation = 0.0
vent_fan.in_unit_flow_rate = 10.0
vent_fan.hours_in_operation = 22.0
+ vent_fan.fan_power = 12.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mech_vent_values(hpxml_default, true, 22.0)
+ _test_default_mech_vent_values(hpxml_default, true, 22.0, 12.5)
# Test defaults
vent_fan.rated_flow_rate = nil
@@ -947,25 +1262,46 @@ def test_mech_ventilation_fans
vent_fan.fraction_recirculation = nil
vent_fan.in_unit_flow_rate = nil
vent_fan.hours_in_operation = nil
+ vent_fan.fan_power = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mech_vent_values(hpxml_default, false, 24.0)
+ _test_default_mech_vent_values(hpxml_default, false, 24.0, 38.5)
# Test inputs not overridden by defaults w/ CFIS
hpxml = _create_hpxml('base-mechvent-cfis.xml')
vent_fan = hpxml.ventilation_fans.select { |f| f.used_for_whole_building_ventilation }[0]
vent_fan.is_shared_system = false
vent_fan.hours_in_operation = 12.0
+ vent_fan.fan_power = 12.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mech_vent_values(hpxml_default, false, 12.0)
+ _test_default_mech_vent_values(hpxml_default, false, 12.0, 12.5)
# Test defaults w/ CFIS
vent_fan.is_shared_system = nil
vent_fan.hours_in_operation = nil
+ vent_fan.fan_power = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_mech_vent_values(hpxml_default, false, 8.0)
+ _test_default_mech_vent_values(hpxml_default, false, 8.0, 165.0)
+
+ # Test inputs not overridden by defaults w/ ERV
+ hpxml = _create_hpxml('base-mechvent-erv.xml')
+ vent_fan = hpxml.ventilation_fans.select { |f| f.used_for_whole_building_ventilation }[0]
+ vent_fan.is_shared_system = false
+ vent_fan.hours_in_operation = 20.0
+ vent_fan.fan_power = 45.0
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_mech_vent_values(hpxml_default, false, 20.0, 45.0)
+
+ # Test defaults w/ CFIS
+ vent_fan.is_shared_system = nil
+ vent_fan.hours_in_operation = nil
+ vent_fan.fan_power = nil
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ _test_default_mech_vent_values(hpxml_default, false, 24.0, 110.0)
end
def test_local_ventilation_fans
@@ -1017,11 +1353,13 @@ def test_storage_water_heaters
wh.recovery_efficiency = 0.95
wh.location = HPXML::LocationLivingSpace
wh.temperature = 111
+ wh.energy_factor = 0.90
+ wh.year_installed = 2003
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
_test_default_storage_water_heater_values(hpxml_default,
- [true, 15000.0, 40.0, 0.95, HPXML::LocationLivingSpace, 111])
+ [true, 15000.0, 40.0, 0.95, HPXML::LocationLivingSpace, 111, 0.90])
# Test defaults w/ 3-bedroom house & electric storage water heater
hpxml.water_heating_systems.each do |wh|
@@ -1031,11 +1369,13 @@ def test_storage_water_heaters
wh.recovery_efficiency = nil
wh.location = nil
wh.temperature = nil
+ wh.energy_factor = nil
+ wh.year_installed = 2003
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
_test_default_storage_water_heater_values(hpxml_default,
- [false, 18766.7, 50.0, 0.98, HPXML::LocationBasementConditioned, 125])
+ [false, 18766.7, 50.0, 0.98, HPXML::LocationBasementConditioned, 125, 0.857])
# Test defaults w/ 5-bedroom house & electric storage water heater
hpxml = _create_hpxml('base-enclosure-beds-5.xml')
@@ -1046,11 +1386,13 @@ def test_storage_water_heaters
wh.recovery_efficiency = nil
wh.location = nil
wh.temperature = nil
+ wh.energy_factor = nil
+ wh.year_installed = 2010
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
_test_default_storage_water_heater_values(hpxml_default,
- [false, 18766.7, 66.0, 0.98, HPXML::LocationBasementConditioned, 125])
+ [false, 18766.7, 66.0, 0.98, HPXML::LocationBasementConditioned, 125, 0.90])
# Test defaults w/ 3-bedroom house & 2 storage water heaters (1 electric and 1 natural gas)
hpxml = _create_hpxml('base-dhw-multiple.xml')
@@ -1063,12 +1405,45 @@ def test_storage_water_heaters
wh.recovery_efficiency = nil
wh.location = nil
wh.temperature = nil
+ wh.energy_factor = nil
+ wh.year_installed = 2010
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
_test_default_storage_water_heater_values(hpxml_default,
- [false, 15354.6, 50.0, 0.98, HPXML::LocationBasementConditioned, 125],
- [false, 36000.0, 40.0, 0.756, HPXML::LocationBasementConditioned, 125])
+ [false, 15354.6, 50.0, 0.98, HPXML::LocationBasementConditioned, 125, 0.90],
+ [false, 36000.0, 40.0, 0.746, HPXML::LocationBasementConditioned, 125, 0.55])
+
+ # Test inputs not overridden by defaults w/ UEF
+ hpxml = _create_hpxml('base-dhw-tank-gas-uef.xml')
+ hpxml.water_heating_systems.each do |wh|
+ wh.first_hour_rating = nil
+ wh.usage_bin = HPXML::WaterHeaterUsageBinVerySmall
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ assert_nil(hpxml_default.water_heating_systems[0].first_hour_rating)
+ assert_equal(HPXML::WaterHeaterUsageBinVerySmall, hpxml_default.water_heating_systems[0].usage_bin)
+
+ # Test defaults w/ UEF & FHR
+ hpxml.water_heating_systems.each do |wh|
+ wh.first_hour_rating = 40
+ wh.usage_bin = nil
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ assert_equal(40, hpxml_default.water_heating_systems[0].first_hour_rating)
+ assert_equal(HPXML::WaterHeaterUsageBinLow, hpxml_default.water_heating_systems[0].usage_bin)
+
+ # Test defaults w/ UEF & no FHR
+ hpxml.water_heating_systems.each do |wh|
+ wh.first_hour_rating = nil
+ wh.usage_bin = nil
+ end
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ hpxml_default = _test_measure()
+ assert_nil(hpxml_default.water_heating_systems[0].first_hour_rating)
+ assert_equal(HPXML::WaterHeaterUsageBinMedium, hpxml_default.water_heating_systems[0].usage_bin)
end
def test_tankless_water_heaters
@@ -1100,7 +1475,7 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = 2.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_standard_distribution_values(hpxml_default, 50.0, 2.5)
+ _test_default_standard_distribution_values(hpxml_default.hot_water_distributions[0], 50.0, 2.5)
# Test inputs not overridden by defaults -- recirculation
hpxml = _create_hpxml('base-dhw-recirc-demand.xml')
@@ -1108,14 +1483,14 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = 2.5
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_recirc_distribution_values(hpxml_default, 50.0, 50.0, 65.0, 2.5)
+ _test_default_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 50.0, 50.0, 65.0, 2.5)
# Test inputs not overridden by defaults -- shared recirculation
hpxml = _create_hpxml('base-bldgtype-multifamily-shared-water-heater-recirc.xml')
hpxml.hot_water_distributions[0].shared_recirculation_pump_power = 333.0
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_shared_recirc_distribution_values(hpxml_default, 333.0)
+ _test_default_shared_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 333.0)
# Test defaults w/ conditioned basement
hpxml = _create_hpxml('base.xml')
@@ -1123,7 +1498,7 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_standard_distribution_values(hpxml_default, 93.48, 0.0)
+ _test_default_standard_distribution_values(hpxml_default.hot_water_distributions[0], 93.48, 0.0)
# Test defaults w/ unconditioned basement
hpxml = _create_hpxml('base-foundation-unconditioned-basement.xml')
@@ -1131,7 +1506,7 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_standard_distribution_values(hpxml_default, 88.48, 0.0)
+ _test_default_standard_distribution_values(hpxml_default.hot_water_distributions[0], 88.48, 0.0)
# Test defaults w/ 2-story building
hpxml = _create_hpxml('base-enclosure-2stories.xml')
@@ -1139,7 +1514,7 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_standard_distribution_values(hpxml_default, 103.48, 0.0)
+ _test_default_standard_distribution_values(hpxml_default.hot_water_distributions[0], 103.48, 0.0)
# Test defaults w/ recirculation & conditioned basement
hpxml = _create_hpxml('base-dhw-recirc-demand.xml')
@@ -1149,7 +1524,7 @@ def test_hot_water_distribution
hpxml.hot_water_distributions[0].pipe_r_value = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_recirc_distribution_values(hpxml_default, 166.96, 10.0, 50.0, 0.0)
+ _test_default_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 166.96, 10.0, 50.0, 0.0)
# Test defaults w/ recirculation & unconditioned basement
hpxml = _create_hpxml('base-foundation-unconditioned-basement.xml')
@@ -1159,7 +1534,7 @@ def test_hot_water_distribution
recirculation_control_type: HPXML::DHWRecirControlTypeSensor)
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_recirc_distribution_values(hpxml_default, 156.96, 10.0, 50.0, 0.0)
+ _test_default_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 156.96, 10.0, 50.0, 0.0)
# Test defaults w/ recirculation & 2-story building
hpxml = _create_hpxml('base-enclosure-2stories.xml')
@@ -1169,14 +1544,14 @@ def test_hot_water_distribution
recirculation_control_type: HPXML::DHWRecirControlTypeSensor)
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_recirc_distribution_values(hpxml_default, 186.96, 10.0, 50.0, 0.0)
+ _test_default_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 186.96, 10.0, 50.0, 0.0)
# Test defaults w/ shared recirculation
hpxml = _create_hpxml('base-bldgtype-multifamily-shared-water-heater-recirc.xml')
hpxml.hot_water_distributions[0].shared_recirculation_pump_power = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_shared_recirc_distribution_values(hpxml_default, 220.0)
+ _test_default_shared_recirc_distribution_values(hpxml_default.hot_water_distributions[0], 220.0)
end
def test_water_fixtures
@@ -1198,22 +1573,25 @@ def test_solar_thermal_systems
# Test inputs not overridden by defaults
hpxml = _create_hpxml('base-dhw-solar-direct-flat-plate.xml')
hpxml.solar_thermal_systems[0].storage_volume = 55.0
+ hpxml.solar_thermal_systems[0].collector_azimuth = 123
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_solar_thermal_values(hpxml_default, 55.0)
+ _test_default_solar_thermal_values(hpxml_default.solar_thermal_systems[0], 55.0, 123)
# Test defaults w/ collector area of 40 sqft
hpxml.solar_thermal_systems[0].storage_volume = nil
+ hpxml.solar_thermal_systems[0].collector_orientation = HPXML::OrientationNorth
+ hpxml.solar_thermal_systems[0].collector_azimuth = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_solar_thermal_values(hpxml_default, 60.0)
+ _test_default_solar_thermal_values(hpxml_default.solar_thermal_systems[0], 60.0, 0)
# Test defaults w/ collector area of 100 sqft
hpxml.solar_thermal_systems[0].collector_area = 100.0
hpxml.solar_thermal_systems[0].storage_volume = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_solar_thermal_values(hpxml_default, 150.0)
+ _test_default_solar_thermal_values(hpxml_default.solar_thermal_systems[0], 150.0, 0)
end
def test_pv_systems
@@ -1228,10 +1606,11 @@ def test_pv_systems
pv.location = HPXML::LocationGround
pv.tracking = HPXML::PVTrackingType1Axis
pv.module_type = HPXML::PVModuleTypePremium
+ pv.array_azimuth = 123
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pv_system_values(hpxml_default, 0.90, 0.20, true, HPXML::LocationGround, HPXML::PVTrackingType1Axis, HPXML::PVModuleTypePremium)
+ _test_default_pv_system_values(hpxml_default, 0.90, 0.20, true, HPXML::LocationGround, HPXML::PVTrackingType1Axis, HPXML::PVModuleTypePremium, 123)
# Test defaults w/o year modules manufactured
hpxml.pv_systems.each do |pv|
@@ -1241,10 +1620,12 @@ def test_pv_systems
pv.location = nil
pv.tracking = nil
pv.module_type = nil
+ pv.array_orientation = HPXML::OrientationSoutheast
+ pv.array_azimuth = nil
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pv_system_values(hpxml_default, 0.96, 0.14, false, HPXML::LocationRoof, HPXML::PVTrackingTypeFixed, HPXML::PVModuleTypeStandard)
+ _test_default_pv_system_values(hpxml_default, 0.96, 0.14, false, HPXML::LocationRoof, HPXML::PVTrackingTypeFixed, HPXML::PVModuleTypeStandard, 135)
# Test defaults w/ year modules manufactured
hpxml.pv_systems.each do |pv|
@@ -1252,7 +1633,7 @@ def test_pv_systems
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pv_system_values(hpxml_default, 0.96, 0.186, false, HPXML::LocationRoof, HPXML::PVTrackingTypeFixed, HPXML::PVModuleTypeStandard)
+ _test_default_pv_system_values(hpxml_default, 0.96, 0.186, false, HPXML::LocationRoof, HPXML::PVTrackingTypeFixed, HPXML::PVModuleTypeStandard, 135)
end
def test_generators
@@ -1289,7 +1670,7 @@ def test_clothes_washers
hpxml.clothes_washers[0].water_heating_system_idref = hpxml.water_heating_systems[0].id
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_washer_values(hpxml_default, true, HPXML::LocationBasementConditioned, 1.21, 380.0, 0.12, 1.09, 27.0, 3.2, 6.0, 1.5)
+ _test_default_clothes_washer_values(hpxml_default.clothes_washers[0], true, HPXML::LocationBasementConditioned, 1.21, 380.0, 0.12, 1.09, 27.0, 3.2, 6.0, 1.5)
# Test defaults
hpxml.clothes_washers[0].is_shared_appliance = nil
@@ -1304,7 +1685,7 @@ def test_clothes_washers
hpxml.clothes_washers[0].usage_multiplier = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_washer_values(hpxml_default, false, HPXML::LocationLivingSpace, 1.0, 400.0, 0.12, 1.09, 27.0, 3.0, 6.0, 1.0)
+ _test_default_clothes_washer_values(hpxml_default.clothes_washers[0], false, HPXML::LocationLivingSpace, 1.0, 400.0, 0.12, 1.09, 27.0, 3.0, 6.0, 1.0)
# Test defaults before 301-2019 Addendum A
hpxml = _create_hpxml('base.xml')
@@ -1321,7 +1702,7 @@ def test_clothes_washers
hpxml.clothes_washers[0].usage_multiplier = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_washer_values(hpxml_default, false, HPXML::LocationLivingSpace, 0.331, 704.0, 0.08, 0.58, 23.0, 2.874, 999, 1.0)
+ _test_default_clothes_washer_values(hpxml_default.clothes_washers[0], false, HPXML::LocationLivingSpace, 0.331, 704.0, 0.08, 0.58, 23.0, 2.874, 999, 1.0)
end
def test_clothes_dryers
@@ -1337,7 +1718,7 @@ def test_clothes_dryers
hpxml.clothes_dryers[0].usage_multiplier = 1.1
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_values(hpxml_default, true, HPXML::LocationBasementConditioned, 3.33, 1.1)
+ _test_default_clothes_dryer_values(hpxml_default.clothes_dryers[0], true, HPXML::LocationBasementConditioned, 3.33, 1.1)
# Test defaults w/ electric clothes dryer
hpxml.clothes_dryers[0].location = nil
@@ -1346,26 +1727,26 @@ def test_clothes_dryers
hpxml.clothes_dryers[0].usage_multiplier = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_values(hpxml_default, false, HPXML::LocationLivingSpace, 3.01, 1.0)
+ _test_default_clothes_dryer_values(hpxml_default.clothes_dryers[0], false, HPXML::LocationLivingSpace, 3.01, 1.0)
# Test defaults w/ gas clothes dryer
hpxml.clothes_dryers[0].fuel_type = HPXML::FuelTypeNaturalGas
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_values(hpxml_default, false, HPXML::LocationLivingSpace, 3.01, 1.0)
+ _test_default_clothes_dryer_values(hpxml_default.clothes_dryers[0], false, HPXML::LocationLivingSpace, 3.01, 1.0)
# Test defaults w/ electric clothes dryer before 301-2019 Addendum A
hpxml.header.eri_calculation_version = '2019'
hpxml.clothes_dryers[0].fuel_type = HPXML::FuelTypeElectricity
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_values(hpxml_default, false, HPXML::LocationLivingSpace, 2.62, 1.0)
+ _test_default_clothes_dryer_values(hpxml_default.clothes_dryers[0], false, HPXML::LocationLivingSpace, 2.62, 1.0)
# Test defaults w/ gas clothes dryer before 301-2019 Addendum A
hpxml.clothes_dryers[0].fuel_type = HPXML::FuelTypeNaturalGas
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_values(hpxml_default, false, HPXML::LocationLivingSpace, 2.32, 1.0)
+ _test_default_clothes_dryer_values(hpxml_default.clothes_dryers[0], false, HPXML::LocationLivingSpace, 2.32, 1.0)
end
def test_clothes_dryer_exhaust
@@ -1377,21 +1758,21 @@ def test_clothes_dryer_exhaust
clothes_dryer.vented_flow_rate = 200
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_exhaust_values(hpxml_default, true, 200)
+ _test_default_clothes_dryer_exhaust_values(hpxml_default.clothes_dryers[0], true, 200)
# Test inputs not overridden by defaults w/ unvented dryer
clothes_dryer.is_vented = false
clothes_dryer.vented_flow_rate = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_exhaust_values(hpxml_default, false, nil)
+ _test_default_clothes_dryer_exhaust_values(hpxml_default.clothes_dryers[0], false, nil)
# Test defaults
clothes_dryer.is_vented = nil
clothes_dryer.vented_flow_rate = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_clothes_dryer_exhaust_values(hpxml_default, true, 100)
+ _test_default_clothes_dryer_exhaust_values(hpxml_default.clothes_dryers[0], true, 100)
end
def test_dishwashers
@@ -1407,7 +1788,7 @@ def test_dishwashers
hpxml.dishwashers[0].water_heating_system_idref = hpxml.water_heating_systems[0].id
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_dishwasher_values(hpxml_default, true, HPXML::LocationBasementConditioned, 307.0, 0.12, 1.09, 22.32, 4.0, 12, 1.3)
+ _test_default_dishwasher_values(hpxml_default.dishwashers[0], true, HPXML::LocationBasementConditioned, 307.0, 0.12, 1.09, 22.32, 4.0, 12, 1.3)
# Test defaults
hpxml.dishwashers[0].is_shared_appliance = nil
@@ -1421,13 +1802,13 @@ def test_dishwashers
hpxml.dishwashers[0].usage_multiplier = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_dishwasher_values(hpxml_default, false, HPXML::LocationLivingSpace, 467.0, 0.12, 1.09, 33.12, 4.0, 12, 1.0)
+ _test_default_dishwasher_values(hpxml_default.dishwashers[0], false, HPXML::LocationLivingSpace, 467.0, 0.12, 1.09, 33.12, 4.0, 12, 1.0)
# Test defaults before 301-2019 Addendum A
hpxml.header.eri_calculation_version = '2019'
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_dishwasher_values(hpxml_default, false, HPXML::LocationLivingSpace, 467.0, 999, 999, 999, 999, 12, 1.0)
+ _test_default_dishwasher_values(hpxml_default.dishwashers[0], false, HPXML::LocationLivingSpace, 467.0, 999, 999, 999, 999, 12, 1.0)
end
def test_refrigerators
@@ -1536,7 +1917,7 @@ def test_cooking_ranges
hpxml.cooking_ranges[0].monthly_multipliers = ConstantMonthSchedule
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_cooking_range_values(hpxml_default, HPXML::LocationBasementConditioned, true, 1.1, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
+ _test_default_cooking_range_values(hpxml_default.cooking_ranges[0], HPXML::LocationBasementConditioned, true, 1.1, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
# Test defaults
hpxml.cooking_ranges[0].location = nil
@@ -1547,13 +1928,13 @@ def test_cooking_ranges
hpxml.cooking_ranges[0].monthly_multipliers = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_cooking_range_values(hpxml_default, HPXML::LocationLivingSpace, false, 1.0, '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097')
+ _test_default_cooking_range_values(hpxml_default.cooking_ranges[0], HPXML::LocationLivingSpace, false, 1.0, '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097')
# Test defaults before 301-2019 Addendum A
hpxml.header.eri_calculation_version = '2019'
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_cooking_range_values(hpxml_default, HPXML::LocationLivingSpace, false, 1.0, '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097')
+ _test_default_cooking_range_values(hpxml_default.cooking_ranges[0], HPXML::LocationLivingSpace, false, 1.0, '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011', '1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097')
end
def test_ovens
@@ -1562,19 +1943,19 @@ def test_ovens
hpxml.ovens[0].is_convection = true
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_oven_values(hpxml_default, true)
+ _test_default_oven_values(hpxml_default.ovens[0], true)
# Test defaults
hpxml.ovens[0].is_convection = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_oven_values(hpxml_default, false)
+ _test_default_oven_values(hpxml_default.ovens[0], false)
# Test defaults before 301-2019 Addendum A
hpxml.header.eri_calculation_version = '2019'
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_oven_values(hpxml_default, false)
+ _test_default_oven_values(hpxml_default.ovens[0], false)
end
def test_lighting
@@ -1664,7 +2045,7 @@ def test_ceiling_fans
hpxml.ceiling_fans[0].efficiency = 100
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_ceiling_fan_values(hpxml_default, 2, 100)
+ _test_default_ceiling_fan_values(hpxml_default.ceiling_fans[0], 2, 100)
# Test defaults
hpxml.ceiling_fans.each do |ceiling_fan|
@@ -1673,7 +2054,7 @@ def test_ceiling_fans
end
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_ceiling_fan_values(hpxml_default, 4, 70.4)
+ _test_default_ceiling_fan_values(hpxml_default.ceiling_fans[0], 4, 70.4)
end
def test_pools
@@ -1693,8 +2074,8 @@ def test_pools
pool.pump_monthly_multipliers = ConstantMonthSchedule
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pool_heater_values(hpxml_default, HPXML::UnitsKwhPerYear, 1000, 1.4, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
- _test_default_pool_pump_values(hpxml_default, 3000, 1.3, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
+ _test_default_pool_heater_values(hpxml_default.pools[0], HPXML::UnitsKwhPerYear, 1000, 1.4, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
+ _test_default_pool_pump_values(hpxml_default.pools[0], 3000, 1.3, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
# Test defaults
pool = hpxml.pools[0]
@@ -1711,8 +2092,8 @@ def test_pools
pool.pump_monthly_multipliers = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pool_heater_values(hpxml_default, HPXML::UnitsThermPerYear, 236, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
- _test_default_pool_pump_values(hpxml_default, 2496, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
+ _test_default_pool_heater_values(hpxml_default.pools[0], HPXML::UnitsThermPerYear, 236, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
+ _test_default_pool_pump_values(hpxml_default.pools[0], 2496, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
# Test defaults 2
hpxml = _create_hpxml('base-misc-loads-large-uncommon2.xml')
@@ -1730,8 +2111,8 @@ def test_pools
pool.pump_monthly_multipliers = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_pool_heater_values(hpxml_default, nil, nil, nil, nil, nil, nil)
- _test_default_pool_pump_values(hpxml_default, 2496, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
+ _test_default_pool_heater_values(hpxml_default.pools[0], nil, nil, nil, nil, nil, nil)
+ _test_default_pool_pump_values(hpxml_default.pools[0], 2496, 1.0, '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '0.003, 0.003, 0.003, 0.004, 0.008, 0.015, 0.026, 0.044, 0.084, 0.121, 0.127, 0.121, 0.120, 0.090, 0.075, 0.061, 0.037, 0.023, 0.013, 0.008, 0.004, 0.003, 0.003, 0.003', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
end
def test_hot_tubs
@@ -1751,8 +2132,8 @@ def test_hot_tubs
hot_tub.pump_monthly_multipliers = ConstantMonthSchedule
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_hot_tub_heater_values(hpxml_default, HPXML::UnitsThermPerYear, 1000, 0.8, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
- _test_default_hot_tub_pump_values(hpxml_default, 3000, 0.7, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
+ _test_default_hot_tub_heater_values(hpxml_default.hot_tubs[0], HPXML::UnitsThermPerYear, 1000, 0.8, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
+ _test_default_hot_tub_pump_values(hpxml_default.hot_tubs[0], 3000, 0.7, ConstantDaySchedule, ConstantDaySchedule, ConstantMonthSchedule)
# Test defaults
hot_tub = hpxml.hot_tubs[0]
@@ -1769,8 +2150,8 @@ def test_hot_tubs
hot_tub.pump_monthly_multipliers = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_hot_tub_heater_values(hpxml_default, HPXML::UnitsKwhPerYear, 1125, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.837, 0.835, 1.084, 1.084, 1.084, 1.096, 1.096, 1.096, 1.096, 0.931, 0.925, 0.837')
- _test_default_hot_tub_pump_values(hpxml_default, 1111, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.921, 0.928, 0.921, 0.915, 0.921, 1.160, 1.158, 1.158, 1.160, 0.921, 0.915, 0.921')
+ _test_default_hot_tub_heater_values(hpxml_default.hot_tubs[0], HPXML::UnitsKwhPerYear, 1125, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.837, 0.835, 1.084, 1.084, 1.084, 1.096, 1.096, 1.096, 1.096, 0.931, 0.925, 0.837')
+ _test_default_hot_tub_pump_values(hpxml_default.hot_tubs[0], 1111, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.921, 0.928, 0.921, 0.915, 0.921, 1.160, 1.158, 1.158, 1.160, 0.921, 0.915, 0.921')
# Test defaults 2
hpxml = _create_hpxml('base-misc-loads-large-uncommon2.xml')
@@ -1788,8 +2169,8 @@ def test_hot_tubs
hot_tub.pump_monthly_multipliers = nil
XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
hpxml_default = _test_measure()
- _test_default_hot_tub_heater_values(hpxml_default, HPXML::UnitsKwhPerYear, 225, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.837, 0.835, 1.084, 1.084, 1.084, 1.096, 1.096, 1.096, 1.096, 0.931, 0.925, 0.837')
- _test_default_hot_tub_pump_values(hpxml_default, 1111, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.921, 0.928, 0.921, 0.915, 0.921, 1.160, 1.158, 1.158, 1.160, 0.921, 0.915, 0.921')
+ _test_default_hot_tub_heater_values(hpxml_default.hot_tubs[0], HPXML::UnitsKwhPerYear, 225, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.837, 0.835, 1.084, 1.084, 1.084, 1.096, 1.096, 1.096, 1.096, 0.931, 0.925, 0.837')
+ _test_default_hot_tub_pump_values(hpxml_default.hot_tubs[0], 1111, 1.0, '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.024, 0.029, 0.024, 0.029, 0.047, 0.067, 0.057, 0.024, 0.024, 0.019, 0.015, 0.014, 0.014, 0.014, 0.024, 0.058, 0.126, 0.122, 0.068, 0.061, 0.051, 0.043, 0.024, 0.024', '0.921, 0.928, 0.921, 0.915, 0.921, 1.160, 1.158, 1.158, 1.160, 0.921, 0.915, 0.921')
end
def test_plug_loads
@@ -1902,6 +2283,94 @@ def test_fuel_loads
_test_default_fuel_load_values(hpxml_default, HPXML::FuelLoadTypeFireplace, 67, 0.5, 0.1, 1.0, '0.044, 0.023, 0.019, 0.015, 0.016, 0.018, 0.026, 0.033, 0.033, 0.032, 0.033, 0.033, 0.032, 0.032, 0.032, 0.033, 0.045, 0.057, 0.066, 0.076, 0.081, 0.086, 0.075, 0.065', '0.044, 0.023, 0.019, 0.015, 0.016, 0.018, 0.026, 0.033, 0.033, 0.032, 0.033, 0.033, 0.032, 0.032, 0.032, 0.033, 0.045, 0.057, 0.066, 0.076, 0.081, 0.086, 0.075, 0.065', '1.154, 1.161, 1.013, 1.010, 1.013, 0.888, 0.883, 0.883, 0.888, 0.978, 0.974, 1.154')
end
+ def test_hvac_lookup
+ central_air_conditioner_seer = HVAC.get_default_hvac_efficiency_by_year_installed(1970, 'central air conditioner', 'electricity', 'SEER')
+ assert_equal(central_air_conditioner_seer, 8.0)
+
+ room_air_conditioner_eer = HVAC.get_default_hvac_efficiency_by_year_installed(1993, 'room air conditioner', 'electricity', 'EER')
+ assert_equal(room_air_conditioner_eer, 9.05)
+
+ furnace_afue = HVAC.get_default_hvac_efficiency_by_year_installed(1997, 'Furnace', 'natural gas', 'AFUE')
+ assert_equal(furnace_afue, 0.829)
+
+ furnace_afue = HVAC.get_default_hvac_efficiency_by_year_installed(1981, 'Furnace', 'diesel', 'AFUE')
+ assert_equal(furnace_afue, 0.768)
+
+ wall_furnace_afue = HVAC.get_default_hvac_efficiency_by_year_installed(1997, 'WallFurnace', 'natural gas', 'AFUE')
+ assert_equal(wall_furnace_afue, 0.656)
+
+ wall_furnace_afue = HVAC.get_default_hvac_efficiency_by_year_installed(1971, 'WallFurnace', 'propane', 'AFUE')
+ assert_equal(wall_furnace_afue, 0.548)
+
+ wall_furnace_afue = HVAC.get_default_hvac_efficiency_by_year_installed(1970, 'FloorFurnace', 'natural gas', 'AFUE')
+ assert_equal(wall_furnace_afue, 0.5)
+
+ boiler_afue = HVAC.get_default_hvac_efficiency_by_year_installed(2004, 'Boiler', 'propane', 'AFUE')
+ assert_equal(boiler_afue, 0.831)
+
+ heatpump_seer = HVAC.get_default_hvac_efficiency_by_year_installed(1991, 'air-to-air', 'electricity', 'SEER')
+ assert_equal(heatpump_seer, 9.77)
+
+ heatpump_hspf = HVAC.get_default_hvac_efficiency_by_year_installed(1988, 'air-to-air', 'electricity', 'HSPF')
+ assert_equal(heatpump_hspf, 6.88)
+
+ assert_equal(
+ HVAC.get_default_hvac_efficiency_by_year_installed(2010, 'air-to-air', 'electricity', 'SEER'),
+ HVAC.get_default_hvac_efficiency_by_year_installed(2011, 'air-to-air', 'electricity', 'SEER')
+ )
+
+ assert_equal(
+ HVAC.get_default_hvac_efficiency_by_year_installed(2010, 'Furnace', 'natural gas', 'AFUE'),
+ HVAC.get_default_hvac_efficiency_by_year_installed(2020, 'Furnace', 'natural gas', 'AFUE')
+ )
+
+ assert_equal(
+ HVAC.get_default_hvac_efficiency_by_year_installed(1969, 'Boiler', 'fuel oil', 'AFUE'),
+ HVAC.get_default_hvac_efficiency_by_year_installed(1970, 'Boiler', 'fuel oil', 'AFUE')
+ )
+
+ assert_equal(
+ HVAC.get_default_hvac_efficiency_by_year_installed(1955, 'central air conditioner', 'electricity', 'SEER'),
+ HVAC.get_default_hvac_efficiency_by_year_installed(1970, 'central air conditioner', 'electricity', 'SEER')
+ )
+ end
+
+ def test_dhw_lookup
+ waterheater_elec_ef = Waterheater.get_default_water_heater_efficiency_by_year_installed(2006, 'electricity')
+ assert_equal(waterheater_elec_ef, 0.9)
+
+ waterheater_natural_gas_ef = Waterheater.get_default_water_heater_efficiency_by_year_installed(1998, 'natural gas')
+ assert_equal(waterheater_natural_gas_ef, 0.501)
+
+ waterheater_propane_ef = Waterheater.get_default_water_heater_efficiency_by_year_installed(2007, 'propane')
+ assert_equal(waterheater_propane_ef, 0.55)
+
+ waterheater_fuel_oil_ef = Waterheater.get_default_water_heater_efficiency_by_year_installed(1989, 'fuel oil')
+ assert_equal(waterheater_fuel_oil_ef, 0.54)
+
+ waterheater_fuel_oil_ef = Waterheater.get_default_water_heater_efficiency_by_year_installed(1989, 'wood')
+ assert_equal(waterheater_fuel_oil_ef, 0.54)
+
+ ['natural gas', 'electricity', 'propane', 'fuel oil'].each do |fuel_type|
+ assert_equal(
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(2010, fuel_type),
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(2011, fuel_type)
+ )
+ assert_equal(
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(2010, fuel_type),
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(2020, fuel_type)
+ )
+ assert_equal(
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(1971, fuel_type),
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(1972, fuel_type)
+ )
+ assert_equal(
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(1955, fuel_type),
+ Waterheater.get_default_water_heater_efficiency_by_year_installed(1972, fuel_type)
+ )
+ end
+ end
+
def _test_measure()
# create an instance of the measure
measure = HPXMLtoOpenStudio.new
@@ -1960,6 +2429,13 @@ def _test_default_site_values(hpxml, site_type, shielding_of_home)
assert_equal(shielding_of_home, hpxml.site.shielding_of_home)
end
+ def _test_default_neighbor_building_values(hpxml, azimuths)
+ assert_equal(azimuths.size, hpxml.neighbor_buildings.size)
+ hpxml.neighbor_buildings.each_with_index do |neighbor_building, idx|
+ assert_equal(azimuths[idx], neighbor_building.azimuth)
+ end
+ end
+
def _test_default_occupancy_values(hpxml, num_occupants)
assert_equal(num_occupants, hpxml.building_occupancy.number_of_residents)
end
@@ -1971,67 +2447,93 @@ def _test_default_building_construction_values(hpxml, building_volume, average_c
assert_equal(n_bathrooms, hpxml.building_construction.number_of_bathrooms)
end
- def _test_default_infiltration_values(hpxml, volume)
- air_infiltration_measurement = hpxml.air_infiltration_measurements[0]
-
+ def _test_default_infiltration_values(air_infiltration_measurement, volume)
assert_equal(volume, air_infiltration_measurement.infiltration_volume)
end
- def _test_default_attic_values(hpxml, sla)
- attic = hpxml.attics[0]
-
+ def _test_default_attic_values(attic, sla)
assert_in_epsilon(sla, attic.vented_attic_sla, 0.001)
end
- def _test_default_foundation_values(hpxml, sla)
- foundation = hpxml.foundations[0]
-
+ def _test_default_foundation_values(foundation, sla)
assert_in_epsilon(sla, foundation.vented_crawlspace_sla, 0.001)
end
- def _test_default_roof_values(hpxml, roof_type, solar_absorptance, roof_color, emittance, radiant_barrier)
- roof = hpxml.roofs[0]
-
+ def _test_default_roof_values(roof, roof_type, solar_absorptance, roof_color, emittance, radiant_barrier,
+ radiant_barrier_grade, int_finish_type, int_finish_thickness, azimuth)
assert_equal(roof_type, roof.roof_type)
assert_equal(solar_absorptance, roof.solar_absorptance)
assert_equal(roof_color, roof.roof_color)
assert_equal(emittance, roof.emittance)
assert_equal(radiant_barrier, roof.radiant_barrier)
+ if not radiant_barrier_grade.nil?
+ assert_equal(radiant_barrier_grade, roof.radiant_barrier_grade)
+ else
+ assert_nil(roof.radiant_barrier_grade)
+ end
+ assert_equal(int_finish_type, roof.interior_finish_type)
+ if not int_finish_thickness.nil?
+ assert_equal(int_finish_thickness, roof.interior_finish_thickness)
+ else
+ assert_nil(roof.interior_finish_thickness)
+ end
+ assert_equal(azimuth, roof.azimuth)
end
- def _test_default_rim_joist_values(hpxml, siding, solar_absorptance, color, emittance)
- rim_joist = hpxml.rim_joists[0]
-
+ def _test_default_rim_joist_values(rim_joist, siding, solar_absorptance, color, emittance, azimuth)
assert_equal(siding, rim_joist.siding)
assert_equal(solar_absorptance, rim_joist.solar_absorptance)
assert_equal(color, rim_joist.color)
assert_equal(emittance, rim_joist.emittance)
+ assert_equal(azimuth, rim_joist.azimuth)
end
- def _test_default_wall_values(hpxml, siding, solar_absorptance, color, emittance)
- wall = hpxml.walls[0]
-
+ def _test_default_wall_values(wall, siding, solar_absorptance, color, emittance, int_finish_type, int_finish_thickness, azimuth)
assert_equal(siding, wall.siding)
assert_equal(solar_absorptance, wall.solar_absorptance)
assert_equal(color, wall.color)
assert_equal(emittance, wall.emittance)
+ assert_equal(int_finish_type, wall.interior_finish_type)
+ if not int_finish_thickness.nil?
+ assert_equal(int_finish_thickness, wall.interior_finish_thickness)
+ else
+ assert_nil(wall.interior_finish_thickness)
+ end
end
- def _test_default_foundation_wall_values(hpxml, thickness)
- foundation_wall = hpxml.foundation_walls[0]
-
+ def _test_default_foundation_wall_values(foundation_wall, thickness, int_finish_type, int_finish_thickness, azimuth, area,
+ ins_int_top, ins_int_bottom, ins_ext_top, ins_ext_bottom)
assert_equal(thickness, foundation_wall.thickness)
+ assert_equal(int_finish_type, foundation_wall.interior_finish_type)
+ if not int_finish_thickness.nil?
+ assert_equal(int_finish_thickness, foundation_wall.interior_finish_thickness)
+ else
+ assert_nil(foundation_wall.interior_finish_thickness)
+ end
+ assert_equal(azimuth, foundation_wall.azimuth)
+ assert_equal(area, foundation_wall.area)
+ assert_equal(ins_int_top, foundation_wall.insulation_interior_distance_to_top)
+ assert_equal(ins_int_bottom, foundation_wall.insulation_interior_distance_to_bottom)
+ assert_equal(ins_ext_top, foundation_wall.insulation_exterior_distance_to_top)
+ assert_equal(ins_ext_bottom, foundation_wall.insulation_exterior_distance_to_bottom)
end
- def _test_default_slab_values(hpxml, thickness, carpet_r_value, carpet_fraction)
- slab = hpxml.slabs[0]
+ def _test_default_frame_floor_values(frame_floor, int_finish_type, int_finish_thickness)
+ assert_equal(int_finish_type, frame_floor.interior_finish_type)
+ if not int_finish_thickness.nil?
+ assert_equal(int_finish_thickness, frame_floor.interior_finish_thickness)
+ else
+ assert_nil(frame_floor.interior_finish_thickness)
+ end
+ end
+ def _test_default_slab_values(slab, thickness, carpet_r_value, carpet_fraction)
assert_equal(thickness, slab.thickness)
assert_equal(carpet_r_value, slab.carpet_r_value)
assert_equal(carpet_fraction, slab.carpet_fraction)
end
- def _test_default_window_values(hpxml, ext_summer_sfs, ext_winter_sfs, int_summer_sfs, int_winter_sfs, fraction_operable)
+ def _test_default_window_values(hpxml, ext_summer_sfs, ext_winter_sfs, int_summer_sfs, int_winter_sfs, fraction_operable, azimuths)
assert_equal(ext_summer_sfs.size, hpxml.windows.size)
hpxml.windows.each_with_index do |window, idx|
assert_equal(ext_summer_sfs[idx], window.exterior_shading_factor_summer)
@@ -2039,23 +2541,29 @@ def _test_default_window_values(hpxml, ext_summer_sfs, ext_winter_sfs, int_summe
assert_equal(int_summer_sfs[idx], window.interior_shading_factor_summer)
assert_equal(int_winter_sfs[idx], window.interior_shading_factor_winter)
assert_equal(fraction_operable[idx], window.fraction_operable)
+ assert_equal(azimuths[idx], window.azimuth)
end
end
- def _test_default_skylight_values(hpxml, ext_summer_sfs, ext_winter_sfs, int_summer_sfs, int_winter_sfs)
+ def _test_default_skylight_values(hpxml, ext_summer_sfs, ext_winter_sfs, int_summer_sfs, int_winter_sfs, azimuths)
assert_equal(ext_summer_sfs.size, hpxml.skylights.size)
hpxml.skylights.each_with_index do |skylight, idx|
assert_equal(ext_summer_sfs[idx], skylight.exterior_shading_factor_summer)
assert_equal(ext_winter_sfs[idx], skylight.exterior_shading_factor_winter)
assert_equal(int_summer_sfs[idx], skylight.interior_shading_factor_summer)
assert_equal(int_winter_sfs[idx], skylight.interior_shading_factor_winter)
+ assert_equal(azimuths[idx], skylight.azimuth)
end
end
- def _test_default_central_air_conditioner_values(hpxml, shr, compressor_type, fan_watts_per_cfm, charge_defect_ratio,
- airflow_defect_ratio, cooling_capacity)
- cooling_system = hpxml.cooling_systems[0]
+ def _test_default_door_values(hpxml, azimuths)
+ hpxml.doors.each_with_index do |door, idx|
+ assert_equal(azimuths[idx], door.azimuth)
+ end
+ end
+ def _test_default_central_air_conditioner_values(cooling_system, shr, compressor_type, fan_watts_per_cfm, charge_defect_ratio,
+ airflow_defect_ratio, cooling_capacity, cooling_efficiency_seer)
assert_equal(shr, cooling_system.cooling_shr)
assert_equal(compressor_type, cooling_system.compressor_type)
assert_equal(fan_watts_per_cfm, cooling_system.fan_watts_per_cfm)
@@ -2066,22 +2574,28 @@ def _test_default_central_air_conditioner_values(hpxml, shr, compressor_type, fa
else
assert_equal(cooling_system.cooling_capacity, cooling_capacity)
end
+ if cooling_efficiency_seer.nil?
+ assert_nil(cooling_system.cooling_efficiency_seer)
+ else
+ assert_equal(cooling_system.cooling_efficiency_seer, cooling_efficiency_seer)
+ end
end
- def _test_default_room_air_conditioner_values(hpxml, shr, cooling_capacity)
- cooling_system = hpxml.cooling_systems[0]
-
+ def _test_default_room_air_conditioner_values(cooling_system, shr, cooling_capacity, cooling_efficiency_eer)
assert_equal(shr, cooling_system.cooling_shr)
if cooling_capacity.nil?
assert(cooling_system.cooling_capacity > 0)
else
assert_equal(cooling_system.cooling_capacity, cooling_capacity)
end
+ if cooling_efficiency_eer.nil?
+ assert_nil(cooling_system.cooling_efficiency_eer)
+ else
+ assert_equal(cooling_system.cooling_efficiency_eer, cooling_efficiency_eer)
+ end
end
- def _test_default_evap_cooler_values(hpxml, cooling_capacity)
- cooling_system = hpxml.cooling_systems[0]
-
+ def _test_default_evap_cooler_values(cooling_system, cooling_capacity)
if cooling_capacity.nil?
assert(cooling_system.cooling_capacity > 0)
else
@@ -2089,10 +2603,8 @@ def _test_default_evap_cooler_values(hpxml, cooling_capacity)
end
end
- def _test_default_mini_split_air_conditioner_values(hpxml, shr, fan_watts_per_cfm, charge_defect_ratio,
+ def _test_default_mini_split_air_conditioner_values(cooling_system, shr, fan_watts_per_cfm, charge_defect_ratio,
airflow_defect_ratio, cooling_capacity)
- cooling_system = hpxml.cooling_systems[0]
-
assert_equal(shr, cooling_system.cooling_shr)
assert_equal(fan_watts_per_cfm, cooling_system.fan_watts_per_cfm)
assert_equal(charge_defect_ratio, cooling_system.charge_defect_ratio)
@@ -2104,10 +2616,16 @@ def _test_default_mini_split_air_conditioner_values(hpxml, shr, fan_watts_per_cf
end
end
- def _test_default_furnace_values(hpxml, fan_watts_per_cfm, airflow_defect_ratio,
- heating_capacity)
- heating_system = hpxml.heating_systems[0]
+ def _test_default_elec_resistance(heating_system, heating_efficiency_percent)
+ if heating_efficiency_percent.nil?
+ assert_nil(heating_system.heating_efficiency_percent)
+ else
+ assert_equal(heating_system.heating_efficiency_percent, heating_efficiency_percent)
+ end
+ end
+ def _test_default_furnace_values(heating_system, fan_watts_per_cfm, airflow_defect_ratio,
+ heating_capacity, heating_efficiency_afue)
assert_equal(fan_watts_per_cfm, heating_system.fan_watts_per_cfm)
assert_equal(airflow_defect_ratio, heating_system.airflow_defect_ratio)
if heating_capacity.nil?
@@ -2115,90 +2633,115 @@ def _test_default_furnace_values(hpxml, fan_watts_per_cfm, airflow_defect_ratio,
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_afue.nil?
+ assert_nil(heating_system.heating_efficiency_afue)
+ else
+ assert_equal(heating_system.heating_efficiency_afue, heating_efficiency_afue)
+ end
end
- def _test_default_wall_furnace_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_wall_furnace_values(heating_system, fan_watts, heating_capacity, heating_efficiency_afue)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_afue.nil?
+ assert_nil(heating_system.heating_efficiency_afue)
+ else
+ assert_equal(heating_system.heating_efficiency_afue, heating_efficiency_afue)
+ end
end
- def _test_default_floor_furnace_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_floor_furnace_values(heating_system, fan_watts, heating_capacity, heating_efficiency_afue)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_afue.nil?
+ assert_nil(heating_system.heating_efficiency_afue)
+ else
+ assert_equal(heating_system.heating_efficiency_afue, heating_efficiency_afue)
+ end
end
- def _test_default_boiler_values(hpxml, eae, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_boiler_values(heating_system, eae, heating_capacity, heating_efficiency_afue)
assert_equal(eae, heating_system.electric_auxiliary_energy)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_afue.nil?
+ assert_nil(heating_system.heating_efficiency_afue)
+ else
+ assert_equal(heating_system.heating_efficiency_afue, heating_efficiency_afue)
+ end
end
- def _test_default_stove_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_stove_values(heating_system, fan_watts, heating_capacity, heating_efficiency_percent)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_percent.nil?
+ assert_nil(heating_system.heating_efficiency_percent)
+ else
+ assert_equal(heating_system.heating_efficiency_percent, heating_efficiency_percent)
+ end
end
- def _test_default_portable_heater_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_portable_heater_values(heating_system, fan_watts, heating_capacity, heating_efficiency_percent)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_percent.nil?
+ assert_nil(heating_system.heating_efficiency_percent)
+ else
+ assert_equal(heating_system.heating_efficiency_percent, heating_efficiency_percent)
+ end
end
- def _test_default_fixed_heater_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_fixed_heater_values(heating_system, fan_watts, heating_capacity, heating_efficiency_percent)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_percent.nil?
+ assert_nil(heating_system.heating_efficiency_percent)
+ else
+ assert_equal(heating_system.heating_efficiency_percent, heating_efficiency_percent)
+ end
end
- def _test_default_fireplace_values(hpxml, fan_watts, heating_capacity)
- heating_system = hpxml.heating_systems[0]
-
+ def _test_default_fireplace_values(heating_system, fan_watts, heating_capacity, heating_efficiency_percent)
assert_equal(fan_watts, heating_system.fan_watts)
if heating_capacity.nil?
assert(heating_system.heating_capacity > 0)
else
assert_equal(heating_system.heating_capacity, heating_capacity)
end
+ if heating_efficiency_percent.nil?
+ assert_nil(heating_system.heating_efficiency_percent)
+ else
+ assert_equal(heating_system.heating_efficiency_percent, heating_efficiency_percent)
+ end
end
- def _test_default_air_to_air_heat_pump_values(hpxml, shr, compressor_type, fan_watts_per_cfm, charge_defect_ratio,
+ def _test_default_air_to_air_heat_pump_values(heat_pump, shr, compressor_type, fan_watts_per_cfm, charge_defect_ratio,
airflow_defect_ratio, cooling_capacity, heating_capacity,
- heating_capacity_17F, backup_heating_capacity)
- heat_pump = hpxml.heat_pumps[0]
-
+ heating_capacity_17F, backup_heating_capacity,
+ cooling_efficiency_seer, heating_efficiency_hspf)
assert_equal(shr, heat_pump.cooling_shr)
assert_equal(compressor_type, heat_pump.compressor_type)
assert_equal(fan_watts_per_cfm, heat_pump.fan_watts_per_cfm)
@@ -2224,13 +2767,21 @@ def _test_default_air_to_air_heat_pump_values(hpxml, shr, compressor_type, fan_w
else
assert_equal(heat_pump.backup_heating_capacity, backup_heating_capacity)
end
+ if cooling_efficiency_seer.nil?
+ assert_nil(heat_pump.cooling_efficiency_seer)
+ else
+ assert_equal(heat_pump.cooling_efficiency_seer, cooling_efficiency_seer)
+ end
+ if heating_efficiency_hspf.nil?
+ assert_nil(heat_pump.heating_efficiency_hspf)
+ else
+ assert_equal(heat_pump.heating_efficiency_hspf, heating_efficiency_hspf)
+ end
end
- def _test_default_mini_split_heat_pump_values(hpxml, shr, fan_watts_per_cfm, charge_defect_ratio,
+ def _test_default_mini_split_heat_pump_values(heat_pump, shr, fan_watts_per_cfm, charge_defect_ratio,
airflow_defect_ratio, cooling_capacity, heating_capacity,
heating_capacity_17F, backup_heating_capacity)
- heat_pump = hpxml.heat_pumps[0]
-
assert_equal(shr, heat_pump.cooling_shr)
assert_equal(fan_watts_per_cfm, heat_pump.fan_watts_per_cfm)
assert_equal(charge_defect_ratio, heat_pump.charge_defect_ratio)
@@ -2257,12 +2808,9 @@ def _test_default_mini_split_heat_pump_values(hpxml, shr, fan_watts_per_cfm, cha
end
end
- def _test_default_ground_to_air_heat_pump_values(hpxml, pump_watts_per_ton, fan_watts_per_cfm,
+ def _test_default_ground_to_air_heat_pump_values(heat_pump, pump_watts_per_ton, fan_watts_per_cfm,
airflow_defect_ratio, cooling_capacity, heating_capacity,
backup_heating_capacity)
-
- heat_pump = hpxml.heat_pumps[0]
-
assert_equal(pump_watts_per_ton, heat_pump.pump_watts_per_ton)
assert_equal(fan_watts_per_cfm, heat_pump.fan_watts_per_cfm)
assert_equal(airflow_defect_ratio, heat_pump.airflow_defect_ratio)
@@ -2283,9 +2831,7 @@ def _test_default_ground_to_air_heat_pump_values(hpxml, pump_watts_per_ton, fan_
end
end
- def _test_default_hvac_control_values(hpxml, htg_setback_start_hr, clg_setup_start_hr, htg_season_begin_month, htg_season_begin_day, htg_season_end_month, htg_season_end_day, clg_season_begin_month, clg_season_begin_day, clg_season_end_month, clg_season_end_day)
- hvac_control = hpxml.hvac_controls[0]
-
+ def _test_default_hvac_control_values(hvac_control, htg_setback_start_hr, clg_setup_start_hr, htg_season_begin_month, htg_season_begin_day, htg_season_end_month, htg_season_end_day, clg_season_begin_month, clg_season_begin_day, clg_season_end_month, clg_season_end_day)
assert_equal(htg_setback_start_hr, hvac_control.heating_setback_start_hour)
assert_equal(clg_setup_start_hr, hvac_control.cooling_setup_start_hour)
assert_equal(htg_season_begin_month, hvac_control.seasons_heating_begin_month)
@@ -2299,7 +2845,7 @@ def _test_default_hvac_control_values(hpxml, htg_setback_start_hr, clg_setup_sta
end
def _test_default_duct_values(hpxml, supply_locations, return_locations, supply_areas, return_areas,
- area_fracs, n_return_registers)
+ supply_fracs, return_fracs, n_return_registers)
supply_duct_idx = 0
return_duct_idx = 0
hpxml.hvac_distributions.each do |hvac_distribution|
@@ -2310,23 +2856,24 @@ def _test_default_duct_values(hpxml, supply_locations, return_locations, supply_
if duct.duct_type == HPXML::DuctTypeSupply
assert_equal(supply_locations[supply_duct_idx], duct.duct_location)
assert_in_epsilon(supply_areas[supply_duct_idx], duct.duct_surface_area, 0.01)
- assert_in_epsilon(area_fracs[supply_duct_idx], duct.duct_fraction_area, 0.01)
+ assert_in_epsilon(supply_fracs[supply_duct_idx], duct.duct_fraction_area, 0.01)
supply_duct_idx += 1
elsif duct.duct_type == HPXML::DuctTypeReturn
assert_equal(return_locations[return_duct_idx], duct.duct_location)
assert_in_epsilon(return_areas[return_duct_idx], duct.duct_surface_area, 0.01)
- assert_in_epsilon(area_fracs[return_duct_idx], duct.duct_fraction_area, 0.01)
+ assert_in_epsilon(return_fracs[return_duct_idx], duct.duct_fraction_area, 0.01)
return_duct_idx += 1
end
end
end
end
- def _test_default_mech_vent_values(hpxml, is_shared_system, hours_in_operation)
+ def _test_default_mech_vent_values(hpxml, is_shared_system, hours_in_operation, fan_power)
vent_fan = hpxml.ventilation_fans.select { |f| f.used_for_whole_building_ventilation }[0]
assert_equal(is_shared_system, vent_fan.is_shared_system)
assert_equal(hours_in_operation, vent_fan.hours_in_operation)
+ assert_equal(fan_power, vent_fan.fan_power)
end
def _test_default_kitchen_fan_values(hpxml, quantity, rated_flow_rate, hours_in_operation, fan_power, start_hour)
@@ -2353,13 +2900,19 @@ def _test_default_storage_water_heater_values(hpxml, *expected_wh_values)
storage_water_heaters = hpxml.water_heating_systems.select { |w| w.water_heater_type == HPXML::WaterHeaterTypeStorage }
assert_equal(expected_wh_values.size, storage_water_heaters.size)
storage_water_heaters.each_with_index do |wh_system, idx|
- is_shared, heating_capacity, tank_volume, recovery_efficiency, location = expected_wh_values[idx]
+ is_shared, heating_capacity, tank_volume, recovery_efficiency, location, temperature, energy_factor = expected_wh_values[idx]
assert_equal(is_shared, wh_system.is_shared_system)
assert_in_epsilon(heating_capacity, wh_system.heating_capacity, 0.01)
assert_equal(tank_volume, wh_system.tank_volume)
assert_in_epsilon(recovery_efficiency, wh_system.recovery_efficiency, 0.01)
assert_equal(location, wh_system.location)
+ assert_equal(temperature, wh_system.temperature)
+ if energy_factor.nil?
+ assert_nil(wh_system.energy_factor)
+ else
+ assert_equal(energy_factor, wh_system.energy_factor)
+ end
end
end
@@ -2373,25 +2926,19 @@ def _test_default_tankless_water_heater_values(hpxml, *expected_wh_values)
end
end
- def _test_default_standard_distribution_values(hpxml, piping_length, pipe_r_value)
- hot_water_distribution = hpxml.hot_water_distributions[0]
-
+ def _test_default_standard_distribution_values(hot_water_distribution, piping_length, pipe_r_value)
assert_in_epsilon(piping_length, hot_water_distribution.standard_piping_length, 0.01)
assert_equal(pipe_r_value, hot_water_distribution.pipe_r_value)
end
- def _test_default_recirc_distribution_values(hpxml, piping_length, branch_piping_length, pump_power, pipe_r_value)
- hot_water_distribution = hpxml.hot_water_distributions[0]
-
+ def _test_default_recirc_distribution_values(hot_water_distribution, piping_length, branch_piping_length, pump_power, pipe_r_value)
assert_in_epsilon(piping_length, hot_water_distribution.recirculation_piping_length, 0.01)
assert_in_epsilon(branch_piping_length, hot_water_distribution.recirculation_branch_piping_length, 0.01)
assert_in_epsilon(pump_power, hot_water_distribution.recirculation_pump_power, 0.01)
assert_equal(pipe_r_value, hot_water_distribution.pipe_r_value)
end
- def _test_default_shared_recirc_distribution_values(hpxml, pump_power)
- hot_water_distribution = hpxml.hot_water_distributions[0]
-
+ def _test_default_shared_recirc_distribution_values(hot_water_distribution, pump_power)
assert_in_epsilon(pump_power, hot_water_distribution.shared_recirculation_pump_power, 0.01)
end
@@ -2399,13 +2946,12 @@ def _test_default_water_fixture_values(hpxml, usage_multiplier)
assert_equal(usage_multiplier, hpxml.water_heating.water_fixtures_usage_multiplier)
end
- def _test_default_solar_thermal_values(hpxml, storage_volume)
- solar_thermal_system = hpxml.solar_thermal_systems[0]
-
+ def _test_default_solar_thermal_values(solar_thermal_system, storage_volume, azimuth)
assert_equal(storage_volume, solar_thermal_system.storage_volume)
+ assert_equal(azimuth, solar_thermal_system.collector_azimuth)
end
- def _test_default_pv_system_values(hpxml, interver_efficiency, system_loss_frac, is_shared_system, location, tracking, module_type)
+ def _test_default_pv_system_values(hpxml, interver_efficiency, system_loss_frac, is_shared_system, location, tracking, module_type, azimuth)
hpxml.pv_systems.each_with_index do |pv, idx|
assert_equal(is_shared_system, pv.is_shared_system)
assert_equal(interver_efficiency, pv.inverter_efficiency)
@@ -2413,6 +2959,7 @@ def _test_default_pv_system_values(hpxml, interver_efficiency, system_loss_frac,
assert_equal(location, pv.location)
assert_equal(tracking, pv.tracking)
assert_equal(module_type, pv.module_type)
+ assert_equal(azimuth, pv.array_azimuth)
end
end
@@ -2422,9 +2969,7 @@ def _test_default_generator_values(hpxml, is_shared_system)
end
end
- def _test_default_clothes_washer_values(hpxml, is_shared, location, imef, rated_annual_kwh, label_electric_rate, label_gas_rate, label_annual_gas_cost, capacity, label_usage, usage_multiplier)
- clothes_washer = hpxml.clothes_washers[0]
-
+ def _test_default_clothes_washer_values(clothes_washer, is_shared, location, imef, rated_annual_kwh, label_electric_rate, label_gas_rate, label_annual_gas_cost, capacity, label_usage, usage_multiplier)
assert_equal(is_shared, clothes_washer.is_shared_appliance)
assert_equal(location, clothes_washer.location)
assert_equal(imef, clothes_washer.integrated_modified_energy_factor)
@@ -2437,18 +2982,14 @@ def _test_default_clothes_washer_values(hpxml, is_shared, location, imef, rated_
assert_equal(usage_multiplier, clothes_washer.usage_multiplier)
end
- def _test_default_clothes_dryer_values(hpxml, is_shared, location, cef, usage_multiplier)
- clothes_dryer = hpxml.clothes_dryers[0]
-
+ def _test_default_clothes_dryer_values(clothes_dryer, is_shared, location, cef, usage_multiplier)
assert_equal(is_shared, clothes_dryer.is_shared_appliance)
assert_equal(location, clothes_dryer.location)
assert_equal(cef, clothes_dryer.combined_energy_factor)
assert_equal(usage_multiplier, clothes_dryer.usage_multiplier)
end
- def _test_default_clothes_dryer_exhaust_values(hpxml, is_vented, vented_flow_rate)
- clothes_dryer = hpxml.clothes_dryers[0]
-
+ def _test_default_clothes_dryer_exhaust_values(clothes_dryer, is_vented, vented_flow_rate)
assert_equal(is_vented, clothes_dryer.is_vented)
if vented_flow_rate.nil?
assert_nil(clothes_dryer.vented_flow_rate)
@@ -2457,9 +2998,7 @@ def _test_default_clothes_dryer_exhaust_values(hpxml, is_vented, vented_flow_rat
end
end
- def _test_default_dishwasher_values(hpxml, is_shared, location, rated_annual_kwh, label_electric_rate, label_gas_rate, label_annual_gas_cost, label_usage, place_setting_capacity, usage_multiplier)
- dishwasher = hpxml.dishwashers[0]
-
+ def _test_default_dishwasher_values(dishwasher, is_shared, location, rated_annual_kwh, label_electric_rate, label_gas_rate, label_annual_gas_cost, label_usage, place_setting_capacity, usage_multiplier)
assert_equal(is_shared, dishwasher.is_shared_appliance)
assert_equal(location, dishwasher.location)
assert_equal(rated_annual_kwh, dishwasher.rated_annual_kwh)
@@ -2544,9 +3083,7 @@ def _test_default_freezers_values(hpxml, location, rated_annual_kwh, usage_multi
end
end
- def _test_default_cooking_range_values(hpxml, location, is_induction, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
- cooking_range = hpxml.cooking_ranges[0]
-
+ def _test_default_cooking_range_values(cooking_range, location, is_induction, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
assert_equal(location, cooking_range.location)
assert_equal(is_induction, cooking_range.is_induction)
assert_equal(usage_multiplier, cooking_range.usage_multiplier)
@@ -2567,9 +3104,7 @@ def _test_default_cooking_range_values(hpxml, location, is_induction, usage_mult
end
end
- def _test_default_oven_values(hpxml, is_convection)
- oven = hpxml.ovens[0]
-
+ def _test_default_oven_values(oven, is_convection)
assert_equal(is_convection, oven.is_convection)
end
@@ -2644,16 +3179,12 @@ def _test_default_lighting_values(hpxml, interior_usage_multiplier, garage_usage
end
end
- def _test_default_ceiling_fan_values(hpxml, quantity, efficiency)
- ceiling_fan = hpxml.ceiling_fans[0]
-
+ def _test_default_ceiling_fan_values(ceiling_fan, quantity, efficiency)
assert_equal(quantity, ceiling_fan.quantity)
assert_in_epsilon(efficiency, ceiling_fan.efficiency, 0.01)
end
- def _test_default_pool_heater_values(hpxml, load_units, load_value, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
- pool = hpxml.pools[0]
-
+ def _test_default_pool_heater_values(pool, load_units, load_value, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
if load_units.nil?
assert_nil(pool.heater_load_units)
else
@@ -2686,9 +3217,7 @@ def _test_default_pool_heater_values(hpxml, load_units, load_value, usage_multip
end
end
- def _test_default_pool_pump_values(hpxml, kWh_per_year, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
- pool = hpxml.pools[0]
-
+ def _test_default_pool_pump_values(pool, kWh_per_year, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
assert_in_epsilon(kWh_per_year, pool.pump_kwh_per_year, 0.01)
assert_equal(usage_multiplier, pool.pump_usage_multiplier)
assert_equal(weekday_sch, pool.pump_weekday_fractions)
@@ -2696,9 +3225,7 @@ def _test_default_pool_pump_values(hpxml, kWh_per_year, usage_multiplier, weekda
assert_equal(monthly_mults, pool.pump_monthly_multipliers)
end
- def _test_default_hot_tub_heater_values(hpxml, load_units, load_value, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
- hot_tub = hpxml.hot_tubs[0]
-
+ def _test_default_hot_tub_heater_values(hot_tub, load_units, load_value, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
if load_units.nil?
assert_nil(hot_tub.heater_load_units)
else
@@ -2731,9 +3258,7 @@ def _test_default_hot_tub_heater_values(hpxml, load_units, load_value, usage_mul
end
end
- def _test_default_hot_tub_pump_values(hpxml, kWh_per_year, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
- hot_tub = hpxml.hot_tubs[0]
-
+ def _test_default_hot_tub_pump_values(hot_tub, kWh_per_year, usage_multiplier, weekday_sch, weekend_sch, monthly_mults)
assert_in_epsilon(kWh_per_year, hot_tub.pump_kwh_per_year, 0.01)
assert_equal(usage_multiplier, hot_tub.pump_usage_multiplier)
assert_equal(weekday_sch, hot_tub.pump_weekday_fractions)
diff --git a/HPXMLtoOpenStudio/tests/test_enclosure.rb b/HPXMLtoOpenStudio/tests/test_enclosure.rb
index c4d8b223f3..5cb77b8ff2 100644
--- a/HPXMLtoOpenStudio/tests/test_enclosure.rb
+++ b/HPXMLtoOpenStudio/tests/test_enclosure.rb
@@ -9,10 +9,373 @@
require_relative 'util.rb'
class HPXMLtoOpenStudioEnclosureTest < MiniTest::Test
+ def setup
+ @root_path = File.absolute_path(File.join(File.dirname(__FILE__), '..', '..'))
+ @sample_files_path = File.join(@root_path, 'workflow', 'sample_files')
+ @tmp_hpxml_path = File.join(@sample_files_path, 'tmp.xml')
+ @tmp_output_path = File.join(@sample_files_path, 'tmp_output')
+ FileUtils.mkdir_p(@tmp_output_path)
+ end
+
+ def teardown
+ File.delete(@tmp_hpxml_path) if File.exist? @tmp_hpxml_path
+ FileUtils.rm_rf(@tmp_output_path)
+ end
+
def sample_files_dir
return File.join(File.dirname(__FILE__), '..', '..', 'workflow', 'sample_files')
end
+ def test_roofs
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Open cavity, asphalt shingles roof
+ roofs_values = [{ assembly_r: 0.1, layer_names: ['asphalt or fiberglass shingles'] },
+ { assembly_r: 5.0, layer_names: ['asphalt or fiberglass shingles', 'roof rigid ins', 'osb sheathing'] },
+ { assembly_r: 20.0, layer_names: ['asphalt or fiberglass shingles', 'roof rigid ins', 'osb sheathing'] }]
+
+ hpxml = _create_hpxml('base.xml')
+ roofs_values.each do |roof_values|
+ hpxml.roofs[0].insulation_assembly_r_value = roof_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.roofs[0].id}:" }[0]
+ _check_surface(hpxml.roofs[0], os_surface, roof_values[:layer_names])
+ end
+
+ # Closed cavity, asphalt shingles roof
+ roofs_values = [{ assembly_r: 0.1, layer_names: ['asphalt or fiberglass shingles', 'roof stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['asphalt or fiberglass shingles', 'osb sheathing', 'roof stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['asphalt or fiberglass shingles', 'roof rigid ins', 'osb sheathing', 'roof stud and cavity', 'gypsum board'] }]
+
+ hpxml = _create_hpxml('base-atticroof-cathedral.xml')
+ roofs_values.each do |roof_values|
+ hpxml.roofs[0].insulation_assembly_r_value = roof_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.roofs[0].id}:" }[0]
+ _check_surface(hpxml.roofs[0], os_surface, roof_values[:layer_names])
+ end
+
+ # Closed cavity, Miscellaneous
+ roofs_values = [
+ # Slate or tile
+ [{ assembly_r: 0.1, layer_names: ['slate or tile shingles', 'roof stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['slate or tile shingles', 'osb sheathing', 'roof stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['slate or tile shingles', 'roof rigid ins', 'osb sheathing', 'roof stud and cavity', 'gypsum board'] }],
+ # Metal
+ [{ assembly_r: 0.1, layer_names: ['metal surfacing', 'roof stud and cavity', 'plaster'] },
+ { assembly_r: 5.0, layer_names: ['metal surfacing', 'osb sheathing', 'roof stud and cavity', 'plaster'] },
+ { assembly_r: 20.0, layer_names: ['metal surfacing', 'roof rigid ins', 'osb sheathing', 'roof stud and cavity', 'plaster'] }],
+ # Wood shingles
+ [{ assembly_r: 0.1, layer_names: ['wood shingles or shakes', 'roof stud and cavity', 'wood'] },
+ { assembly_r: 5.0, layer_names: ['wood shingles or shakes', 'osb sheathing', 'roof stud and cavity', 'wood'] },
+ { assembly_r: 20.0, layer_names: ['wood shingles or shakes', 'roof rigid ins', 'osb sheathing', 'roof stud and cavity', 'wood'] }],
+ ]
+
+ hpxml = _create_hpxml('base-enclosure-rooftypes.xml')
+ for i in 0..hpxml.roofs.size - 1
+ roofs_values[i].each do |roof_values|
+ hpxml.roofs[i].insulation_assembly_r_value = roof_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.roofs[i].id}:" }[0]
+ _check_surface(hpxml.roofs[i], os_surface, roof_values[:layer_names])
+ end
+ end
+
+ # Radiant Barrier
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Open cavity, asphalt shingles roof
+ roofs_values = [{ assembly_r: 0.1, layer_names: ['asphalt or fiberglass shingles', 'radiant barrier'] },
+ { assembly_r: 5.0, layer_names: ['asphalt or fiberglass shingles', 'roof rigid ins', 'osb sheathing', 'radiant barrier'] },
+ { assembly_r: 20.0, layer_names: ['asphalt or fiberglass shingles', 'roof rigid ins', 'osb sheathing', 'radiant barrier'] }]
+
+ hpxml = _create_hpxml('base-atticroof-radiant-barrier.xml')
+ roofs_values.each do |roof_values|
+ hpxml.roofs[0].insulation_assembly_r_value = roof_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.roofs[0].id}:" }[0]
+ _check_surface(hpxml.roofs[0], os_surface, roof_values[:layer_names])
+ end
+ end
+
+ def test_rim_joists
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Wood siding
+ rimjs_values = [{ assembly_r: 0.1, layer_names: ['wood siding', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['wood siding', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['wood siding', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }]
+
+ hpxml = _create_hpxml('base.xml')
+ rimjs_values.each do |rimj_values|
+ hpxml.rim_joists[0].insulation_assembly_r_value = rimj_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.rim_joists[0].id}:" }[0]
+ _check_surface(hpxml.rim_joists[0], os_surface, rimj_values[:layer_names])
+ end
+
+ # Miscellaneous
+ rimjs_values = [
+ # Aluminum siding
+ [{ assembly_r: 0.1, layer_names: ['aluminum siding', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['aluminum siding', 'osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['aluminum siding', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ # Brick veneer
+ [{ assembly_r: 0.1, layer_names: ['brick veneer', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['brick veneer', 'osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['brick veneer', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ # Fiber cement siding
+ [{ assembly_r: 0.1, layer_names: ['fiber cement siding', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['fiber cement siding', 'osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['fiber cement siding', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ # Stucco
+ [{ assembly_r: 0.1, layer_names: ['stucco', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['stucco', 'osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['stucco', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ # Vinyl siding
+ [{ assembly_r: 0.1, layer_names: ['vinyl siding', 'rim joist stud and cavity'] },
+ { assembly_r: 5.0, layer_names: ['vinyl siding', 'osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['vinyl siding', 'rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ # None
+ [{ assembly_r: 0.1, layer_names: ['rim joist stud and cavity', 'rim joist stud and cavity'] }, # Note: Below grade material doubled in update_solar_absorptances()
+ { assembly_r: 5.0, layer_names: ['osb sheathing', 'rim joist stud and cavity'] },
+ { assembly_r: 20.0, layer_names: ['rim joist rigid ins', 'osb sheathing', 'rim joist stud and cavity'] }],
+ ]
+
+ hpxml = _create_hpxml('base-enclosure-walltypes.xml')
+ for i in 0..hpxml.rim_joists.size - 1
+ rimjs_values[i].each do |rimj_values|
+ hpxml.rim_joists[i].insulation_assembly_r_value = rimj_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.rim_joists[i].id}:" }[0]
+ _check_surface(hpxml.rim_joists[i], os_surface, rimj_values[:layer_names])
+ end
+ end
+ end
+
+ def test_walls
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Wood Stud wall
+ walls_values = [{ assembly_r: 0.1, layer_names: ['wood siding', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['wood siding', 'osb sheathing', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['wood siding', 'wall rigid ins', 'osb sheathing', 'wall stud and cavity', 'gypsum board'] }]
+
+ hpxml = _create_hpxml('base.xml')
+ walls_values.each do |wall_values|
+ hpxml.walls[0].insulation_assembly_r_value = wall_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.walls[0].id}:" }[0]
+ _check_surface(hpxml.walls[0], os_surface, wall_values[:layer_names])
+ end
+
+ # Miscellaneous
+ walls_values = [
+ # CMU wall
+ [{ assembly_r: 0.1, layer_names: ['aluminum siding', 'concrete block', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['aluminum siding', 'wall rigid ins', 'concrete block', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['aluminum siding', 'wall rigid ins', 'osb sheathing', 'concrete block', 'gypsum board'] }],
+ # Double Stud wall
+ [{ assembly_r: 0.1, layer_names: ['brick veneer', 'wall stud and cavity', 'wall cavity', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['brick veneer', 'osb sheathing', 'wall stud and cavity', 'wall cavity', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['brick veneer', 'osb sheathing', 'wall stud and cavity', 'wall cavity', 'wall stud and cavity', 'gypsum board'] }],
+ # ICF wall
+ [{ assembly_r: 0.1, layer_names: ['fiber cement siding', 'wall ins form', 'wall concrete', 'wall ins form', 'gypsum composite board'] },
+ { assembly_r: 5.0, layer_names: ['fiber cement siding', 'osb sheathing', 'wall ins form', 'wall concrete', 'wall ins form', 'gypsum composite board'] },
+ { assembly_r: 20.0, layer_names: ['fiber cement siding', 'osb sheathing', 'wall ins form', 'wall concrete', 'wall ins form', 'gypsum composite board'] }],
+ # Log wall
+ [{ assembly_r: 0.1, layer_names: ['stucco', 'wall layer', 'plaster'] },
+ { assembly_r: 5.0, layer_names: ['stucco', 'osb sheathing', 'wall layer', 'plaster'] },
+ { assembly_r: 20.0, layer_names: ['stucco', 'wall rigid ins', 'osb sheathing', 'wall layer', 'plaster'] }],
+ # SIP wall
+ [{ assembly_r: 0.1, layer_names: ['vinyl siding', 'wall spline layer', 'wall ins layer', 'wall spline layer', 'osb sheathing', 'wood'] },
+ { assembly_r: 5.0, layer_names: ['vinyl siding', 'osb sheathing', 'wall spline layer', 'wall ins layer', 'wall spline layer', 'osb sheathing', 'wood'] },
+ { assembly_r: 20.0, layer_names: ['vinyl siding', 'osb sheathing', 'wall spline layer', 'wall ins layer', 'wall spline layer', 'osb sheathing', 'wood'] }],
+ # Solid Concrete wall
+ [{ assembly_r: 0.1, layer_names: ['wall layer'] },
+ { assembly_r: 5.0, layer_names: ['osb sheathing', 'wall layer'] },
+ { assembly_r: 20.0, layer_names: ['wall rigid ins', 'osb sheathing', 'wall layer'] }],
+ # Steel frame wall
+ [{ assembly_r: 0.1, layer_names: ['aluminum siding', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['aluminum siding', 'osb sheathing', 'wall stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['aluminum siding', 'wall rigid ins', 'osb sheathing', 'wall stud and cavity', 'gypsum board'] }],
+ # Stone wall
+ [{ assembly_r: 0.1, layer_names: ['brick veneer', 'wall layer', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['brick veneer', 'osb sheathing', 'wall layer', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['brick veneer', 'wall rigid ins', 'osb sheathing', 'wall layer', 'gypsum board'] }],
+ # Straw Bale wall
+ [{ assembly_r: 0.1, layer_names: ['fiber cement siding', 'wall layer', 'gypsum composite board'] },
+ { assembly_r: 5.0, layer_names: ['fiber cement siding', 'osb sheathing', 'wall layer', 'gypsum composite board'] },
+ { assembly_r: 20.0, layer_names: ['fiber cement siding', 'wall rigid ins', 'osb sheathing', 'wall layer', 'gypsum composite board'] }],
+ # Structural Brick wall
+ [{ assembly_r: 0.1, layer_names: ['stucco', 'wall layer', 'plaster'] },
+ { assembly_r: 5.0, layer_names: ['stucco', 'osb sheathing', 'wall layer', 'plaster'] },
+ { assembly_r: 20.0, layer_names: ['stucco', 'wall rigid ins', 'osb sheathing', 'wall layer', 'plaster'] }],
+ # Adobe wall
+ [{ assembly_r: 0.1, layer_names: ['vinyl siding', 'wall layer', 'wood'] },
+ { assembly_r: 5.0, layer_names: ['vinyl siding', 'osb sheathing', 'wall layer', 'wood'] },
+ { assembly_r: 20.0, layer_names: ['vinyl siding', 'wall rigid ins', 'osb sheathing', 'wall layer', 'wood'] }],
+ ]
+
+ hpxml = _create_hpxml('base-enclosure-walltypes.xml')
+ for i in 0..hpxml.walls.size - 2
+ walls_values[i].each do |wall_values|
+ hpxml.walls[i].insulation_assembly_r_value = wall_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s.start_with? "#{hpxml.walls[i].id}:" }[0]
+ _check_surface(hpxml.walls[i], os_surface, wall_values[:layer_names])
+ end
+ end
+ end
+
+ def test_foundation_walls
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Foundation wall w/ Assembly R-values
+ walls_values = [{ assembly_r: 0.1, layer_names: ['concrete'] },
+ { assembly_r: 5.0, layer_names: ['concrete', 'exterior vertical ins'] },
+ { assembly_r: 20.0, layer_names: ['concrete', 'exterior vertical ins'] }]
+
+ hpxml = _create_hpxml('base-foundation-unconditioned-basement-assembly-r.xml')
+ walls_values.each do |wall_values|
+ hpxml.foundation_walls[0].insulation_assembly_r_value = wall_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s == hpxml.foundation_walls[0].id }[0]
+ _check_surface(hpxml.foundation_walls[0], os_surface, wall_values[:layer_names])
+ end
+
+ # Foundation wall w/ Insulation Layers
+ walls_values = [{ interior_r: 0.0, exterior_r: 0.0, layer_names: ['concrete'] },
+ { interior_r: 5.0, exterior_r: 0.0, layer_names: ['concrete', 'interior vertical ins'] },
+ { interior_r: 20.0, exterior_r: 0.0, layer_names: ['concrete', 'interior vertical ins'] },
+ { interior_r: 0.0, exterior_r: 5.0, layer_names: ['concrete', 'exterior vertical ins'] },
+ { interior_r: 0.0, exterior_r: 20.0, layer_names: ['concrete', 'exterior vertical ins'] },
+ { interior_r: 5.0, exterior_r: 5.0, layer_names: ['concrete', 'interior vertical ins', 'exterior vertical ins'] },
+ { interior_r: 20.0, exterior_r: 20.0, layer_names: ['concrete', 'interior vertical ins', 'exterior vertical ins'] }]
+
+ hpxml = _create_hpxml('base-foundation-unconditioned-basement-wall-insulation.xml')
+ walls_values.each do |wall_values|
+ hpxml.foundation_walls[0].insulation_interior_r_value = wall_values[:interior_r]
+ hpxml.foundation_walls[0].insulation_interior_distance_to_top = 0.0
+ hpxml.foundation_walls[0].insulation_interior_distance_to_bottom = 8.0
+ hpxml.foundation_walls[0].insulation_exterior_r_value = wall_values[:exterior_r]
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_top = 0.0
+ hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = 8.0
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s == hpxml.foundation_walls[0].id }[0]
+ _check_surface(hpxml.foundation_walls[0], os_surface, wall_values[:layer_names])
+ end
+ end
+
+ def test_frame_floors
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Ceilings
+ ceilings_values = [{ assembly_r: 0.1, layer_names: ['ceiling stud and cavity', 'gypsum board'] },
+ { assembly_r: 5.0, layer_names: ['ceiling stud and cavity', 'gypsum board'] },
+ { assembly_r: 20.0, layer_names: ['ceiling loosefill ins', 'ceiling stud and cavity', 'gypsum board'] }]
+
+ hpxml = _create_hpxml('base-foundation-vented-crawlspace.xml')
+ ceilings_values.each do |ceiling_values|
+ hpxml.frame_floors[0].insulation_assembly_r_value = ceiling_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s == hpxml.frame_floors[0].id }[0]
+ _check_surface(hpxml.frame_floors[0], os_surface, ceiling_values[:layer_names])
+ end
+
+ # Floors
+ floors_values = [{ assembly_r: 0.1, layer_names: ['floor stud and cavity', 'floor covering'] },
+ { assembly_r: 5.0, layer_names: ['floor stud and cavity', 'osb sheathing', 'floor covering'] },
+ { assembly_r: 20.0, layer_names: ['floor stud and cavity', 'floor rigid ins', 'osb sheathing', 'floor covering'] }]
+
+ hpxml = _create_hpxml('base-foundation-vented-crawlspace.xml')
+ floors_values.each do |floor_values|
+ hpxml.frame_floors[1].insulation_assembly_r_value = floor_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s == hpxml.frame_floors[1].id }[0]
+ _check_surface(hpxml.frame_floors[1], os_surface, floor_values[:layer_names])
+ end
+ end
+
+ def test_slabs
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Slab
+ slabs_values = [{ perimeter_r: 0.0, under_r: 0.0, under_span: false, layer_names: ['concrete', 'floor covering'] },
+ { perimeter_r: 5.0, under_r: 0.0, under_span: false, layer_names: ['concrete', 'floor covering', 'exterior vertical ins'] },
+ { perimeter_r: 20.0, under_r: 0.0, under_span: false, layer_names: ['concrete', 'floor covering', 'exterior vertical ins'] },
+ { perimeter_r: 0.0, under_r: 5.0, under_span: false, layer_names: ['concrete', 'floor covering', 'interior horizontal ins', 'interior vertical ins'] },
+ { perimeter_r: 0.0, under_r: 20.0, under_span: false, layer_names: ['concrete', 'floor covering', 'interior horizontal ins', 'interior vertical ins'] },
+ { perimeter_r: 0.0, under_r: 5.0, under_span: true, layer_names: ['slab rigid ins', 'concrete', 'floor covering', 'interior vertical ins'] },
+ { perimeter_r: 0.0, under_r: 20.0, under_span: true, layer_names: ['slab rigid ins', 'concrete', 'floor covering', 'interior vertical ins'] },
+ { perimeter_r: 5.0, under_r: 5.0, under_span: false, layer_names: ['concrete', 'floor covering', 'interior horizontal ins', 'interior vertical ins', 'exterior vertical ins'] },
+ { perimeter_r: 20.0, under_r: 20.0, under_span: false, layer_names: ['concrete', 'floor covering', 'interior horizontal ins', 'interior vertical ins', 'exterior vertical ins'] }]
+
+ hpxml = _create_hpxml('base-foundation-slab.xml')
+ slabs_values.each do |slab_values|
+ hpxml.slabs[0].perimeter_insulation_r_value = slab_values[:perimeter_r]
+ hpxml.slabs[0].perimeter_insulation_depth = 2.0
+ hpxml.slabs[0].under_slab_insulation_r_value = slab_values[:under_r]
+ if slab_values[:under_span]
+ hpxml.slabs[0].under_slab_insulation_spans_entire_slab = true
+ hpxml.slabs[0].under_slab_insulation_width = nil
+ else
+ hpxml.slabs[0].under_slab_insulation_width = 2.0
+ hpxml.slabs[0].under_slab_insulation_spans_entire_slab = nil
+ end
+
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSurfaces.select { |s| s.name.to_s == hpxml.slabs[0].id }[0]
+ _check_surface(hpxml.slabs[0], os_surface, slab_values[:layer_names])
+ end
+ end
+
def test_windows
args_hash = {}
args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base.xml'))
@@ -26,9 +389,8 @@ def test_windows
assert_equal(window.shgc, os_simple_glazing.solarHeatGainCoefficient)
assert_in_epsilon(window.ufactor, UnitConversions.convert(os_simple_glazing.uFactor, 'W/(m^2*K)', 'Btu/(hr*ft^2*F)'), 0.001)
end
- end
- def test_windows_shading
+ # Check window shading
args_hash = {}
args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-enclosure-windows-shading.xml'))
model, hpxml = _test_measure(args_hash)
@@ -58,7 +420,7 @@ def test_windows_shading
subsurface_view_factor = 0.5
window_actuator = model.getEnergyManagementSystemActuators.select { |w| w.actuatedComponent.get.name.to_s == window.id }[0]
program_values = get_ems_values(model.getEnergyManagementSystemPrograms, 'fixedwindow view factor to ground program')
- assert_equal(subsurface_view_factor, program_values["#{window_actuator.name.to_s}"][0])
+ assert_equal(subsurface_view_factor, program_values["#{window_actuator.name}"][0])
end
end
@@ -75,9 +437,8 @@ def test_skylights
assert_equal(skylight.shgc, os_simple_glazing.solarHeatGainCoefficient)
assert_in_epsilon(skylight.ufactor / 1.2, UnitConversions.convert(os_simple_glazing.uFactor, 'W/(m^2*K)', 'Btu/(hr*ft^2*F)'), 0.001)
end
- end
- def test_skylights_shading
+ # Check skylight shading
args_hash = {}
args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-enclosure-skylights-shading.xml'))
model, hpxml = _test_measure(args_hash)
@@ -107,7 +468,137 @@ def test_skylights_shading
subsurface_view_factor = 0.05 # 6:12 pitch
skylight_actuator = model.getEnergyManagementSystemActuators.select { |w| w.actuatedComponent.get.name.to_s == skylight.id }[0]
program_values = get_ems_values(model.getEnergyManagementSystemPrograms, 'skylight view factor to ground program')
- assert_equal(subsurface_view_factor, program_values["#{skylight_actuator.name.to_s}"][0])
+ assert_equal(subsurface_view_factor, program_values["#{skylight_actuator.name}"][0])
+ end
+ end
+
+ def test_doors
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(@tmp_hpxml_path)
+
+ # Door
+ doors_values = [{ assembly_r: 0.1, layer_names: ['door material'] },
+ { assembly_r: 5.0, layer_names: ['door material'] },
+ { assembly_r: 20.0, layer_names: ['door material'] }]
+
+ hpxml = _create_hpxml('base.xml')
+ doors_values.each do |door_values|
+ hpxml.doors[0].r_value = door_values[:assembly_r]
+ XMLHelper.write_file(hpxml.to_oga, @tmp_hpxml_path)
+ model, hpxml = _test_measure(args_hash)
+
+ # Check properties
+ os_surface = model.getSubSurfaces.select { |s| s.name.to_s == hpxml.doors[0].id }[0]
+ _check_surface(hpxml.doors[0], os_surface, door_values[:layer_names])
+ end
+ end
+
+ def _check_surface(hpxml_surface, os_surface, expected_layer_names)
+ os_construction = os_surface.construction.get.to_LayeredConstruction.get
+
+ # Check exterior solar absorptance and emittance
+ exterior_layer = os_construction.getLayer(0).to_OpaqueMaterial.get
+ if hpxml_surface.respond_to? :solar_absorptance
+ assert_equal(hpxml_surface.solar_absorptance, exterior_layer.solarAbsorptance)
+ end
+ if hpxml_surface.respond_to? :emittance
+ assert_equal(hpxml_surface.emittance, exterior_layer.thermalAbsorptance)
+ end
+
+ # Check interior finish solar absorptance and emittance
+ if hpxml_surface.respond_to?(:interior_finish_type) && hpxml_surface.interior_finish_type != HPXML::InteriorFinishNone
+ interior_layer = os_construction.getLayer(os_construction.numLayers - 1).to_OpaqueMaterial.get
+ assert_equal(0.6, interior_layer.solarAbsorptance)
+ assert_equal(0.9, interior_layer.thermalAbsorptance)
+ end
+
+ # Check for appropriate construction layers (including Kiva insulation/custom blocks)
+
+ num_layers = os_construction.numLayers
+ if os_surface.is_a?(OpenStudio::Model::Surface) && os_surface.adjacentFoundation.is_initialized
+ adjacent_foundation = os_surface.adjacentFoundation.get
+ if adjacent_foundation.interiorHorizontalInsulationMaterial.is_initialized
+ num_layers += 1
+ end
+ if adjacent_foundation.exteriorHorizontalInsulationMaterial.is_initialized
+ num_layers += 1
+ end
+ if adjacent_foundation.interiorVerticalInsulationMaterial.is_initialized
+ num_layers += 1
+ end
+ if adjacent_foundation.exteriorVerticalInsulationMaterial.is_initialized
+ num_layers += 1
+ end
+ num_layers += adjacent_foundation.numberofCustomBlocks
+ end
+ assert_equal(expected_layer_names.size, num_layers)
+
+ # Construction layers
+ for i in 0..os_construction.numLayers - 1
+ layer_name = os_construction.getLayer(i).name.to_s
+ expected_layer_name = expected_layer_names[i]
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
+ curr_layer_num = os_construction.numLayers
+
+ if not adjacent_foundation.nil?
+ # Kiva - Interior Horizontal Insulation
+ if adjacent_foundation.interiorHorizontalInsulationMaterial.is_initialized
+ layer_name = adjacent_foundation.interiorHorizontalInsulationMaterial.get.name.to_s
+ expected_layer_name = expected_layer_names[curr_layer_num]
+ curr_layer_num += 1
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
+
+ # Kiva - Exterior Horizontal Insulation
+ if adjacent_foundation.exteriorHorizontalInsulationMaterial.is_initialized
+ layer_name = adjacent_foundation.exteriorHorizontalInsulationMaterial.get.name.to_s
+ expected_layer_name = expected_layer_names[curr_layer_num]
+ curr_layer_num += 1
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
+
+ # Kiva - Interior Vertical Insulation
+ if adjacent_foundation.interiorVerticalInsulationMaterial.is_initialized
+ layer_name = adjacent_foundation.interiorVerticalInsulationMaterial.get.name.to_s
+ expected_layer_name = expected_layer_names[curr_layer_num]
+ curr_layer_num += 1
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
+
+ # Kiva - Exterior Vertical Insulation
+ if adjacent_foundation.exteriorVerticalInsulationMaterial.is_initialized
+ layer_name = adjacent_foundation.exteriorVerticalInsulationMaterial.get.name.to_s
+ expected_layer_name = expected_layer_names[curr_layer_num]
+ curr_layer_num += 1
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
+
+ # Kiva - Custom insulation blocks
+ for i in 0..adjacent_foundation.numberofCustomBlocks - 1
+ layer_name = adjacent_foundation.customBlocks[i].material.name.to_s
+ expected_layer_name = expected_layer_names[curr_layer_num]
+ curr_layer_num += 1
+ if not layer_name.start_with? expected_layer_name
+ puts "'#{layer_name}' does not start with '#{expected_layer_name}'"
+ end
+ assert(layer_name.start_with? expected_layer_name)
+ end
end
end
@@ -142,10 +633,14 @@ def _test_measure(args_hash)
# assert that it ran correctly
assert_equal('Success', result.value.valueName)
- hpxml = HPXML.new(hpxml_path: args_hash['hpxml_path'])
+ hpxml = HPXML.new(hpxml_path: File.join(File.dirname(__FILE__), 'in.xml'))
File.delete(File.join(File.dirname(__FILE__), 'in.xml'))
return model, hpxml
end
+
+ def _create_hpxml(hpxml_name)
+ return HPXML.new(hpxml_path: File.join(@sample_files_path, hpxml_name))
+ end
end
diff --git a/HPXMLtoOpenStudio/tests/test_hvac.rb b/HPXMLtoOpenStudio/tests/test_hvac.rb
index 30bd1652f4..0618d46f71 100644
--- a/HPXMLtoOpenStudio/tests/test_hvac.rb
+++ b/HPXMLtoOpenStudio/tests/test_hvac.rb
@@ -94,13 +94,32 @@ def test_room_air_conditioner
# Get HPXML values
cooling_system = hpxml.cooling_systems[0]
eer = cooling_system.cooling_efficiency_eer
+ ceer = eer / 1.01 # convert to ceer
+ cop = UnitConversions.convert(ceer, 'Btu/hr', 'W') # Expected value
capacity = UnitConversions.convert(cooling_system.cooling_capacity, 'Btu/hr', 'W')
# Check cooling coil
assert_equal(1, model.getCoilCoolingDXSingleSpeeds.size)
clg_coil = model.getCoilCoolingDXSingleSpeeds[0]
- cop = 2.49 # Expected value
- assert_in_epsilon(cop, clg_coil.ratedCOP.get, 0.01)
+ assert_in_epsilon(cop, clg_coil.ratedCOP.get, 0.001)
+ assert_in_epsilon(capacity, clg_coil.ratedTotalCoolingCapacity.get, 0.01)
+ end
+
+ def test_room_air_conditioner_ceer
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-room-ac-only-ceer.xml'))
+ model, hpxml = _test_measure(args_hash)
+
+ # Get HPXML values
+ cooling_system = hpxml.cooling_systems[0]
+ ceer = cooling_system.cooling_efficiency_ceer
+ cop = UnitConversions.convert(ceer, 'Btu/hr', 'W') # Expected value
+ capacity = UnitConversions.convert(cooling_system.cooling_capacity, 'Btu/hr', 'W')
+
+ # Check cooling coil
+ assert_equal(1, model.getCoilCoolingDXSingleSpeeds.size)
+ clg_coil = model.getCoilCoolingDXSingleSpeeds[0]
+ assert_in_epsilon(cop, clg_coil.ratedCOP.get, 0.001)
assert_in_epsilon(capacity, clg_coil.ratedTotalCoolingCapacity.get, 0.01)
end
@@ -643,7 +662,7 @@ def test_shared_ground_loop_ground_to_air_heat_pump
def test_install_quality_air_to_air_heat_pump_1_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-air-to-air-heat-pump-1-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -670,8 +689,8 @@ def test_install_quality_air_to_air_heat_pump_1_speed_ratio
rated_airflow_cfm_htg = UnitConversions.convert(htg_coil.ratedAirFlowRate.get, 'm^3/s', 'cfm')
# Fan
- fanonoff = unitary_system.supplyFan.get.to_FanOnOff.get
- assert_in_epsilon(fan_watts_cfm, fanonoff.pressureRise / fanonoff.fanEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+ fan = unitary_system.supplyFan.get.to_FanSystemModel.get
+ assert_in_epsilon(fan_watts_cfm, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
# Check installation quality EMS
program_values = get_ems_values(model.getEnergyManagementSystemPrograms, "#{unitary_system.name} install quality")
@@ -684,7 +703,7 @@ def test_install_quality_air_to_air_heat_pump_1_speed_ratio
def test_install_quality_air_to_air_heat_pump_2_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-air-to-air-heat-pump-2-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -694,7 +713,7 @@ def test_install_quality_air_to_air_heat_pump_2_speed_ratio
def test_install_quality_air_to_air_heat_pump_var_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-air-to-air-heat-pump-var-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-air-to-air-heat-pump-var-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -704,7 +723,7 @@ def test_install_quality_air_to_air_heat_pump_var_speed_ratio
def test_install_quality_furnace_central_air_conditioner_1_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-furnace-gas-central-ac-1-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -727,9 +746,9 @@ def test_install_quality_furnace_central_air_conditioner_1_speed_ratio
rated_airflow_cfm = UnitConversions.convert(clg_coil.ratedAirFlowRate.get, 'm^3/s', 'cfm')
# Fan
- fanonoff = unitary_system.supplyFan.get.to_FanOnOff.get
- assert_in_epsilon(fan_watts_cfm, fanonoff.pressureRise / fanonoff.fanEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
- assert_in_epsilon(fan_watts_cfm2, fanonoff.pressureRise / fanonoff.fanEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+ fan = unitary_system.supplyFan.get.to_FanSystemModel.get
+ assert_in_epsilon(fan_watts_cfm, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+ assert_in_epsilon(fan_watts_cfm2, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
# Check installation quality EMS
program_values = get_ems_values(model.getEnergyManagementSystemPrograms, "#{unitary_system.name} install quality")
@@ -743,7 +762,7 @@ def test_install_quality_furnace_central_air_conditioner_1_speed_ratio
def test_install_quality_furnace_central_air_conditioner_2_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-furnace-gas-central-ac-2-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -753,7 +772,7 @@ def test_install_quality_furnace_central_air_conditioner_2_speed_ratio
def test_install_quality_furnace_central_air_conditioner_var_speed_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-furnace-gas-central-ac-var-speed.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -763,7 +782,7 @@ def test_install_quality_furnace_central_air_conditioner_var_speed_ratio
def test_install_quality_furnace_gas_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-furnace-gas-only.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-furnace-gas-only.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -775,17 +794,54 @@ def test_install_quality_furnace_gas_ratio
unitary_system = model.getAirLoopHVACUnitarySystems[0]
# Fan
- fanonoff = unitary_system.supplyFan.get.to_FanOnOff.get
- assert_in_epsilon(fan_watts_cfm, fanonoff.pressureRise / fanonoff.fanEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+ fan = unitary_system.supplyFan.get.to_FanSystemModel.get
+ assert_in_epsilon(fan_watts_cfm, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
end
def test_install_quality_ground_to_air_heat_pump_ratio
- # TODO
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-ground-to-air-heat-pump.xml'))
+ model, hpxml = _test_measure(args_hash)
+
+ # Get HPXML values
+ heat_pump = hpxml.heat_pumps[0]
+ airflow_defect = heat_pump.airflow_defect_ratio
+ charge_defect = heat_pump.charge_defect_ratio
+ fan_watts_cfm = heat_pump.fan_watts_per_cfm
+
+ # model objects:
+ # Unitary system
+ assert_equal(1, model.getAirLoopHVACUnitarySystems.size)
+ unitary_system = model.getAirLoopHVACUnitarySystems[0]
+ cooling_cfm = UnitConversions.convert(unitary_system.supplyAirFlowRateDuringCoolingOperation.get, 'm^3/s', 'cfm')
+ heating_cfm = UnitConversions.convert(unitary_system.supplyAirFlowRateDuringHeatingOperation.get, 'm^3/s', 'cfm')
+
+ # Cooling coil
+ assert_equal(1, model.getCoilCoolingWaterToAirHeatPumpEquationFits.size)
+ clg_coil = model.getCoilCoolingWaterToAirHeatPumpEquationFits[0]
+ rated_airflow_cfm_clg = UnitConversions.convert(clg_coil.ratedAirFlowRate.get, 'm^3/s', 'cfm')
+
+ # Heating coil
+ assert_equal(1, model.getCoilHeatingWaterToAirHeatPumpEquationFits.size)
+ htg_coil = model.getCoilHeatingWaterToAirHeatPumpEquationFits[0]
+ rated_airflow_cfm_htg = UnitConversions.convert(htg_coil.ratedAirFlowRate.get, 'm^3/s', 'cfm')
+
+ # Fan
+ fan = unitary_system.supplyFan.get.to_FanSystemModel.get
+ assert_in_epsilon(fan_watts_cfm, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+
+ # Check installation quality EMS
+ program_values = get_ems_values(model.getEnergyManagementSystemPrograms, "#{unitary_system.name} install quality")
+
+ # defect ratios in EMS is calculated correctly
+ assert_in_epsilon(program_values['F_CH'].sum, charge_defect, 0.01)
+ assert_in_epsilon(program_values['FF_AF_c'].sum, cooling_cfm / rated_airflow_cfm_clg, 0.01)
+ assert_in_epsilon(program_values['FF_AF_h'].sum, heating_cfm / rated_airflow_cfm_htg, 0.01)
end
def test_install_quality_mini_split_air_conditioner_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-mini-split-air-conditioner-only-ducted.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-mini-split-air-conditioner-only-ducted.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -795,7 +851,7 @@ def test_install_quality_mini_split_air_conditioner_ratio
def test_install_quality_mini_split_heat_pump_ratio
args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-all-mini-split-heat-pump-ducted.xml'))
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-hvac-install-quality-mini-split-heat-pump-ducted.xml'))
model, hpxml = _test_measure(args_hash)
# Get HPXML values
@@ -919,8 +975,8 @@ def _check_install_quality_multispeed_ratio(hpxml_clg_sys, model, hpxml_htg_sys
end
# Fan
- fanonoff = unitary_system.supplyFan.get.to_FanOnOff.get
- assert_in_epsilon(fan_watts_cfm, fanonoff.pressureRise / fanonoff.fanEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
+ fan = unitary_system.supplyFan.get.to_FanSystemModel.get
+ assert_in_epsilon(fan_watts_cfm, fan.designPressureRise / fan.fanTotalEfficiency * UnitConversions.convert(1.0, 'cfm', 'm^3/s'), 0.01)
# Check installation quality EMS
program_values = get_ems_values(model.getEnergyManagementSystemPrograms, "#{unitary_system.name} install quality")
diff --git a/HPXMLtoOpenStudio/tests/test_water_heater.rb b/HPXMLtoOpenStudio/tests/test_water_heater.rb
index b1f6ea0bc4..6c1354ad5d 100644
--- a/HPXMLtoOpenStudio/tests/test_water_heater.rb
+++ b/HPXMLtoOpenStudio/tests/test_water_heater.rb
@@ -45,34 +45,36 @@ def test_tank_gas
end
def test_tank_gas_uef
- args_hash = {}
- args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, 'base-dhw-tank-gas-uef.xml'))
- model, hpxml = _test_measure(args_hash)
-
- # Get HPXML values
- water_heating_system = hpxml.water_heating_systems[0]
-
- # Expected value
- tank_volume = UnitConversions.convert(water_heating_system.tank_volume * 0.95, 'gal', 'm^3') # convert to actual volume
- cap = UnitConversions.convert(water_heating_system.heating_capacity / 1000.0, 'kBtu/hr', 'W')
- fuel = EPlus.fuel_type(water_heating_system.fuel_type)
- ua = UnitConversions.convert(6.476, 'Btu/(hr*F)', 'W/K')
- t_set = UnitConversions.convert(water_heating_system.temperature, 'F', 'C') + 1 # setpoint + 1/2 deadband
- ther_eff = 0.762
- loc = water_heating_system.location
-
- # Check water heater
- assert_equal(1, model.getWaterHeaterMixeds.size)
- wh = model.getWaterHeaterMixeds[0]
- assert_equal(fuel, wh.heaterFuelType)
- assert_equal(loc, wh.ambientTemperatureThermalZone.get.name.get)
- assert_in_epsilon(tank_volume, wh.tankVolume.get, 0.001)
- assert_in_epsilon(cap, wh.heaterMaximumCapacity.get, 0.001)
- assert_in_epsilon(ua, wh.onCycleLossCoefficienttoAmbientTemperature.get, 0.001)
- assert_in_epsilon(ua, wh.offCycleLossCoefficienttoAmbientTemperature.get, 0.001)
- assert_in_epsilon(t_set, wh.setpointTemperatureSchedule.get.to_ScheduleConstant.get.value, 0.001)
- assert_in_epsilon(ther_eff, wh.heaterThermalEfficiency.get, 0.001)
- assert_equal(0.64, wh.offCycleLossFractiontoThermalZone)
+ ['base-dhw-tank-gas-uef.xml', 'base-dhw-tank-gas-uef-fhr.xml'].each do |hpxml_name|
+ args_hash = {}
+ args_hash['hpxml_path'] = File.absolute_path(File.join(sample_files_dir, hpxml_name))
+ model, hpxml = _test_measure(args_hash)
+
+ # Get HPXML values
+ water_heating_system = hpxml.water_heating_systems[0]
+
+ # Expected value
+ tank_volume = UnitConversions.convert(water_heating_system.tank_volume * 0.95, 'gal', 'm^3') # convert to actual volume
+ cap = UnitConversions.convert(water_heating_system.heating_capacity / 1000.0, 'kBtu/hr', 'W')
+ fuel = EPlus.fuel_type(water_heating_system.fuel_type)
+ ua = UnitConversions.convert(6.476, 'Btu/(hr*F)', 'W/K')
+ t_set = UnitConversions.convert(water_heating_system.temperature, 'F', 'C') + 1 # setpoint + 1/2 deadband
+ ther_eff = 0.762
+ loc = water_heating_system.location
+
+ # Check water heater
+ assert_equal(1, model.getWaterHeaterMixeds.size)
+ wh = model.getWaterHeaterMixeds[0]
+ assert_equal(fuel, wh.heaterFuelType)
+ assert_equal(loc, wh.ambientTemperatureThermalZone.get.name.get)
+ assert_in_epsilon(tank_volume, wh.tankVolume.get, 0.001)
+ assert_in_epsilon(cap, wh.heaterMaximumCapacity.get, 0.001)
+ assert_in_epsilon(ua, wh.onCycleLossCoefficienttoAmbientTemperature.get, 0.001)
+ assert_in_epsilon(ua, wh.offCycleLossCoefficienttoAmbientTemperature.get, 0.001)
+ assert_in_epsilon(t_set, wh.setpointTemperatureSchedule.get.to_ScheduleConstant.get.value, 0.001)
+ assert_in_epsilon(ther_eff, wh.heaterThermalEfficiency.get, 0.001)
+ assert_equal(0.64, wh.offCycleLossFractiontoThermalZone)
+ end
end
def test_tank_oil
diff --git a/README.md b/README.md
index 1396f005ca..61fff3a7ac 100644
--- a/README.md
+++ b/README.md
@@ -28,11 +28,11 @@ This repository contains two OpenStudio measures:
## Projects
The OpenStudio-HPXML workflow is used by a number of other residential projects, including:
-- [Energy Rating Index (ERI)](https://github.com/NREL/OpenStudio-ERI)
-- Home Energy Score (pending)
-- Weatherization Assistant (pending)
-- ResStock (pending)
+- [Energy Rating Index (ERI) and ENERGY STAR](https://github.com/NREL/OpenStudio-ERI)
+- [Home Energy Score](https://betterbuildingssolutioncenter.energy.gov/home-energy-score)
- [UrbanOpt](https://www.nrel.gov/buildings/urbanopt.html)
+- ResStock (pending)
+- Weatherization Assistant (pending)
## License
diff --git a/SimulationOutputReport/measure.rb b/SimulationOutputReport/measure.rb
index 78021187b4..38be83774e 100644
--- a/SimulationOutputReport/measure.rb
+++ b/SimulationOutputReport/measure.rb
@@ -5,6 +5,7 @@
require_relative 'resources/constants.rb'
require_relative '../HPXMLtoOpenStudio/resources/constants.rb'
+require_relative '../HPXMLtoOpenStudio/resources/energyplus.rb'
require_relative '../HPXMLtoOpenStudio/resources/hpxml.rb'
require_relative '../HPXMLtoOpenStudio/resources/unit_conversions.rb'
@@ -113,12 +114,21 @@ def outputs
setup_outputs
+ all_outputs = []
+ all_outputs << @fuels
+ all_outputs << @end_uses
+ all_outputs << @loads
+ all_outputs << @unmet_loads
+ all_outputs << @peak_fuels
+ all_outputs << @peak_loads
+ all_outputs << @component_loads
+ all_outputs << @hot_water_uses
+
output_names = []
- @fuels.each do |fuel_type, fuel|
- output_names << get_runner_output_name(fuel)
- end
- @end_uses.each do |key, end_use|
- output_names << get_runner_output_name(end_use)
+ all_outputs.each do |outputs|
+ outputs.each do |key, obj|
+ output_names << get_runner_output_name(obj)
+ end
end
output_names.each do |output_name|
@@ -209,6 +219,7 @@ def energyPlusOutputRequests(runner, user_arguments)
# Add component load outputs
@component_loads.each do |key, comp_load|
next if comp_loads_program.nil?
+
result << OpenStudio::IdfObject.load("EnergyManagementSystem:OutputVariable,#{comp_load.ems_variable}_annual_outvar,#{comp_load.ems_variable},Summed,ZoneTimestep,#{comp_loads_program.name},J;").get
result << OpenStudio::IdfObject.load("Output:Variable,*,#{comp_load.ems_variable}_annual_outvar,runperiod;").get
end
@@ -421,7 +432,7 @@ def run(runner, user_arguments)
# Write/report results
write_annual_output_results(runner, outputs, output_format, annual_output_path)
- report_sim_outputs(outputs, runner)
+ report_sim_outputs(runner)
write_eri_output_results(outputs, eri_output_path)
write_timeseries_output_results(runner, output_format,
timeseries_output_path,
@@ -988,16 +999,36 @@ def write_annual_output_results(runner, outputs, output_format, annual_output_pa
runner.registerInfo("Wrote annual output results to #{annual_output_path}.")
end
- def report_sim_outputs(outputs, runner)
- @fuels.each do |fuel_type, fuel|
- output_name = get_runner_output_name(fuel)
- runner.registerValue(output_name, fuel.annual_output.round(2))
- runner.registerInfo("Registering #{fuel.annual_output.round(2)} for #{output_name}.")
+ def report_sim_outputs(runner)
+ all_outputs = []
+ all_outputs << @fuels
+ all_outputs << @end_uses
+ all_outputs << @loads
+ all_outputs << @unmet_loads
+ all_outputs << @peak_fuels
+ all_outputs << @peak_loads
+ if @component_loads.values.map { |load| load.annual_output }.sum != 0 # Skip if component loads not calculated
+ all_outputs << @component_loads
end
- @end_uses.each do |key, end_use|
- output_name = get_runner_output_name(end_use)
- runner.registerValue(output_name, end_use.annual_output.round(2))
- runner.registerInfo("Registering #{end_use.annual_output.round(2)} for #{output_name}.")
+ all_outputs << @hot_water_uses
+
+ all_outputs.each do |outputs|
+ outputs.each do |key, obj|
+ output_name = get_runner_output_name(obj)
+ output_val = obj.annual_output.round(2)
+ runner.registerValue(output_name, output_val)
+ runner.registerInfo("Registering #{output_val} for #{output_name}.")
+ next unless key == FT::Elec && obj.is_a?(Fuel)
+
+ # Also add Net Electricity
+ elec_total = @fuels[FT::Elec]
+ elec_pv_produced = @end_uses[[FT::Elec, EUT::PV]]
+ elec_generator_produced = @end_uses[[FT::Elec, EUT::Generator]]
+ output_name = 'Fuel Use: Electricity: Net (MBtu)'
+ output_val = (elec_total.annual_output + elec_pv_produced.annual_output + elec_generator_produced.annual_output).round(2)
+ runner.registerValue(output_name, output_val)
+ runner.registerInfo("Registering #{output_val} for #{output_name}.")
+ end
end
end
@@ -1470,6 +1501,8 @@ def get_hpxml_eec_cools()
eec_cools[sys_id] = get_eri_eec_value_numerator('SEER') / clg_system.cooling_efficiency_seer
elsif not clg_system.cooling_efficiency_eer.nil?
eec_cools[sys_id] = get_eri_eec_value_numerator('EER') / clg_system.cooling_efficiency_eer
+ elsif not clg_system.cooling_efficiency_ceer.nil?
+ eec_cools[sys_id] = get_eri_eec_value_numerator('CEER') / clg_system.cooling_efficiency_ceer
end
if clg_system.cooling_system_type == HPXML::HVACTypeEvaporativeCooler
@@ -1550,7 +1583,7 @@ def get_hpxml_eec_vent_precools()
end
def get_eri_eec_value_numerator(unit)
- if ['HSPF', 'SEER', 'EER'].include? unit
+ if ['HSPF', 'SEER', 'EER', 'CEER'].include? unit
return 3.413
elsif ['AFUE', 'COP', 'Percent', 'EF'].include? unit
return 1.0
@@ -2404,7 +2437,7 @@ def self.WaterHeating(fuel)
return { 'OpenStudio::Model::WaterHeaterMixed' => ["Water Heater #{fuel} Energy", "Water Heater Off Cycle Parasitic #{fuel} Energy", "Water Heater On Cycle Parasitic #{fuel} Energy"],
'OpenStudio::Model::WaterHeaterStratified' => ["Water Heater #{fuel} Energy", "Water Heater Off Cycle Parasitic #{fuel} Energy", "Water Heater On Cycle Parasitic #{fuel} Energy"],
'OpenStudio::Model::CoilWaterHeatingAirToWaterHeatPumpWrapped' => ["Cooling Coil Water Heating #{fuel} Energy"],
- 'OpenStudio::Model::FanOnOff' => ["Fan #{fuel} Energy"] }
+ 'OpenStudio::Model::FanOnOff' => ["Fan #{fuel} Energy"] } # TOOD: Update if this changes to FanSystemModel per https://github.com/NREL/OpenStudio/issues/4334
end
def self.WaterHeatingLoad
diff --git a/SimulationOutputReport/measure.xml b/SimulationOutputReport/measure.xml
index 0bc7874378..0b32f0eb92 100644
--- a/SimulationOutputReport/measure.xml
+++ b/SimulationOutputReport/measure.xml
@@ -3,8 +3,8 @@
3.0
simulation_output_report
df9d170c-c21a-4130-866d-0d46b06073fd
- cad6dfc5-7e51-41cf-a31e-d634e0e439fb
- 20210510T230920Z
+ 036a34fa-a458-4aff-a0a6-18d9029a1f7b
+ 20210625T191456Z
9BF1E6AC
SimulationOutputReport
HPXML Simulation Output Report
@@ -899,6 +899,356 @@
Double
false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -943,7 +1293,7 @@
measure.rb
rb
script
- F21B59B8
+ 02DBEC40
diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst
index d3537e6a33..a30e7d46e2 100644
--- a/docs/source/getting_started.rst
+++ b/docs/source/getting_started.rst
@@ -6,7 +6,7 @@ Setup
To get started:
-#. Download `OpenStudio 3.2.0 `_ and install the Command Line Interface/EnergyPlus components, or use the `nrel/openstudio docker image `_.
+#. Download `OpenStudio 3.2.1 `_ and install the Command Line Interface/EnergyPlus components, or use the `nrel/openstudio docker image `_.
#. Download the `latest release `_.
Running
diff --git a/docs/source/workflow_inputs.rst b/docs/source/workflow_inputs.rst
index 715aea525e..e68c4d1853 100644
--- a/docs/source/workflow_inputs.rst
+++ b/docs/source/workflow_inputs.rst
@@ -160,14 +160,15 @@ Building site information is entered in ``/HPXML/Building/BuildingDetails/Buildi
For each neighboring building defined, additional information is entered in a ``extension/Neighbors/NeighborBuilding``.
- ============ ======== ======= =========== ======== ======== =============================================
- Element Type Units Constraints Required Default Notes
- ============ ======== ======= =========== ======== ======== =============================================
- ``Azimuth`` integer deg 0 - 359 Yes Direction of neighbors (clockwise from North)
- ``Distance`` double ft > 0 Yes Distance of neighbor from the dwelling unit
- ``Height`` double ft > 0 No See [#]_ Height of neighbor
- ============ ======== ======= =========== ======== ======== =============================================
+ ============================== ================= ================ =================== ======== ======== =============================================
+ Element Type Units Constraints Required Default Notes
+ ============================== ================= ================ =================== ======== ======== =============================================
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ Yes Direction of neighbors (clockwise from North)
+ ``Distance`` double ft > 0 Yes Distance of neighbor from the dwelling unit
+ ``Height`` double ft > 0 No See [#]_ Height of neighbor
+ ============================== ================= ================ =================== ======== ======== =============================================
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
.. [#] If Height not provided, assumed to be same height as the dwelling unit.
HPXML Building Occupancy
@@ -195,7 +196,7 @@ Building construction is entered in ``/HPXML/Building/BuildingDetails/BuildingSu
``ResidentialFacilityType`` string See [#]_ Yes Type of dwelling unit
``NumberofConditionedFloors`` double > 0 Yes Number of conditioned floors (including a basement)
``NumberofConditionedFloorsAboveGrade`` double > 0, <= NumberofConditionedFloors Yes Number of conditioned floors above grade (including a walkout basement)
- ``NumberofBedrooms`` integer > 0 [#]_ Yes Number of bedrooms [#]_
+ ``NumberofBedrooms`` integer > 0 Yes Number of bedrooms [#]_
``NumberofBathrooms`` integer > 0 No See [#]_ Number of bathrooms
``ConditionedFloorArea`` double ft2 > 0 Yes Floor area within conditioned space boundary
``ConditionedBuildingVolume`` or ``AverageCeilingHeight`` double ft3 or ft > 0 No See [#]_ Volume/ceiling height within conditioned space boundary
@@ -203,7 +204,6 @@ Building construction is entered in ``/HPXML/Building/BuildingDetails/BuildingSu
========================================================= ======== ========= ================================= ======== ======== =======================================================================
.. [#] ResidentialFacilityType choices are "single-family detached", "single-family attached", "apartment unit", or "manufactured home".
- .. [#] NumberofBedrooms must also be <= (ConditionedFloorArea-120)/70.
.. [#] NumberofBedrooms is currently used to determine usage of plug loads, appliances, hot water, etc.
.. [#] If NumberofBathrooms not provided, calculated as NumberofBedrooms/2 + 0.5 based on the `2010 BAHSP `_.
.. [#] If neither ConditionedBuildingVolume nor AverageCeilingHeight provided, AverageCeilingHeight defaults to 8.0.
@@ -248,8 +248,8 @@ For example, a foundation wall between the unit's vented crawlspace and the neig
It is the software tool's responsibility to provide the appropriate building surfaces.
While some error-checking is in place, it is not possible to know whether some surfaces are incorrectly missing.
-Also note that wall and roof surfaces do not require an azimuth to be specified.
-Rather, only the windows/skylights themselves require an azimuth.
+Also note that wall and roof surfaces do not require an azimuth/orientation to be specified.
+Rather, only the windows/skylights themselves require an azimuth/orientation.
Thus, software tools can choose to use a single wall (or roof) surface to represent multiple wall (or roof) surfaces for the entire building if all their other properties (construction type, interior/exterior adjacency, etc.) are identical.
HPXML Air Infiltration
@@ -308,36 +308,40 @@ Each pitched or flat roof surface that is exposed to ambient conditions is enter
For a multifamily building where the dwelling unit has another dwelling unit above it, the surface between the two dwelling units should be considered a ``FrameFloor`` and not a ``Roof``.
- ====================================== ================ ============ ================= ========= ============================== ==================================
- Element Type Units Constraints Required Default Notes
- ====================================== ================ ============ ================= ========= ============================== ==================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
- ``Area`` double ft2 > 0 Yes Gross area (including skylights)
- ``Azimuth`` integer deg 0 - 359 No See [#]_ Azimuth (clockwise from North)
- ``RoofType`` string See [#]_ No asphalt or fiberglass shingles Roof type
- ``SolarAbsorptance`` or ``RoofColor`` double or string 0 - 1 or See [#]_ Yes See [#]_ Solar absorptance or color
- ``Emittance`` double 0 - 1 No 0.90 Emittance
- ``Pitch`` integer ?:12 >= 0 Yes Pitch
- ``RadiantBarrier`` boolean No false Presence of radiant barrier
- ``RadiantBarrierGrade`` integer 1 - 3 See [#]_ Radiant barrier installation grade
- ``Insulation/SystemIdentifier`` id Yes Unique identifier
- ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
- ====================================== ================ ============ ================= ========= ============================== ==================================
+ ====================================== ================= ================ ===================== ========= ============================== ==================================
+ Element Type Units Constraints Required Default Notes
+ ====================================== ================= ================ ===================== ========= ============================== ==================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
+ ``Area`` double ft2 > 0 Yes Gross area (including skylights)
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ No See [#]_ Direction (clockwise from North)
+ ``RoofType`` string See [#]_ No asphalt or fiberglass shingles Roof type
+ ``RoofColor`` or ``SolarAbsorptance`` string or double See [#]_ or 0 - 1 No medium Roof color or solar absorptance [#]_
+ ``Emittance`` double 0 - 1 No 0.90 Emittance
+ ``InteriorFinish/Type`` string See [#]_ No See [#]_ Interior finish material
+ ``InteriorFinish/Thickness`` double in >= 0 No 0.5 Interior finish thickness
+ ``Pitch`` integer ?:12 >= 0 Yes Pitch
+ ``RadiantBarrier`` boolean No false Presence of radiant barrier
+ ``RadiantBarrierGrade`` integer 1 - 3 No 1 Radiant barrier installation grade
+ ``Insulation/SystemIdentifier`` id Yes Unique identifier
+ ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
+ ====================================== ================= ================ ===================== ========= ============================== ==================================
.. [#] InteriorAdjacentTo choices are "attic - vented", "attic - unvented", "living space", or "garage".
See :ref:`hpxmllocations` for descriptions.
- .. [#] If Azimuth not provided, modeled as four surfaces of equal area facing every direction.
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
+ .. [#] If neither Azimuth nor Orientation provided, modeled as four surfaces of equal area facing every direction.
.. [#] RoofType choices are "asphalt or fiberglass shingles", "wood shingles or shakes", "slate or tile shingles", or "metal surfacing".
.. [#] RoofColor choices are "light", "medium", "medium dark", "dark", or "reflective".
- .. [#] If SolarAbsorptance not provided, defaults based on RoofColor/RoofType:
+ .. [#] If SolarAbsorptance not provided, defaults based on RoofType and RoofColor:
- **asphalt or fiberglass shingles**: dark=0.92, medium dark=0.89, medium=0.85, light=0.75, reflective=0.50
- **wood shingles or shakes**: dark=0.92, medium dark=0.89, medium=0.85, light=0.75, reflective=0.50
- **slate or tile shingles**: dark=0.90, medium dark=0.83, medium=0.75, light=0.60, reflective=0.30
- **metal surfacing**: dark=0.90, medium dark=0.83, medium=0.75, light=0.60, reflective=0.30
- .. [#] RadiantBarrierGrade only required if RadiantBarrier is provided.
+ .. [#] InteriorFinish/Type choices are "gypsum board", "gypsum composite board", "plaster", "wood", "other", or "none".
+ .. [#] InteriorFinish/Type defaults to "gypsum board" if InteriorAdjacentTo is living space, otherwise "none".
.. [#] AssemblyEffectiveRValue includes all material layers, interior/exterior air films, and insulation installation grade.
HPXML Rim Joists
@@ -345,27 +349,28 @@ HPXML Rim Joists
Each rim joist surface (i.e., the perimeter of floor joists typically found between stories of a building or on top of a foundation wall) is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/RimJoists/RimJoist``.
- ====================================== ================ ============ ================= ======== =========== ==============================
- Element Type Units Constraints Required Default Notes
- ====================================== ================ ============ ================= ======== =========== ==============================
- ``SystemIdentifier`` id Yes Unique identifier
- ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
- ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
- ``Area`` double ft2 > 0 Yes Gross area
- ``Azimuth`` integer deg 0 - 359 No See [#]_ Azimuth (clockwise from North)
- ``Siding`` string See [#]_ No wood siding Siding material
- ``SolarAbsorptance`` or ``Color`` double or string 0 - 1 or See [#]_ Yes See [#]_ Solar absorptance or color
- ``Emittance`` double 0 - 1 No 0.90 Emittance
- ``Insulation/SystemIdentifier`` id Yes Unique identifier
- ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
- ====================================== ================ ============ ================= ======== =========== ==============================
+ ====================================== ================= ================ ===================== ======== =========== ==============================
+ Element Type Units Constraints Required Default Notes
+ ====================================== ================= ================ ===================== ======== =========== ==============================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
+ ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
+ ``Area`` double ft2 > 0 Yes Gross area
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ No See [#]_ Direction (clockwise from North)
+ ``Siding`` string See [#]_ No wood siding Siding material
+ ``Color`` or ``SolarAbsorptance`` string or double See [#]_ or 0 - 1 No medium Color or solar absorptance [#]_
+ ``Emittance`` double 0 - 1 No 0.90 Emittance
+ ``Insulation/SystemIdentifier`` id Yes Unique identifier
+ ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
+ ====================================== ================= ================ ===================== ======== =========== ==============================
.. [#] ExteriorAdjacentTo choices are "outside", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "garage", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
See :ref:`hpxmllocations` for descriptions.
.. [#] InteriorAdjacentTo choices are "living space", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", or "garage".
See :ref:`hpxmllocations` for descriptions.
- .. [#] If Azimuth not provided, modeled as four surfaces of equal area facing every direction.
- .. [#] Siding choices are "wood siding", "vinyl siding", "stucco", "fiber cement siding", "brick veneer", or "aluminum siding".
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
+ .. [#] If neither Azimuth nor Orientation provided, modeled as four surfaces of equal area facing every direction.
+ .. [#] Siding choices are "wood siding", "vinyl siding", "stucco", "fiber cement siding", "brick veneer", "aluminum siding", or "none".
.. [#] Color choices are "light", "medium", "medium dark", "dark", or "reflective".
.. [#] If SolarAbsorptance not provided, defaults based on Color:
@@ -382,29 +387,32 @@ HPXML Walls
Each wall that has no contact with the ground and bounds a space type is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/Walls/Wall``.
- ====================================== ================ ============ ================= ============= =========== ====================================
- Element Type Units Constraints Required Default Notes
- ====================================== ================ ============ ================= ============= =========== ====================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
- ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
- ``WallType`` element 1 [#]_ Yes Wall type (for thermal mass)
- ``Area`` double ft2 > 0 Yes Gross area (including doors/windows)
- ``Azimuth`` integer deg 0 - 359 No See [#]_ Azimuth (clockwise from North)
- ``Siding`` string See [#]_ No wood siding Siding material
- ``SolarAbsorptance`` or ``Color`` double or string 0 - 1 or See [#]_ Yes See [#]_ Solar absorptance or color
- ``Emittance`` double 0 - 1 No 0.90 Emittance
- ``Insulation/SystemIdentifier`` id Yes Unique identifier
- ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
- ====================================== ================ ============ ================= ============= =========== ====================================
+ ====================================== ================= ================ ===================== ============= =========== ====================================
+ Element Type Units Constraints Required Default Notes
+ ====================================== ================= ================ ===================== ============= =========== ====================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
+ ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
+ ``WallType`` element 1 [#]_ Yes Wall type (for thermal mass)
+ ``Area`` double ft2 > 0 Yes Gross area (including doors/windows)
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ No See [#]_ Direction (clockwise from North)
+ ``Siding`` string See [#]_ No wood siding Siding material
+ ``Color`` or ``SolarAbsorptance`` string or double See [#]_ or 0 - 1 No medium Color or solar absorptance [#]_
+ ``Emittance`` double 0 - 1 No 0.90 Emittance
+ ``InteriorFinish/Type`` string See [#]_ No See [#]_ Interior finish material
+ ``InteriorFinish/Thickness`` double in >= 0 No 0.5 Interior finish thickness
+ ``Insulation/SystemIdentifier`` id Yes Unique identifier
+ ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
+ ====================================== ================= ================ ===================== ============= =========== ====================================
.. [#] ExteriorAdjacentTo choices are "outside", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "garage", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
See :ref:`hpxmllocations` for descriptions.
.. [#] InteriorAdjacentTo choices are "living space", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", or "garage".
See :ref:`hpxmllocations` for descriptions.
.. [#] WallType child element choices are ``WoodStud``, ``DoubleWoodStud``, ``ConcreteMasonryUnit``, ``StructurallyInsulatedPanel``, ``InsulatedConcreteForms``, ``SteelFrame``, ``SolidConcrete``, ``StructuralBrick``, ``StrawBale``, ``Stone``, ``LogWall``, or ``Adobe``.
- .. [#] If Azimuth not provided, modeled as four surfaces of equal area facing every direction.
- .. [#] Siding choices are "wood siding", "vinyl siding", "stucco", "fiber cement siding", "brick veneer", or "aluminum siding".
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
+ .. [#] If neither Azimuth nor Orientation provided, modeled as four surfaces of equal area facing every direction.
+ .. [#] Siding choices are "wood siding", "vinyl siding", "stucco", "fiber cement siding", "brick veneer", "aluminum siding", or "none".
.. [#] Color choices are "light", "medium", "medium dark", "dark", or "reflective".
.. [#] If SolarAbsorptance not provided, defaults based on Color:
@@ -414,6 +422,8 @@ Each wall that has no contact with the ground and bounds a space type is entered
- **light**: 0.50
- **reflective**: 0.30
+ .. [#] InteriorFinish/Type choices are "gypsum board", "gypsum composite board", "plaster", "wood", "other", or "none".
+ .. [#] InteriorFinish/Type defaults to "gypsum board" if InteriorAdjacentTo is living space or basement - conditioned, otherwise "none".
.. [#] AssemblyEffectiveRValue includes all material layers, interior/exterior air films, and insulation installation grade.
HPXML Foundation Walls
@@ -423,33 +433,38 @@ Each wall that is in contact with the ground should be specified as an ``/HPXML/
Other walls (e.g., wood framed walls) that are connected to a below-grade space but have no contact with the ground should be specified as a ``Wall`` and not a ``FoundationWall``.
- ============================================================== ======== ============ =========== ========= ======== ====================================
- Element Type Units Constraints Required Default Notes
- ============================================================== ======== ============ =========== ========= ======== ====================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type [#]_
- ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
- ``Height`` double ft > 0 Yes Total height
- ``Area`` double ft2 > 0 Yes Gross area (including doors/windows)
- ``Azimuth`` integer deg 0 - 359 No See [#]_ Azimuth (clockwise from North)
- ``Thickness`` double inches > 0 No 8.0 Thickness excluding interior framing
- ``DepthBelowGrade`` double ft 0 - Height Yes Depth below grade [#]_
- ``Insulation/SystemIdentifier`` id Yes Unique identifier
- ``Insulation/Layer[InstallationType="continuous - interior"]`` element 0 - 1 See [#]_ Interior insulation layer
- ``Insulation/Layer[InstallationType="continuous - exterior"]`` element 0 - 1 See [#]_ Exterior insulation layer
- ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 See [#]_ Assembly R-value [#]_
- ============================================================== ======== ============ =========== ========= ======== ====================================
+ ============================================================== ================= ================ =================== ========= ======== ====================================
+ Element Type Units Constraints Required Default Notes
+ ============================================================== ================= ================ =================== ========= ======== ====================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type [#]_
+ ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
+ ``Height`` double ft > 0 Yes Total height
+ ``Area`` or ``Length`` double ft2 or ft > 0 Yes Gross area (including doors/windows) or length
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ No See [#]_ Direction (clockwise from North)
+ ``Thickness`` double inches > 0 No 8.0 Thickness excluding interior framing
+ ``DepthBelowGrade`` double ft 0 - Height Yes Depth below grade [#]_
+ ``InteriorFinish/Type`` string See [#]_ No See [#]_ Interior finish material
+ ``InteriorFinish/Thickness`` double in >= 0 No 0.5 Interior finish thickness
+ ``Insulation/SystemIdentifier`` id Yes Unique identifier
+ ``Insulation/Layer[InstallationType="continuous - interior"]`` element 0 - 1 See [#]_ Interior insulation layer
+ ``Insulation/Layer[InstallationType="continuous - exterior"]`` element 0 - 1 See [#]_ Exterior insulation layer
+ ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 See [#]_ Assembly R-value [#]_
+ ============================================================== ================= ================ =================== ========= ======== ====================================
.. [#] ExteriorAdjacentTo choices are "ground", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "garage", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
See :ref:`hpxmllocations` for descriptions.
.. [#] InteriorAdjacentTo choices are "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", or "garage".
See :ref:`hpxmllocations` for descriptions.
.. [#] Interior foundation walls (e.g., between basement and crawlspace) should **not** use "ground" even if the foundation wall has some contact with the ground due to the difference in below-grade depths of the two adjacent spaces.
- .. [#] If Azimuth not provided, modeled as four surfaces of equal area facing every direction.
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
+ .. [#] If neither Azimuth nor Orientation provided, modeled as four surfaces of equal area facing every direction.
.. [#] For exterior foundation walls, depth below grade is relative to the ground plane.
For interior foundation walls, depth below grade is the vertical span of foundation wall in contact with the ground.
For example, an interior foundation wall between an 8 ft conditioned basement and a 3 ft crawlspace has a height of 8 ft and a depth below grade of 5 ft.
Alternatively, an interior foundation wall between an 8 ft conditioned basement and an 8 ft unconditioned basement has a height of 8 ft and a depth below grade of 0 ft.
+ .. [#] InteriorFinish/Type choices are "gypsum board", "gypsum composite board", "plaster", "wood", "other", or "none".
+ .. [#] InteriorFinish/Type defaults to "gypsum board" if InteriorAdjacentTo is basement - conditioned, otherwise "none".
.. [#] Layer[InstallationType="continuous - interior"] only required if AssemblyEffectiveRValue is not provided.
.. [#] Layer[InstallationType="continuous - exterior"] only required if AssemblyEffectiveRValue is not provided.
.. [#] AssemblyEffectiveRValue only required if Layer elements are not provided.
@@ -462,8 +477,8 @@ If insulation layers are provided, additional information is entered in each ``F
Element Type Units Constraints Required Default Notes
========================================== ======== ============ ================================== ======== ======= =====================================================================
``NominalRValue`` double F-ft2-hr/Btu >= 0 Yes R-value of the foundation wall insulation; use zero if no insulation
- ``extension/DistanceToTopOfInsulation`` double ft >= 0 Yes Vertical distance from top of foundation wall to top of insulation
- ``extension/DistanceToBottomOfInsulation`` double ft DistanceToTopOfInsulation - Height Yes Vertical distance from top of foundation wall to bottom of insulation
+ ``extension/DistanceToTopOfInsulation`` double ft >= 0 No 0 Vertical distance from top of foundation wall to top of insulation
+ ``extension/DistanceToBottomOfInsulation`` double ft DistanceToTopOfInsulation - Height No Height Vertical distance from top of foundation wall to bottom of insulation
========================================== ======== ============ ================================== ======== ======= =====================================================================
HPXML Frame Floors
@@ -471,21 +486,25 @@ HPXML Frame Floors
Each horizontal floor/ceiling surface that is not in contact with the ground (Slab) nor adjacent to ambient conditions above (Roof) is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/FrameFloors/FrameFloor``.
- ====================================== ======== ============ =========== ======== ======= ============================
- Element Type Units Constraints Required Default Notes
- ====================================== ======== ============ =========== ======== ======= ============================
- ``SystemIdentifier`` id Yes Unique identifier
- ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
- ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
- ``Area`` double ft2 > 0 Yes Gross area
- ``Insulation/SystemIdentifier`` id Yes Unique identifier
- ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
- ====================================== ======== ============ =========== ======== ======= ============================
+ ====================================== ======== ============ =========== ======== ======== ============================
+ Element Type Units Constraints Required Default Notes
+ ====================================== ======== ============ =========== ======== ======== ============================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``ExteriorAdjacentTo`` string See [#]_ Yes Exterior adjacent space type
+ ``InteriorAdjacentTo`` string See [#]_ Yes Interior adjacent space type
+ ``Area`` double ft2 > 0 Yes Gross area
+ ``InteriorFinish/Type`` string See [#]_ No See [#]_ Interior finish material
+ ``InteriorFinish/Thickness`` double in >= 0 No 0.5 Interior finish thickness
+ ``Insulation/SystemIdentifier`` id Yes Unique identifier
+ ``Insulation/AssemblyEffectiveRValue`` double F-ft2-hr/Btu > 0 Yes Assembly R-value [#]_
+ ====================================== ======== ============ =========== ======== ======== ============================
.. [#] ExteriorAdjacentTo choices are "outside", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "garage", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
See :ref:`hpxmllocations` for descriptions.
.. [#] InteriorAdjacentTo choices are "living space", "attic - vented", "attic - unvented", "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", or "garage".
See :ref:`hpxmllocations` for descriptions.
+ .. [#] InteriorFinish/Type choices are "gypsum board", "gypsum composite board", "plaster", "wood", "other", or "none".
+ .. [#] InteriorFinish/Type defaults to "gypsum board" if InteriorAdjacentTo is living space and the surface is a ceiling, otherwise "none".
.. [#] AssemblyEffectiveRValue includes all material layers, interior/exterior air films, and insulation installation grade.
For frame floors adjacent to "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space", additional information is entered in ``FrameFloor``.
@@ -543,23 +562,24 @@ HPXML Windows
Each window or glass door area is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/Windows/Window``.
- ============================================ ======== ============ =========== ======== ========= =============================================================
- Element Type Units Constraints Required Default Notes
- ============================================ ======== ============ =========== ======== ========= =============================================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``Area`` double ft2 > 0 Yes Total area
- ``Azimuth`` integer deg 0 - 359 Yes Azimuth (clockwise from North)
- ``UFactor`` double Btu/F-ft2-hr > 0 Yes Full-assembly NFRC U-factor
- ``SHGC`` double 0 - 1 Yes Full-assembly NFRC solar heat gain coefficient
- ``ExteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior summer shading coefficient (1=transparent, 0=opaque)
- ``ExteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior winter shading coefficient (1=transparent, 0=opaque)
- ``InteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 0.70 [#]_ Interior summer shading coefficient (1=transparent, 0=opaque)
- ``InteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 0.85 [#]_ Interior winter shading coefficient (1=transparent, 0=opaque)
- ``Overhangs`` element 0 - 1 No Presence of overhangs (including roof eaves)
- ``FractionOperable`` double frac 0 - 1 No 0.67 Operable fraction [#]_
- ``AttachedToWall`` idref See [#]_ Yes ID of attached wall
- ============================================ ======== ============ =========== ======== ========= =============================================================
-
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+ Element Type Units Constraints Required Default Notes
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``Area`` double ft2 > 0 Yes Total area
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ Yes Direction (clockwise from North)
+ ``UFactor`` double Btu/F-ft2-hr > 0 Yes Full-assembly NFRC U-factor
+ ``SHGC`` double 0 - 1 Yes Full-assembly NFRC solar heat gain coefficient
+ ``ExteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior summer shading coefficient (1=transparent, 0=opaque)
+ ``ExteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior winter shading coefficient (1=transparent, 0=opaque)
+ ``InteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 0.70 [#]_ Interior summer shading coefficient (1=transparent, 0=opaque)
+ ``InteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 0.85 [#]_ Interior winter shading coefficient (1=transparent, 0=opaque)
+ ``Overhangs`` element 0 - 1 No Presence of overhangs (including roof eaves)
+ ``FractionOperable`` double frac 0 - 1 No 0.67 Operable fraction [#]_
+ ``AttachedToWall`` idref See [#]_ Yes ID of attached wall
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
.. [#] InteriorShading/SummerShadingCoefficient default value indicates 30% reduction in solar heat gain, based on `ANSI/RESNET/ICC 301-2019 `_.
.. [#] InteriorShading/WinterShadingCoefficient default value indicates 15% reduction in solar heat gain, based on `ANSI/RESNET/ICC 301-2019 `_.
.. [#] FractionOperable reflects whether the windows are operable (can be opened), not how they are used by the occupants.
@@ -585,21 +605,22 @@ HPXML Skylights
Each skylight is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/Skylights/Skylight``.
- ============================================ ======== ============ =========== ======== ========== =============================================================
- Element Type Units Constraints Required Default Notes
- ============================================ ======== ============ =========== ======== ========== =============================================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``Area`` double ft2 > 0 Yes Total area
- ``Azimuth`` integer deg 0 - 359 Yes Azimuth (clockwise from North)
- ``UFactor`` double Btu/F-ft2-hr > 0 Yes Full-assembly NFRC U-factor
- ``SHGC`` double 0 - 1 Yes Full-assembly NFRC solar heat gain coefficient
- ``ExteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior summer shading coefficient (1=transparent, 0=opaque)
- ``ExteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior winter shading coefficient (1=transparent, 0=opaque)
- ``InteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Interior summer shading coefficient (1=transparent, 0=opaque)
- ``InteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Interior winter shading coefficient (1=transparent, 0=opaque)
- ``AttachedToRoof`` idref See [#]_ Yes ID of attached roof
- ============================================ ======== ============ =========== ======== ========== =============================================================
-
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+ Element Type Units Constraints Required Default Notes
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``Area`` double ft2 > 0 Yes Total area
+ ``Azimuth`` or ``Orientation`` integer or string deg or direction 0 - 359 or See [#]_ Yes Direction (clockwise from North)
+ ``UFactor`` double Btu/F-ft2-hr > 0 Yes Full-assembly NFRC U-factor
+ ``SHGC`` double 0 - 1 Yes Full-assembly NFRC solar heat gain coefficient
+ ``ExteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior summer shading coefficient (1=transparent, 0=opaque)
+ ``ExteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Exterior winter shading coefficient (1=transparent, 0=opaque)
+ ``InteriorShading/SummerShadingCoefficient`` double frac 0 - 1 No 1.00 Interior summer shading coefficient (1=transparent, 0=opaque)
+ ``InteriorShading/WinterShadingCoefficient`` double frac 0 - 1 No 1.00 Interior winter shading coefficient (1=transparent, 0=opaque)
+ ``AttachedToRoof`` idref See [#]_ Yes ID of attached roof
+ ============================================ ================= ================ =================== ======== ========= =============================================================
+
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
.. [#] AttachedToRoof must reference a ``Roof``.
HPXML Doors
@@ -607,17 +628,19 @@ HPXML Doors
Each opaque door is entered as an ``/HPXML/Building/BuildingDetails/Enclosure/Doors/Door``.
- ============================================ ======== ============ =========== ======== ========= ==============================
- Element Type Units Constraints Required Default Notes
- ============================================ ======== ============ =========== ======== ========= ==============================
- ``SystemIdentifier`` id Yes Unique identifier
- ``AttachedToWall`` idref See [#]_ Yes ID of attached wall
- ``Area`` double ft2 > 0 Yes Total area
- ``Azimuth`` integer deg 0 - 359 Yes Azimuth (clockwise from North)
- ``RValue`` double F-ft2-hr/Btu > 0 Yes R-value
- ============================================ ======== ============ =========== ======== ========= ==============================
+ ============================================ ================= ============ =================== ======== ========= ==============================
+ Element Type Units Constraints Required Default Notes
+ ============================================ ================= ============ =================== ======== ========= ==============================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``AttachedToWall`` idref See [#]_ Yes ID of attached wall
+ ``Area`` double ft2 > 0 Yes Total area
+ ``Azimuth`` or ``Orientation`` integer or string deg 0 - 359 or See [#]_ No See [#]_ Direction (clockwise from North)
+ ``RValue`` double F-ft2-hr/Btu > 0 Yes R-value
+ ============================================ ================= ============ =================== ======== ========= ==============================
.. [#] AttachedToWall must reference a ``Wall`` or ``FoundationWall``.
+ .. [#] Orientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
+ .. [#] If neither Azimuth nor Orientation nor AttachedToWall azimuth provided, defaults to the azimuth with the largest surface area defined in the HPXML file.
HPXML Systems
-------------
@@ -637,7 +660,7 @@ Each heating system (other than a heat pump) is entered as an ``/HPXML/Building/
``SystemIdentifier`` id Yes Unique identifier
``HeatingSystemType`` element 1 [#]_ Yes Type of heating system
``HeatingSystemFuel`` string See [#]_ Yes Fuel type
- ``HeatingCapacity`` double Btu/hr >= 0 No autosized Input heating capacity
+ ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating output capacity
``FractionHeatLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of heating load served
================================= ======== ====== =========== ======== ========= ===============================
@@ -654,7 +677,7 @@ If electric resistance heating is specified, additional information is entered i
================================================== ====== ===== =========== ======== ======= ==========
Element Type Units Constraints Required Default Notes
================================================== ====== ===== =========== ======== ======= ==========
- ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 Yes Efficiency
+ ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 No 1.0 Efficiency
================================================== ====== ===== =========== ======== ======= ==========
Furnace
@@ -662,16 +685,17 @@ Furnace
If a furnace is specified, additional information is entered in ``HeatingSystem``.
- =============================================== ====== ===== =========== ======== ========= ================================================
- Element Type Units Constraints Required Default Notes
- =============================================== ====== ===== =========== ======== ========= ================================================
- ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` double frac 0 - 1 Yes Rated efficiency
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan power [#]_
- ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- =============================================== ====== ===== =========== ======== ========= ================================================
+ ==================================================================== ================= ========= =============== ======== ======== ================================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================================== ================= ========= =============== ======== ======== ================================================
+ ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
+ ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` or ``YearInstalled`` double or integer frac or # 0 - 1 or > 1600 Yes See [#]_ Rated efficiency or Year installed
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate [#]_
+ ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
+ ==================================================================== ================= ========= =============== ======== ======== ================================================
.. [#] HVACDistribution type must be AirDistribution (type: "regular velocity" or "gravity") or DSE.
+ .. [#] If AnnualHeatingEfficiency[Units="AFUE"]/Value not provided, defaults to 0.98 if FuelType is "electricity", else AFUE from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
.. [#] If FanPowerWattsPerCFM not provided, defaulted to 0 W/cfm if gravity distribution system, else 0.5 W/cfm if AFUE <= 0.9, else 0.375 W/cfm.
.. [#] If there is a cooling system attached to the DistributionSystem, the heating and cooling systems cannot have different values for FanPowerWattsPerCFM.
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
@@ -682,12 +706,14 @@ Wall/Floor Furnace
If a wall furnace or floor furnace is specified, additional information is entered in ``HeatingSystem``.
- =============================================== ====== ===== =========== ======== ======= ===================
- Element Type Units Constraints Required Default Notes
- =============================================== ====== ===== =========== ======== ======= ===================
- ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` double frac 0 - 1 Yes Rated efficiency
- ``extension/FanPowerWatts`` double W >= 0 No 0 Fan power
- =============================================== ====== ===== =========== ======== ======= ===================
+ ==================================================================== ================= ========= =============== ======== ======== ==================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================================== ================= ========= =============== ======== ======== ==================================
+ ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` or ``YearInstalled`` double or integer frac or # 0 - 1 or > 1600 Yes See [#]_ Rated efficiency or Year installed
+ ``extension/FanPowerWatts`` double W >= 0 No 0 Fan power
+ ==================================================================== ================= ========= =============== ======== ======== ==================================
+
+ .. [#] If AnnualHeatingEfficiency[Units="AFUE"]/Value not provided, defaults to 0.98 if FuelType is "electricity", else AFUE from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
.. _hvac_heating_boiler:
@@ -696,17 +722,19 @@ Boiler
If a boiler is specified, additional information is entered in ``HeatingSystem``.
- ========================================================================== ======== ====== =========== ======== ======== =========================================
- Element Type Units Constraints Required Default Notes
- ========================================================================== ======== ====== =========== ======== ======== =========================================
- ``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units
- ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` double frac 0 - 1 Yes Rated efficiency
- ========================================================================== ======== ====== =========== ======== ======== =========================================
+ ==================================================================== ================= ========= =============== ======== ======== =========================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================================== ================= ========= =============== ======== ======== =========================================
+ ``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units
+ ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
+ ``AnnualHeatingEfficiency[Units="AFUE"]/Value`` or ``YearInstalled`` double or integer frac or # 0 - 1 or > 1600 Yes See [#]_ Rated efficiency or Year installed
+ ==================================================================== ================= ========= =============== ======== ======== =========================================
.. [#] For in-unit boilers, HVACDistribution type must be HydronicDistribution (type: "radiator", "baseboard", "radiant floor", "radiant ceiling", or "water loop") or DSE.
For shared boilers, HVACDistribution type must be HydronicDistribution (type: "radiator", "baseboard", "radiant floor", "radiant ceiling", or "water loop") or AirDistribution (type: "fan coil").
If the shared boiler has "water loop" distribution, a :ref:`hvac_heatpump_wlhp` must also be specified.
+ .. [#] If AnnualHeatingEfficiency[Units="AFUE"]/Value not provided, defaults to 0.98 if FuelType is "electricity", else AFUE from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
+
If an in-unit boiler if specified, additional information is entered in ``HeatingSystem``.
@@ -747,10 +775,12 @@ If a stove is specified, additional information is entered in ``HeatingSystem``.
================================================== ====== ===== =========== ======== ========= ===================
Element Type Units Constraints Required Default Notes
================================================== ====== ===== =========== ======== ========= ===================
- ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 Yes Efficiency
+ ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 No See [#]_ Efficiency
``extension/FanPowerWatts`` double W >= 0 No 40 Fan power
================================================== ====== ===== =========== ======== ========= ===================
+ .. [#] Defaulted to 1.0 if FuelType is "electricity", 0.60 if FuelType is "wood", 0.78 if FuelType is "wood pellets", otherwise 0.81.
+
Portable/Fixed Heater
~~~~~~~~~~~~~~~~~~~~~
@@ -759,10 +789,12 @@ If a portable heater or fixed heater is specified, additional information is ent
================================================== ====== ===== =========== ======== ========= ===================
Element Type Units Constraints Required Default Notes
================================================== ====== ===== =========== ======== ========= ===================
- ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 Yes Efficiency
+ ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 No See [#]_ Efficiency
``extension/FanPowerWatts`` double W >= 0 No 0 Fan power
================================================== ====== ===== =========== ======== ========= ===================
+ .. [#] Defaulted to 1.0 if FuelType is "electricity", 0.60 if FuelType is "wood", 0.78 if FuelType is "wood pellets", otherwise 0.81.
+
Fireplace
~~~~~~~~~
@@ -771,10 +803,12 @@ If a fireplace is specified, additional information is entered in ``HeatingSyste
================================================== ====== ===== =========== ======== ========= ===================
Element Type Units Constraints Required Default Notes
================================================== ====== ===== =========== ======== ========= ===================
- ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 Yes Efficiency
+ ``AnnualHeatingEfficiency[Units="Percent"]/Value`` double frac 0 - 1 No See [#]_ Efficiency
``extension/FanPowerWatts`` double W >= 0 No 0 Fan power
================================================== ====== ===== =========== ======== ========= ===================
+ .. [#] Defaulted to 1.0 if FuelType is "electricity", 0.60 if FuelType is "wood", 0.78 if FuelType is "wood pellets", otherwise 0.81.
+
.. _hvac_cooling:
HPXML Cooling Systems
@@ -800,20 +834,21 @@ Central Air Conditioner
If a central air conditioner is specified, additional information is entered in ``CoolingSystem``.
- =============================================== ======== ====== =========== ======== ========= ================================================
- Element Type Units Constraints Required Default Notes
- =============================================== ======== ====== =========== ======== ========= ================================================
- ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``AnnualCoolingEfficiency[Units="SEER"]/Value`` double Btu/Wh > 0 Yes Rated efficiency
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
- ``SensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
- ``CompressorType`` string See [#]_ No See [#]_ Type of compressor
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan power [#]_
- ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- ``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
- =============================================== ======== ====== =========== ======== ========= ================================================
+ ==================================================================== ================= =========== =============== ======== ========= ================================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================================== ================= =========== =============== ======== ========= ================================================
+ ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
+ ``AnnualCoolingEfficiency[Units="SEER"]/Value`` or ``YearInstalled`` double or integer Btu/Wh or # > 0 or > 1600 Yes See [#]_ Rated efficiency or Year installed
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
+ ``SensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
+ ``CompressorType`` string See [#]_ No See [#]_ Type of compressor
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate [#]_
+ ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
+ ``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
+ ==================================================================== ================= =========== =============== ======== ========= ================================================
.. [#] HVACDistribution type must be AirDistribution (type: "regular velocity") or DSE.
+ .. [#] If AnnualCoolingEfficiency[Units="SEER"]/Value not provided, defaults to SEER from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
.. [#] CompressorType choices are "single stage", "two stage", or "variable speed".
.. [#] If CompressorType not provided, defaults to "single stage" if SEER <= 15, else "two stage" if SEER <= 21, else "variable speed".
.. [#] If FanPowerWattsPerCFM not provided, defaults to using attached furnace W/cfm if available, else 0.5 W/cfm if SEER <= 13.5, else 0.375 W/cfm.
@@ -821,6 +856,7 @@ If a central air conditioner is specified, additional information is entered in
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
.. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are pre-charged on site.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
Room Air Conditioner
@@ -828,13 +864,15 @@ Room Air Conditioner
If a room air conditioner is specified, additional information is entered in ``CoolingSystem``.
- ============================================== ======== ====== =========== ======== ========= ======================
- Element Type Units Constraints Required Default Notes
- ============================================== ======== ====== =========== ======== ========= ======================
- ``AnnualCoolingEfficiency[Units="EER"]/Value`` double Btu/Wh > 0 Yes Rated efficiency
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
- ``SensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
- ============================================== ======== ====== =========== ======== ========= ======================
+ =================================================================================== ================= =========== =============== ======== ========= ==================================
+ Element Type Units Constraints Required Default Notes
+ =================================================================================== ================= =========== =============== ======== ========= ==================================
+ ``AnnualCoolingEfficiency[Units="EER" or Units="CEER"]/Value`` or ``YearInstalled`` double or integer Btu/Wh or # > 0 or > 1600 Yes See [#]_ Rated efficiency or Year installed
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
+ ``SensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
+ =================================================================================== ================= =========== =============== ======== ========= ==================================
+
+ .. [#] If AnnualCoolingEfficiency[Units="EER" or Units="CEER"]/Value not provided, defaults to EER from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
Evaporative Cooler
~~~~~~~~~~~~~~~~~~
@@ -845,7 +883,7 @@ If an evaporative cooler is specified, additional information is entered in ``Co
Element Type Units Constraints Required Default Notes
================================= ======== ====== =========== ======== ========= ==================================
``DistributionSystem`` idref See [#]_ No ID of attached distribution system
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
================================= ======== ====== =========== ======== ========= ==================================
.. [#] If provided, HVACDistribution type must be AirDistribution (type: "regular velocity") or DSE.
@@ -860,25 +898,20 @@ If a mini-split is specified, additional information is entered in ``CoolingSyst
=============================================== ======== ====== =========== ======== ========= ===============================================
``DistributionSystem`` idref See [#]_ No ID of attached distribution system
``AnnualCoolingEfficiency[Units="SEER"]/Value`` double Btu/Wh > 0 Yes Rated cooling efficiency
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
``SensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate
+ ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
=============================================== ======== ====== =========== ======== ========= ===============================================
.. [#] If provided, HVACDistribution type must be AirDistribution (type: "regular velocity") or DSE.
- .. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
- See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
-
-If a ducted mini-split is specified (i.e., a ``DistributionSystem`` has been entered), additional information is entered in ``CoolingSystem``.
-
- ================================= ======== ====== =========== ======== ========= ===============================================
- Element Type Units Constraints Required Default Notes
- ================================= ======== ====== =========== ======== ========= ===============================================
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No 0.18 Fan power
- ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- ================================= ======== ====== =========== ======== ========= ===============================================
-
+ .. [#] FanPowerWattsPerCFM defaults to 0.07 W/cfm for ductless systems and 0.18 W/cfm for ducted systems.
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
+ A non-zero airflow defect should typically only be applied for systems attached to ducts.
+ See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
+ .. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are pre-charged on site.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
.. _hvac_cooling_chiller:
@@ -894,7 +927,7 @@ If a chiller is specified, additional information is entered in ``CoolingSystem`
``IsSharedSystem`` boolean true Yes Whether it serves multiple dwelling units
``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
``NumberofUnitsServed`` integer > 1 Yes Number of dwelling units served
- ``CoolingCapacity`` double Btu/hr >= 0 Yes Total cooling capacity
+ ``CoolingCapacity`` double Btu/hr >= 0 Yes Total cooling output capacity
``AnnualCoolingEfficiency[Units="kW/ton"]/Value`` double kW/ton > 0 Yes Rated efficiency
``extension/SharedLoopWatts`` double W >= 0 Yes Pumping and fan power serving the system
``extension/FanCoilWatts`` double W >= 0 See [#]_ Fan coil power
@@ -957,7 +990,7 @@ If a backup system fuel is provided, additional information is entered in ``Heat
Element Type Units Constraints Required Default Notes
======================================================================== ======== ====== =========== ======== ========= ==========================================
``BackupAnnualHeatingEfficiency[Units="Percent" or Units="AFUE"]/Value`` double frac 0 - 1 Yes Backup heating efficiency
- ``BackupHeatingCapacity`` double Btu/hr >= 0 No autosized Backup heating capacity
+ ``BackupHeatingCapacity`` double Btu/hr >= 0 No autosized Backup heating output capacity
``BackupHeatingSwitchoverTemperature`` double F No Backup heating switchover temperature [#]_
======================================================================== ======== ====== =========== ======== ========= ==========================================
@@ -969,33 +1002,36 @@ Air-to-Air Heat Pump
If an air-to-air heat pump is specified, additional information is entered in ``HeatPump``.
- =============================================== ======== ====== =========== ======== ========= ================================================
- Element Type Units Constraints Required Default Notes
- =============================================== ======== ====== =========== ======== ========= ================================================
- ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``CompressorType`` string See [#]_ No See [#]_ Type of compressor
- ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating capacity (excluding any backup heating)
- ``HeatingCapacity17F`` double Btu/hr >= 0 No Heating capacity at 17F, if available
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
- ``CoolingSensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
- ``FractionHeatLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of heating load served
- ``FractionCoolLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of cooling load served
- ``AnnualCoolingEfficiency[Units="SEER"]/Value`` double Btu/Wh > 0 Yes Rated cooling efficiency
- ``AnnualHeatingEfficiency[Units="HSPF"]/Value`` double Btu/Wh > 0 Yes Rated heating efficiency
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan power
- ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- ``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
- =============================================== ======== ====== =========== ======== ========= ================================================
+ ==================================================================== ================= =========== =============== ======== ========= =================================================
+ Element Type Units Constraints Required Default Notes
+ ==================================================================== ================= =========== =============== ======== ========= =================================================
+ ``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
+ ``CompressorType`` string See [#]_ No See [#]_ Type of compressor
+ ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating output capacity (excluding any backup heating)
+ ``HeatingCapacity17F`` double Btu/hr >= 0 No Heating output capacity at 17F, if available
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
+ ``CoolingSensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
+ ``FractionHeatLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of heating load served
+ ``FractionCoolLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of cooling load served
+ ``AnnualCoolingEfficiency[Units="SEER"]/Value`` or ``YearInstalled`` double or integer Btu/Wh or # > 0 or > 1600 Yes See [#]_ Rated cooling efficiency or Year installed
+ ``AnnualHeatingEfficiency[Units="HSPF"]/Value`` or ``YearInstalled`` double or integer Btu/Wh or # > 0 or > 1600 Yes See [#]_ Rated heating efficiency or Year installed
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate
+ ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
+ ``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
+ ==================================================================== ================= =========== =============== ======== ========= =================================================
.. [#] HVACDistribution type must be AirDistribution (type: "regular velocity") or DSE.
.. [#] CompressorType choices are "single stage", "two stage", or "variable speed".
.. [#] If CompressorType not provided, defaults to "single stage" if SEER <= 15, else "two stage" if SEER <= 21, else "variable speed".
.. [#] The sum of all ``FractionHeatLoadServed`` (across both HeatingSystems and HeatPumps) must be less than or equal to 1.
.. [#] The sum of all ``FractionCoolLoadServed`` (across both CoolingSystems and HeatPumps) must be less than or equal to 1.
+ .. [#] If AnnualCoolingEfficiency[Units="SEER"]/Value not provided, defaults to SEER from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
+ .. [#] If AnnualHeatingEfficiency[Units="HSPF"]/Value not provided, defaults to HSPF from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_hvac_equipment_efficiency.csv`` based on YearInstalled.
.. [#] If FanPowerWattsPerCFM not provided, defaulted to 0.5 W/cfm if HSPF <= 8.75, else 0.375 W/cfm.
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
.. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are pre-charged on site.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
Mini-Split Heat Pump
@@ -1007,33 +1043,28 @@ If a mini-split heat pump is specified, additional information is entered in ``H
Element Type Units Constraints Required Default Notes
=============================================== ======== ====== =========== ======== ========= ==============================================
``DistributionSystem`` idref See [#]_ No ID of attached distribution system, if present
- ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating capacity (excluding any backup heating)
- ``HeatingCapacity17F`` double Btu/hr >= 0 No Heating capacity at 17F, if available
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
+ ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating output capacity (excluding any backup heating)
+ ``HeatingCapacity17F`` double Btu/hr >= 0 No Heating output capacity at 17F, if available
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
``CoolingSensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
``FractionHeatLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of heating load served
``FractionCoolLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of cooling load served
``AnnualCoolingEfficiency[Units="SEER"]/Value`` double Btu/Wh > 0 Yes Rated cooling efficiency
``AnnualHeatingEfficiency[Units="HSPF"]/Value`` double Btu/Wh > 0 Yes Rated heating efficiency
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate
+ ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
=============================================== ======== ====== =========== ======== ========= ==============================================
.. [#] If provided, HVACDistribution type must be AirDistribution (type: "regular velocity") or DSE.
.. [#] The sum of all ``FractionHeatLoadServed`` (across both HeatingSystems and HeatPumps) must be less than or equal to 1.
.. [#] The sum of all ``FractionCoolLoadServed`` (across both CoolingSystems and HeatPumps) must be less than or equal to 1.
- .. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
- See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
-
-If a ducted mini-split is specified (i.e., a ``DistributionSystem`` has been entered), additional information is entered in ``HeatPump``.
-
- ================================= ======== ====== =========== ======== ========= ===============================================
- Element Type Units Constraints Required Default Notes
- ================================= ======== ====== =========== ======== ========= ===============================================
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No 0.18 Fan power
- ``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- ================================= ======== ====== =========== ======== ========= ===============================================
-
+ .. [#] FanPowerWattsPerCFM defaults to 0.07 W/cfm for ductless systems and 0.18 W/cfm for ducted systems.
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
+ A non-zero airflow defect should typically only be applied for systems attached to ducts.
+ See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
+ .. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are pre-charged on site.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
Ground-to-Air Heat Pump
@@ -1046,8 +1077,8 @@ If a ground-to-air heat pump is specified, additional information is entered in
=============================================== ======== ====== =========== ======== ========= ==============================================
``IsSharedSystem`` boolean No false Whether it has a shared hydronic circulation loop [#]_
``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating capacity (excluding any backup heating)
- ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling capacity
+ ``HeatingCapacity`` double Btu/hr >= 0 No autosized Heating output capacity (excluding any backup heating)
+ ``CoolingCapacity`` double Btu/hr >= 0 No autosized Cooling output capacity
``CoolingSensibleHeatFraction`` double frac 0 - 1 No Sensible heat fraction
``FractionHeatLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of heating load served
``FractionCoolLoadServed`` double frac 0 - 1 [#]_ Yes Fraction of cooling load served
@@ -1056,9 +1087,9 @@ If a ground-to-air heat pump is specified, additional information is entered in
``NumberofUnitsServed`` integer > 0 See [#]_ Number of dwelling units served
``extension/PumpPowerWattsPerTon`` double W/ton >= 0 No See [#]_ Pump power [#]_
``extension/SharedLoopWatts`` double W >= 0 See [#]_ Shared pump power [#]_
- ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan power
+ ``extension/FanPowerWattsPerCFM`` double W/cfm >= 0 No See [#]_ Fan efficiency at maximum airflow rate
``extension/AirflowDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed airflows [#]_
- ``extension/ChargeDefectRatio`` double frac 0.0 [#]_ No 0.0 Deviation between design/installed charges [#]_
+ ``extension/ChargeDefectRatio`` double frac > -1 No 0.0 Deviation between design/installed charges [#]_
=============================================== ======== ====== =========== ======== ========= ==============================================
.. [#] IsSharedSystem should be true if the SFA/MF building has multiple ground source heat pumps connected to a shared hydronic circulation loop.
@@ -1074,8 +1105,8 @@ If a ground-to-air heat pump is specified, additional information is entered in
.. [#] If FanPowerWattsPerCFM not provided, defaulted to 0.5 W/cfm if COP <= 8.75/3.2, else 0.375 W/cfm.
.. [#] AirflowDefectRatio is defined as (InstalledAirflow - DesignAirflow) / DesignAirflow; a value of zero means no airflow defect.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
- .. [#] ChargeDefectRatio currently constrained to zero for ground-to-air heat pumps due to an EnergyPlus limitation; this constraint will be relaxed in the future.
.. [#] ChargeDefectRatio is defined as (InstalledCharge - DesignCharge) / DesignCharge; a value of zero means no refrigerant charge defect.
+ A non-zero charge defect should typically only be applied for systems that are pre-charged on site.
See ANSI/RESNET/ACCA 310-2020 Standard for Grading the Installation of HVAC Systems for more information.
.. _hvac_heatpump_wlhp:
@@ -1089,8 +1120,8 @@ If a water-loop-to-air heat pump is specified, additional information is entered
Element Type Units Constraints Required Default Notes
=============================================== ======== ====== =========== ======== ========= ==============================================
``DistributionSystem`` idref See [#]_ Yes ID of attached distribution system
- ``HeatingCapacity`` double Btu/hr > 0 No autosized Heating capacity
- ``CoolingCapacity`` double Btu/hr > 0 See [#]_ Cooling capacity
+ ``HeatingCapacity`` double Btu/hr > 0 No autosized Heating output capacity
+ ``CoolingCapacity`` double Btu/hr > 0 See [#]_ Cooling output capacity
``AnnualCoolingEfficiency[Units="EER"]/Value`` double Btu/Wh > 0 See [#]_ Rated cooling efficiency
``AnnualHeatingEfficiency[Units="COP"]/Value`` double W/W > 0 See [#]_ Rated heating efficiency
=============================================== ======== ====== =========== ======== ========= ==============================================
@@ -1163,7 +1194,7 @@ If a heating and/or cooling season is defined, additional information is entered
====================================== ======== ===== ================= ======== ============================= ===========
Element Type Units Constraints Required Default Description
====================================== ======== ===== ================= ======== ============================= ===========
- ``BeginMonth` integer 1 - 12 Yes Begin month
+ ``BeginMonth`` integer 1 - 12 Yes Begin month
``BeginDayOfMonth`` integer 1 - 31 Yes Begin day
``EndMonth`` integer 1 - 12 Yes End month
``EndDayOfMonth`` integer 1 - 31 Yes End day
@@ -1247,17 +1278,23 @@ Additional information is entered in each ``DuctLeakageMeasurement``.
Additional information is entered in each ``Ducts``.
- ======================== ======= ============ =========== ======== ========= ===============================
- Element Type Units Constraints Required Default Notes
- ======================== ======= ============ =========== ======== ========= ===============================
- ``DuctInsulationRValue`` double F-ft2-hr/Btu >= 0 Yes R-value of duct insulation [#]_
- ``DuctSurfaceArea`` double ft2 >= 0 See [#]_ See [#]_ Duct surface area
- ``DuctLocation`` string See [#]_ See [#]_ See [#]_ Duct location
- ======================== ======= ============ =========== ======== ========= ===============================
+ =============================================== ======= ============ ================ ======== ========= ======================================
+ Element Type Units Constraints Required Default Notes
+ =============================================== ======= ============ ================ ======== ========= ======================================
+ ``DuctInsulationRValue`` double F-ft2-hr/Btu >= 0 Yes R-value of duct insulation [#]_
+ ``DuctLocation`` string See [#]_ No See [#]_ Duct location
+ ``FractionDuctArea`` and/or ``DuctSurfaceArea`` double frac or ft2 0-1 [#]_ or >= 0 See [#]_ See [#]_ Duct fraction/surface area in location
+ =============================================== ======= ============ ================ ======== ========= ======================================
.. [#] DuctInsulationRValue should not include air films (i.e., use 0 for an uninsulated duct).
- .. [#] DuctSurfaceArea and DuctLocation are either both required or both disallowed.
- .. [#] If DuctSurfaceArea not provided, duct areas will be calculated based on `ASHRAE Standard 152 `_:
+ .. [#] DuctLocation choices are "living space", "basement - conditioned", "basement - unconditioned", "crawlspace - unvented", "crawlspace - vented", "attic - unvented", "attic - vented", "garage", "outside", "exterior wall", "under slab", "roof deck", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
+ See :ref:`hpxmllocations` for descriptions.
+ .. [#] If DuctLocation not provided, defaults to the first present space type: "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "attic - vented", "attic - unvented", "garage", or "living space".
+ If NumberofConditionedFloorsAboveGrade > 1, secondary ducts will be located in "living space".
+ .. [#] The sum of all ``[DuctType="supply"]/FractionDuctArea`` and ``[DuctType="return"]/FractionDuctArea`` must each equal to 1.
+ .. [#] Either FractionDuctArea or DuctSurfaceArea (or both) are required if DuctLocation is provided.
+ .. [#] If DuctSurfaceArea not provided, duct surface areas will be calculated based on FractionDuctArea if provided.
+ If FractionDuctArea also not provided, duct surface areas will be calculated based on `ASHRAE Standard 152 `_:
- **Primary supply ducts**: 0.27 * F_out * ConditionedFloorAreaServed
- **Secondary supply ducts**: 0.27 * (1 - F_out) * ConditionedFloorAreaServed
@@ -1265,11 +1302,6 @@ Additional information is entered in each ``Ducts``.
- **Secondary return ducts**: b_r * (1 - F_out) * ConditionedFloorAreaServed
where F_out is 1.0 when NumberofConditionedFloorsAboveGrade <= 1 and 0.75 when NumberofConditionedFloorsAboveGrade > 1, and b_r is 0.05 * NumberofReturnRegisters with a maximum value of 0.25.
- .. [#] DuctLocation choices are "living space", "basement - conditioned", "basement - unconditioned", "crawlspace - unvented", "crawlspace - vented", "attic - unvented", "attic - vented", "garage", "outside", "exterior wall", "under slab", "roof deck", "other housing unit", "other heated space", "other multifamily buffer space", or "other non-freezing space".
- See :ref:`hpxmllocations` for descriptions.
- .. [#] DuctLocation and DuctSurfaceArea are either both required or both disallowed.
- .. [#] If DuctLocation not provided, defaults to the first present space type: "basement - conditioned", "basement - unconditioned", "crawlspace - vented", "crawlspace - unvented", "attic - vented", "attic - unvented", "garage", or "living space".
- Any secondary ducts (i.e., when NumberofConditionedFloorsAboveGrade > 1) will always be located in "living space".
Hydronic Distribution
~~~~~~~~~~~~~~~~~~~~~
@@ -1318,13 +1350,19 @@ If not entered, the simulation will not include mechanical ventilation.
``FanType`` string See [#]_ Yes Type of ventilation system
``TestedFlowRate`` or ``RatedFlowRate`` double cfm >= 0 Yes Flow rate [#]_
``HoursInOperation`` double hrs/day 0 - 24 No See [#]_ Hours per day of operation
- ``FanPower`` double W >= 0 Yes Fan power
+ ``FanPower`` double W >= 0 No See [#]_ Fan power
======================================= ======== ======= =========== ======== ========= =========================================
.. [#] For central fan integrated supply systems, IsSharedSystem must be false.
.. [#] FanType choices are "energy recovery ventilator", "heat recovery ventilator", "exhaust only", "supply only", "balanced", or "central fan integrated supply".
.. [#] For a central fan integrated supply system, the flow rate should equal the amount of outdoor air provided to the distribution system.
.. [#] If HoursInOperation not provided, defaults to 24 (i.e., running continuously) for all system types other than central fan integrated supply (CFIS), and 8.0 (i.e., running intermittently) for CFIS systems.
+ .. [#] If FanPower not provided, defaults based on `ANSI/RESNET/ICC 301-2019 `_:
+
+ - "energy recovery ventilator", "heat recovery ventilator", or shared system: 1.0 W/cfm
+ - "balanced": 0.7 W/cfm
+ - "central fan integrated supply": 0.5 W/cfm
+ - "exhaust only" or "supply only": 0.35 W/cfm
Exhaust/Supply Only
~~~~~~~~~~~~~~~~~~~
@@ -1498,22 +1536,26 @@ Conventional Storage
If a conventional storage water heater is specified, additional information is entered in ``WaterHeatingSystem``.
- ============================================= ======= ============ =========== ======== ======== ==========================================
- Element Type Units Constraints Required Default Notes
- ============================================= ======= ============ =========== ======== ======== ==========================================
- ``FuelType`` string See [#]_ Yes Fuel type
- ``TankVolume`` double gal > 0 No See [#]_ Tank volume
- ``HeatingCapacity`` double Btuh > 0 No See [#]_ Heating capacity
- ``UniformEnergyFactor`` or ``EnergyFactor`` double frac < 1 Yes EnergyGuide label rated efficiency
- ``FirstHourRating`` double gal/hr > 0 See [#]_ EnergyGuide label first hour rating
- ``RecoveryEfficiency`` double frac 0 - 1 No See [#]_ Recovery efficiency
- ``WaterHeaterInsulation/Jacket/JacketRValue`` double F-ft2-hr/Btu >= 0 No 0 R-value of additional tank insulation wrap
- ============================================= ======= ============ =========== ======== ======== ==========================================
+ ================================================================ ================= ============= =============== ======== ======== ====================================================
+ Element Type Units Constraints Required Default Notes
+ ================================================================ ================= ============= =============== ======== ======== ====================================================
+ ``FuelType`` string See [#]_ Yes Fuel type
+ ``TankVolume`` double gal > 0 No See [#]_ Tank volume
+ ``HeatingCapacity`` double Btuh > 0 No See [#]_ Heating capacity
+ ``UniformEnergyFactor`` or ``EnergyFactor`` or ``YearInstalled`` double or integer frac or # < 1 or > 1600 Yes See [#]_ EnergyGuide label rated efficiency or Year installed
+ ``UsageBin`` or ``FirstHourRating`` string or double str or gal/hr See [#]_ or > 0 No See [#]_ EnergyGuide label usage bin/first hour rating
+ ``RecoveryEfficiency`` double frac 0 - 1 No See [#]_ Recovery efficiency
+ ``WaterHeaterInsulation/Jacket/JacketRValue`` double F-ft2-hr/Btu >= 0 No 0 R-value of additional tank insulation wrap
+ ================================================================ ================= ============= =============== ======== ======== ====================================================
.. [#] FuelType choices are "natural gas", "fuel oil", "fuel oil 1", "fuel oil 2", "fuel oil 4", "fuel oil 5/6", "diesel", "propane", "kerosene", "coal", "coke", "bituminous coal", "anthracite coal", "electricity", "wood", or "wood pellets".
.. [#] If TankVolume not provided, defaults based on Table 8 in the `2014 BAHSP `_.
.. [#] If HeatingCapacity not provided, defaults based on Table 8 in the `2014 BAHSP `_.
- .. [#] FirstHourRating only required if UniformEnergyFactor provided.
+ .. [#] If UniformEnergyFactor and EnergyFactor not provided, defaults to EnergyFactor from the lookup table that can be found at ``HPXMLtoOpenStudio\resources\lu_water_heater_efficiency.csv`` based on YearInstalled.
+ .. [#] UsageBin choices are "very small", "low", "medium", or "high".
+ .. [#] UsageBin/FirstHourRating are only used for water heaters that use UniformEnergyFactor.
+ If neither UsageBin nor FirstHourRating provided, UsageBin defaults to "medium".
+ If FirstHourRating provided and UsageBin not provided, UsageBin is determined based on the FirstHourRating value.
.. [#] If RecoveryEfficiency not provided, defaults as follows based on a regression analysis of `AHRI certified water heaters `_:
- **Electric**: 0.98
@@ -1541,18 +1583,21 @@ Heat Pump
If a heat pump water heater is specified, additional information is entered in ``WaterHeatingSystem``.
- ============================================= ======= ============ =========== ======== ======== ==========================================
- Element Type Units Constraints Required Default Notes
- ============================================= ======= ============ =========== ======== ======== ==========================================
- ``FuelType`` string See [#]_ Yes Fuel type
- ``TankVolume`` double gal > 0 Yes Tank volume
- ``UniformEnergyFactor`` or ``EnergyFactor`` double frac > 1 Yes EnergyGuide label rated efficiency
- ``FirstHourRating`` double gal/hr > 0 See [#]_ EnergyGuide label first hour rating
- ``WaterHeaterInsulation/Jacket/JacketRValue`` double F-ft2-hr/Btu >= 0 No 0 R-value of additional tank insulation wrap
- ============================================= ======= ============ =========== ======== ======== ==========================================
+ ============================================= ================ ============= =============== ======== ======== =============================================
+ Element Type Units Constraints Required Default Notes
+ ============================================= ================ ============= =============== ======== ======== =============================================
+ ``FuelType`` string See [#]_ Yes Fuel type
+ ``TankVolume`` double gal > 0 Yes Tank volume
+ ``UniformEnergyFactor`` or ``EnergyFactor`` double frac > 1 Yes EnergyGuide label rated efficiency
+ ``UsageBin`` or ``FirstHourRating`` string or double str or gal/hr See [#]_ or > 0 No See [#]_ EnergyGuide label usage bin/first hour rating
+ ``WaterHeaterInsulation/Jacket/JacketRValue`` double F-ft2-hr/Btu >= 0 No 0 R-value of additional tank insulation wrap
+ ============================================= ================ ============= =============== ======== ======== =============================================
.. [#] FuelType only choice is "electricity".
- .. [#] FirstHourRating only required if UniformEnergyFactor provided.
+ .. [#] UsageBin choices are "very small", "low", "medium", or "high".
+ .. [#] UsageBin/FirstHourRating are only used for water heaters that use UniformEnergyFactor.
+ If neither UsageBin nor FirstHourRating provided, UsageBin defaults to "medium".
+ If FirstHourRating provided and UsageBin not provided, UsageBin is determined based on the FirstHourRating value.
Combi Boiler w/ Storage
~~~~~~~~~~~~~~~~~~~~~~~
@@ -1758,22 +1803,23 @@ Detailed Inputs
To define a detailed solar hot water system, additional information is entered in ``SolarThermalSystem``.
- =================================== ======= ============ =========== ======== ======== ==============================
- Element Type Units Constraints Required Default Notes
- =================================== ======= ============ =========== ======== ======== ==============================
- ``CollectorArea`` double ft2 > 0 Yes Area
- ``CollectorLoopType`` string See [#]_ Yes Loop type
- ``CollectorType`` string See [#]_ Yes System type
- ``CollectorAzimuth`` integer deg 0 - 359 Yes Azimuth (clockwise from North)
- ``CollectorTilt`` double deg 0 - 90 Yes Tilt relative to horizontal
- ``CollectorRatedOpticalEfficiency`` double frac 0 - 1 Yes Rated optical efficiency [#]_
- ``CollectorRatedThermalLosses`` double Btu/hr-ft2-R > 0 Yes Rated thermal losses [#]_
- ``StorageVolume`` double gal > 0 No See [#]_ Hot water storage volume
- ``ConnectedTo`` idref See [#]_ Yes Connected water heater
- =================================== ======= ============ =========== ======== ======== ==============================
+ ================================================ ================= ================ =================== ======== ======== ==============================
+ Element Type Units Constraints Required Default Notes
+ ================================================ ================= ================ =================== ======== ======== ==============================
+ ``CollectorArea`` double ft2 > 0 Yes Area
+ ``CollectorLoopType`` string See [#]_ Yes Loop type
+ ``CollectorType`` string See [#]_ Yes System type
+ ``CollectorAzimuth`` or ``CollectorOrientation`` integer or string deg or direction 0 - 359 or See [#]_ Yes Direction panels face (clockwise from North)
+ ``CollectorTilt`` double deg 0 - 90 Yes Tilt relative to horizontal
+ ``CollectorRatedOpticalEfficiency`` double frac 0 - 1 Yes Rated optical efficiency [#]_
+ ``CollectorRatedThermalLosses`` double Btu/hr-ft2-R > 0 Yes Rated thermal losses [#]_
+ ``StorageVolume`` double gal > 0 No See [#]_ Hot water storage volume
+ ``ConnectedTo`` idref See [#]_ Yes Connected water heater
+ ================================================ ================= ================ =================== ======== ======== ==============================
.. [#] CollectorLoopType choices are "liquid indirect", "liquid direct", or "passive thermosyphon".
.. [#] CollectorType choices are "single glazing black", "double glazing black", "evacuated tube", or "integrated collector storage".
+ .. [#] CollectorOrientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
.. [#] CollectorRatedOpticalEfficiency is FRTA (y-intercept) from the `Directory of SRCC OG-100 Certified Solar Collector Ratings `_.
.. [#] CollectorRatedThermalLosses is FRUL (slope) from the `Directory of SRCC OG-100 Certified Solar Collector Ratings `_.
.. [#] If StorageVolume not provided, calculated as 1.5 gal/ft2 * CollectorArea.
@@ -1787,25 +1833,26 @@ If not entered, the simulation will not include photovoltaics.
Many of the inputs are adopted from the `PVWatts model `_.
- ======================================================= ================= ========= =============== ======== ======== ============================================
- Element Type Units Constraints Required Default Notes
- ======================================================= ================= ========= =============== ======== ======== ============================================
- ``SystemIdentifier`` id Yes Unique identifier
- ``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units
- ``Location`` string See [#]_ No roof Mounting location
- ``ModuleType`` string See [#]_ No standard Type of module
- ``Tracking`` string See [#]_ No fixed Type of tracking
- ``ArrayAzimuth`` integer deg 0 - 359 Yes Direction panels face (clockwise from North)
- ``ArrayTilt`` double deg 0 - 90 Yes Tilt relative to horizontal
- ``MaxPowerOutput`` double W >= 0 Yes Peak power
- ``InverterEfficiency`` double frac 0 - 1 No 0.96 Inverter efficiency
- ``SystemLossesFraction`` or ``YearModulesManufactured`` double or integer frac or # 0 - 1 or > 1600 No 0.14 System losses [#]_
- ``extension/NumberofBedroomsServed`` integer > 1 See [#]_ Number of bedrooms served
- ======================================================= ================= ========= =============== ======== ======== ============================================
+ ======================================================= ================= ================ =================== ======== ======== ============================================
+ Element Type Units Constraints Required Default Notes
+ ======================================================= ================= ================ =================== ======== ======== ============================================
+ ``SystemIdentifier`` id Yes Unique identifier
+ ``IsSharedSystem`` boolean No false Whether it serves multiple dwelling units
+ ``Location`` string See [#]_ No roof Mounting location
+ ``ModuleType`` string See [#]_ No standard Type of module
+ ``Tracking`` string See [#]_ No fixed Type of tracking
+ ``ArrayAzimuth`` or ``ArrayOrientation`` integer or string deg or direction 0 - 359 or See [#]_ Yes Direction panels face (clockwise from North)
+ ``ArrayTilt`` double deg 0 - 90 Yes Tilt relative to horizontal
+ ``MaxPowerOutput`` double W >= 0 Yes Peak power
+ ``InverterEfficiency`` double frac 0 - 1 No 0.96 Inverter efficiency
+ ``SystemLossesFraction`` or ``YearModulesManufactured`` double or integer frac or # 0 - 1 or > 1600 No 0.14 System losses [#]_
+ ``extension/NumberofBedroomsServed`` integer > 1 See [#]_ Number of bedrooms served
+ ======================================================= ================= ================ =================== ======== ======== ============================================
.. [#] Location choices are "ground" or "roof" mounted.
.. [#] ModuleType choices are "standard", "premium", or "thin film".
.. [#] Tracking choices are "fixed", "1-axis", "1-axis backtracked", or "2-axis".
+ .. [#] ArrayOrientation choices are "northeast", "east", "southeast", "south", "southwest", "west", "northwest", or "north"
.. [#] System losses due to soiling, shading, snow, mismatch, wiring, degradation, etc.
If YearModulesManufactured provided but not SystemLossesFraction, system losses calculated as:
SystemLossesFraction = 1.0 - (1.0 - 0.14) * (1.0 - (1.0 - 0.995^(CurrentYear - YearModulesManufactured))).
@@ -1906,7 +1953,7 @@ If not entered, the simulation will not include a clothes dryer.
``FuelType`` string See [#]_ Yes Fuel type
``CombinedEnergyFactor`` or ``EnergyFactor`` double lb/kWh > 0 No See [#]_ EnergyGuide label efficiency [#]_
``Vented`` boolean No true Whether dryer is vented
- ``VentedFlowRate`` double cfm >= 0 No 100 [#]_ Exhust flow rate during operation
+ ``VentedFlowRate`` double cfm >= 0 No 100 [#]_ Exhaust flow rate during operation
``extension/UsageMultiplier`` double >= 0 No 1.0 Multiplier on energy use
============================================ ======= ====== =========== ======== ============ ==============================================
diff --git a/tasks.rb b/tasks.rb
index 2722395da4..51fe4aaace 100644
--- a/tasks.rb
+++ b/tasks.rb
@@ -1,9 +1,6 @@
# frozen_string_literal: true
-$VERBOSE = nil # Prevents ruby warnings, see https://github.com/NREL/OpenStudio/issues/4301
-
def create_hpxmls
- require 'oga'
require_relative 'HPXMLtoOpenStudio/resources/constants'
require_relative 'HPXMLtoOpenStudio/resources/hotwater_appliances'
require_relative 'HPXMLtoOpenStudio/resources/hpxml'
@@ -11,7 +8,6 @@ def create_hpxmls
require_relative 'HPXMLtoOpenStudio/resources/misc_loads'
require_relative 'HPXMLtoOpenStudio/resources/schedules'
require_relative 'HPXMLtoOpenStudio/resources/waterheater'
- require_relative 'HPXMLtoOpenStudio/resources/xmlhelper'
this_dir = File.dirname(__FILE__)
sample_files_dir = File.join(this_dir, 'workflow/sample_files')
@@ -98,6 +94,8 @@ def create_hpxmls
'invalid_files/invalid-datatype-float.xml' => 'base.xml',
'invalid_files/invalid-datatype-integer.xml' => 'base.xml',
'invalid_files/invalid-daylight-saving.xml' => 'base-simcontrol-daylight-saving-custom.xml',
+ 'invalid_files/invalid-distribution-cfa-served.xml' => 'base.xml',
+ 'invalid_files/invalid-duct-area-fractions.xml' => 'base-hvac-ducts-area-fractions.xml',
'invalid_files/invalid-epw-filepath.xml' => 'base.xml',
'invalid_files/invalid-facility-type-equipment.xml' => 'base-bldgtype-multifamily-shared-laundry-room.xml',
'invalid_files/invalid-facility-type-surfaces.xml' => 'base.xml',
@@ -118,6 +116,8 @@ def create_hpxmls
'invalid_files/invalid-timestep.xml' => 'base.xml',
'invalid_files/invalid-window-height.xml' => 'base-enclosure-overhangs.xml',
'invalid_files/lighting-fractions.xml' => 'base.xml',
+ 'invalid_files/missing-duct-area.xml' => 'base-hvac-multiple.xml',
+ 'invalid_files/missing-duct-location.xml' => 'base-hvac-multiple.xml',
'invalid_files/missing-elements.xml' => 'base.xml',
'invalid_files/multifamily-reference-appliance.xml' => 'base.xml',
'invalid_files/multifamily-reference-duct.xml' => 'base.xml',
@@ -131,6 +131,8 @@ def create_hpxmls
'invalid_files/net-area-negative-wall.xml' => 'base.xml',
'invalid_files/orphaned-hvac-distribution.xml' => 'base-hvac-furnace-gas-room-ac.xml',
'invalid_files/refrigerator-location.xml' => 'base.xml',
+ 'invalid_files/refrigerators-multiple-primary.xml' => 'base.xml',
+ 'invalid_files/refrigerators-no-primary.xml' => 'base.xml',
'invalid_files/repeated-relatedhvac-dhw-indirect.xml' => 'base-dhw-indirect.xml',
'invalid_files/repeated-relatedhvac-desuperheater.xml' => 'base-hvac-central-ac-only-1-speed.xml',
'invalid_files/solar-fraction-one.xml' => 'base-dhw-solar-fraction.xml',
@@ -147,10 +149,6 @@ def create_hpxmls
'invalid_files/unattached-window.xml' => 'base.xml',
'invalid_files/water-heater-location.xml' => 'base.xml',
'invalid_files/water-heater-location-other.xml' => 'base.xml',
- 'invalid_files/missing-duct-location.xml' => 'base-hvac-multiple.xml',
- 'invalid_files/invalid-distribution-cfa-served.xml' => 'base.xml',
- 'invalid_files/refrigerators-multiple-primary.xml' => 'base.xml',
- 'invalid_files/refrigerators-no-primary.xml' => 'base.xml',
'base-appliances-coal.xml' => 'base.xml',
'base-appliances-dehumidifier.xml' => 'base-location-dallas-tx.xml',
'base-appliances-dehumidifier-ief-portable.xml' => 'base-appliances-dehumidifier.xml',
@@ -231,6 +229,7 @@ def create_hpxmls
'base-dhw-tank-elec-uef.xml' => 'base.xml',
'base-dhw-tank-gas.xml' => 'base.xml',
'base-dhw-tank-gas-uef.xml' => 'base.xml',
+ 'base-dhw-tank-gas-uef-fhr.xml' => 'base-dhw-tank-gas-uef.xml',
'base-dhw-tank-gas-outside.xml' => 'base-dhw-tank-gas.xml',
'base-dhw-tank-heat-pump.xml' => 'base.xml',
'base-dhw-tank-heat-pump-outside.xml' => 'base-dhw-tank-heat-pump.xml',
@@ -263,6 +262,7 @@ def create_hpxmls
'base-enclosure-infil-cfm50.xml' => 'base.xml',
'base-enclosure-infil-flue.xml' => 'base.xml',
'base-enclosure-infil-natural-ach.xml' => 'base.xml',
+ 'base-enclosure-orientations.xml' => 'base.xml',
'base-enclosure-overhangs.xml' => 'base.xml',
'base-enclosure-rooftypes.xml' => 'base.xml',
'base-enclosure-skylights.xml' => 'base.xml',
@@ -348,6 +348,7 @@ def create_hpxmls
'base-hvac-dual-fuel-air-to-air-heat-pump-var-speed.xml' => 'base-hvac-air-to-air-heat-pump-var-speed.xml',
'base-hvac-dual-fuel-mini-split-heat-pump-ducted.xml' => 'base-hvac-mini-split-heat-pump-ducted.xml',
'base-hvac-ducts-leakage-percent.xml' => 'base.xml',
+ 'base-hvac-ducts-area-fractions.xml' => 'base-enclosure-2stories.xml',
'base-hvac-elec-resistance-only.xml' => 'base.xml',
'base-hvac-evap-cooler-furnace-gas.xml' => 'base.xml',
'base-hvac-evap-cooler-only.xml' => 'base.xml',
@@ -370,20 +371,16 @@ def create_hpxmls
'base-hvac-ground-to-air-heat-pump-cooling-only.xml' => 'base-hvac-ground-to-air-heat-pump.xml',
'base-hvac-ground-to-air-heat-pump-heating-only.xml' => 'base-hvac-ground-to-air-heat-pump.xml',
'base-hvac-seasons.xml' => 'base.xml',
- 'base-hvac-install-quality-none-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
- 'base-hvac-install-quality-airflow-defect-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
- 'base-hvac-install-quality-charge-defect-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
- 'base-hvac-install-quality-blower-efficiency-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
- 'base-hvac-install-quality-all-air-to-air-heat-pump-1-speed.xml' => 'base-hvac-air-to-air-heat-pump-1-speed.xml',
- 'base-hvac-install-quality-all-air-to-air-heat-pump-2-speed.xml' => 'base-hvac-air-to-air-heat-pump-2-speed.xml',
- 'base-hvac-install-quality-all-air-to-air-heat-pump-var-speed.xml' => 'base-hvac-air-to-air-heat-pump-var-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.xml' => 'base-hvac-furnace-gas-central-ac-2-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.xml' => 'base-hvac-furnace-gas-central-ac-var-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-only.xml' => 'base-hvac-furnace-gas-only.xml',
- 'base-hvac-install-quality-all-ground-to-air-heat-pump.xml' => 'base-hvac-ground-to-air-heat-pump.xml',
- 'base-hvac-install-quality-all-mini-split-heat-pump-ducted.xml' => 'base-hvac-mini-split-heat-pump-ducted.xml',
- 'base-hvac-install-quality-all-mini-split-air-conditioner-only-ducted.xml' => 'base-hvac-mini-split-air-conditioner-only-ducted.xml',
+ 'base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml' => 'base-hvac-air-to-air-heat-pump-1-speed.xml',
+ 'base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml' => 'base-hvac-air-to-air-heat-pump-2-speed.xml',
+ 'base-hvac-install-quality-air-to-air-heat-pump-var-speed.xml' => 'base-hvac-air-to-air-heat-pump-var-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-1-speed.xml' => 'base.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-2-speed.xml' => 'base-hvac-furnace-gas-central-ac-2-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-var-speed.xml' => 'base-hvac-furnace-gas-central-ac-var-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-only.xml' => 'base-hvac-furnace-gas-only.xml',
+ 'base-hvac-install-quality-ground-to-air-heat-pump.xml' => 'base-hvac-ground-to-air-heat-pump.xml',
+ 'base-hvac-install-quality-mini-split-heat-pump-ducted.xml' => 'base-hvac-mini-split-heat-pump-ducted.xml',
+ 'base-hvac-install-quality-mini-split-air-conditioner-only-ducted.xml' => 'base-hvac-mini-split-air-conditioner-only-ducted.xml',
'base-hvac-mini-split-air-conditioner-only-ducted.xml' => 'base.xml',
'base-hvac-mini-split-air-conditioner-only-ductless.xml' => 'base-hvac-mini-split-air-conditioner-only-ducted.xml',
'base-hvac-mini-split-heat-pump-ducted.xml' => 'base.xml',
@@ -397,6 +394,7 @@ def create_hpxmls
'base-hvac-programmable-thermostat-detailed.xml' => 'base.xml',
'base-hvac-room-ac-only.xml' => 'base.xml',
'base-hvac-room-ac-only-33percent.xml' => 'base-hvac-room-ac-only.xml',
+ 'base-hvac-room-ac-only-ceer.xml' => 'base-hvac-room-ac-only.xml',
'base-hvac-setpoints.xml' => 'base.xml',
'base-hvac-stove-oil-only.xml' => 'base.xml',
'base-hvac-stove-wood-pellets-only.xml' => 'base.xml',
@@ -550,7 +548,17 @@ def create_hpxmls
building_element = XMLHelper.get_element(hpxml_element, 'Building')
for i in 2..3
new_building_element = Marshal.load(Marshal.dump(building_element))
- XMLHelper.add_attribute(XMLHelper.get_element(new_building_element, 'BuildingID'), 'id', "MyBuilding#{i}")
+
+ # Make all IDs unique so the HPXML is valid
+ new_building_element.each_node do |node|
+ next unless node.is_a?(Oga::XML::Element)
+
+ id = XMLHelper.get_attribute_value(node, 'id')
+ next if id.nil?
+
+ XMLHelper.add_attribute(node, 'id', "#{id}_#{i}")
+ end
+
hpxml_element.children << new_building_element
end
XMLHelper.write_file(hpxml_doc, hpxml_path)
@@ -987,7 +995,7 @@ def set_hpxml_roofs(hpxml_file, hpxml)
elsif ['base.xml'].include? hpxml_file
hpxml.roofs.add(id: 'Roof',
interior_adjacent_to: HPXML::LocationAtticUnvented,
- area: 1510,
+ area: 1509.3,
roof_type: HPXML::RoofTypeAsphaltShingles,
solar_absorptance: 0.7,
emittance: 0.92,
@@ -1002,16 +1010,21 @@ def set_hpxml_roofs(hpxml_file, hpxml)
roof_types = [[HPXML::RoofTypeClayTile, HPXML::ColorLight],
[HPXML::RoofTypeMetal, HPXML::ColorReflective],
[HPXML::RoofTypeWoodShingles, HPXML::ColorDark]]
+ int_finish_types = [[HPXML::InteriorFinishGypsumBoard, 0.5],
+ [HPXML::InteriorFinishPlaster, 0.5],
+ [HPXML::InteriorFinishWood, 0.5]]
hpxml.roofs.clear
roof_types.each_with_index do |roof_type, i|
hpxml.roofs.add(id: "Roof#{i + 1}",
interior_adjacent_to: HPXML::LocationAtticUnvented,
- area: 1510 / roof_types.size,
+ area: 1509.3 / roof_types.size,
roof_type: roof_type[0],
roof_color: roof_type[1],
emittance: 0.92,
pitch: 6,
radiant_barrier: false,
+ interior_finish_type: int_finish_types[i % int_finish_types.size][0],
+ interior_finish_thickness: int_finish_types[i % int_finish_types.size][1],
insulation_assembly_r_value: 2.3)
end
elsif ['base-atticroof-flat.xml'].include? hpxml_file
@@ -1024,6 +1037,7 @@ def set_hpxml_roofs(hpxml_file, hpxml)
emittance: 0.92,
pitch: 0,
radiant_barrier: false,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 25.8)
elsif ['base-atticroof-conditioned.xml'].include? hpxml_file
hpxml.roofs.clear
@@ -1035,6 +1049,7 @@ def set_hpxml_roofs(hpxml_file, hpxml)
emittance: 0.92,
pitch: 6,
radiant_barrier: false,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 25.8)
hpxml.roofs.add(id: 'RoofUncond',
interior_adjacent_to: HPXML::LocationAtticUnvented,
@@ -1050,9 +1065,10 @@ def set_hpxml_roofs(hpxml_file, hpxml)
elsif ['base-atticroof-cathedral.xml'].include? hpxml_file
hpxml.roofs[0].interior_adjacent_to = HPXML::LocationLivingSpace
hpxml.roofs[0].insulation_assembly_r_value = 25.8
+ hpxml.roofs[0].interior_finish_type = HPXML::InteriorFinishGypsumBoard
elsif ['base-enclosure-garage.xml',
'base-foundation-basement-garage.xml'].include? hpxml_file
- hpxml.roofs[0].area += 670
+ hpxml.roofs[0].area += 671
elsif ['base-atticroof-unvented-insulated-roof.xml'].include? hpxml_file
hpxml.roofs[0].insulation_assembly_r_value = 25.8
elsif ['base-enclosure-split-surfaces.xml',
@@ -1079,9 +1095,11 @@ def set_hpxml_roofs(hpxml_file, hpxml)
hpxml.roofs.each do |roof|
roof.roof_type = nil
roof.solar_absorptance = nil
- roof.roof_color = HPXML::ColorLight
+ roof.roof_color = nil
roof.emittance = nil
roof.radiant_barrier = nil
+ roof.interior_finish_type = nil
+ roof.interior_finish_thickness = nil
end
elsif ['invalid_files/invalid-input-parameters.xml'].include? hpxml_file
hpxml.roofs[0].radiant_barrier_grade = 4
@@ -1149,7 +1167,8 @@ def set_hpxml_rim_joists(hpxml_file, hpxml)
[HPXML::SidingTypeBrick, HPXML::ColorReflective],
[HPXML::SidingTypeFiberCement, HPXML::ColorMediumDark],
[HPXML::SidingTypeStucco, HPXML::ColorMedium],
- [HPXML::SidingTypeVinyl, HPXML::ColorLight]]
+ [HPXML::SidingTypeVinyl, HPXML::ColorLight],
+ [HPXML::SidingTypeNone, HPXML::ColorMedium]]
hpxml.rim_joists.clear
siding_types.each_with_index do |siding_type, i|
hpxml.rim_joists.add(id: "RimJoistFoundation#{i + 1}",
@@ -1167,7 +1186,7 @@ def set_hpxml_rim_joists(hpxml_file, hpxml)
elsif ['base-foundation-unconditioned-basement.xml'].include? hpxml_file
for i in 0..hpxml.rim_joists.size - 1
hpxml.rim_joists[i].interior_adjacent_to = HPXML::LocationBasementUnconditioned
- hpxml.rim_joists[i].insulation_assembly_r_value = 2.3
+ hpxml.rim_joists[i].insulation_assembly_r_value = 4.0
end
elsif ['base-foundation-unconditioned-basement-wall-insulation.xml'].include? hpxml_file
for i in 0..hpxml.rim_joists.size - 1
@@ -1191,7 +1210,7 @@ def set_hpxml_rim_joists(hpxml_file, hpxml)
area: 81,
solar_absorptance: 0.7,
emittance: 0.92,
- insulation_assembly_r_value: 2.3)
+ insulation_assembly_r_value: 4.0)
elsif ['base-enclosure-2stories.xml'].include? hpxml_file
hpxml.rim_joists.add(id: 'RimJoist2ndStory',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1228,7 +1247,7 @@ def set_hpxml_rim_joists(hpxml_file, hpxml)
hpxml.rim_joists.each do |rim_joist|
rim_joist.siding = nil
rim_joist.solar_absorptance = nil
- rim_joist.color = HPXML::ColorMedium
+ rim_joist.color = nil
rim_joist.emittance = nil
end
end
@@ -1251,6 +1270,8 @@ def set_hpxml_walls(hpxml_file, hpxml)
azimuth: 0,
solar_absorptance: 0.6,
emittance: 0.9,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
+ interior_finish_thickness: 0.5,
insulation_assembly_r_value: 11.76)
hpxml.walls.add(id: 'WallEast',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1261,6 +1282,8 @@ def set_hpxml_walls(hpxml_file, hpxml)
azimuth: 90,
solar_absorptance: 0.6,
emittance: 0.9,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
+ interior_finish_thickness: 0.5,
insulation_assembly_r_value: 11.76)
hpxml.walls.add(id: 'WallSouth',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1271,6 +1294,8 @@ def set_hpxml_walls(hpxml_file, hpxml)
azimuth: 180,
solar_absorptance: 0.6,
emittance: 0.9,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
+ interior_finish_thickness: 0.5,
insulation_assembly_r_value: 11.76)
hpxml.walls.add(id: 'WallWest',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1281,6 +1306,8 @@ def set_hpxml_walls(hpxml_file, hpxml)
azimuth: 270,
solar_absorptance: 0.6,
emittance: 0.9,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
+ interior_finish_thickness: 0.5,
insulation_assembly_r_value: 11.76)
hpxml.walls.add(id: 'WallAtticGableEast',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1326,6 +1353,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 1200,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallAtticGable',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1346,6 +1374,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 686,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
@@ -1354,6 +1383,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 294,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 4.0)
elsif ['base-bldgtype-single-family-attached.xml'].include? hpxml_file
hpxml.walls.clear
@@ -1365,6 +1395,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 686,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
@@ -1373,6 +1404,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 294,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 4.0)
hpxml.walls.add(id: 'WallAtticGable',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1398,6 +1430,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
elsif ['base-atticroof-cathedral.xml'].include? hpxml_file
hpxml.walls[1].interior_adjacent_to = HPXML::LocationLivingSpace
hpxml.walls[1].insulation_assembly_r_value = 23.0
+ hpxml.walls[1].interior_finish_type = HPXML::InteriorFinishGypsumBoard
elsif ['base-atticroof-conditioned.xml'].include? hpxml_file
hpxml.walls.delete_at(1)
hpxml.walls.add(id: 'WallAtticKneeWall',
@@ -1407,6 +1440,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 316,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallAtticGableCond',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1416,6 +1450,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 240,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 22.3)
hpxml.walls.add(id: 'WallAtticGableUncond',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1435,6 +1470,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 100,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallOtherMultifamilyBufferSpace',
exterior_adjacent_to: HPXML::LocationOtherMultifamilyBufferSpace,
@@ -1443,6 +1479,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 100,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallOtherNonFreezingSpace',
exterior_adjacent_to: HPXML::LocationOtherNonFreezingSpace,
@@ -1451,6 +1488,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 100,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23.0)
hpxml.walls.add(id: 'WallOtherHousingUnit',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
@@ -1459,6 +1497,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 100,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 4.0)
elsif ['base-enclosure-walltypes.xml'].include? hpxml_file
walls_map = { HPXML::WallTypeCMU => 12,
@@ -1476,7 +1515,14 @@ def set_hpxml_walls(hpxml_file, hpxml)
[HPXML::SidingTypeBrick, HPXML::ColorMediumDark],
[HPXML::SidingTypeFiberCement, HPXML::ColorMedium],
[HPXML::SidingTypeStucco, HPXML::ColorLight],
- [HPXML::SidingTypeVinyl, HPXML::ColorDark]]
+ [HPXML::SidingTypeVinyl, HPXML::ColorDark],
+ [HPXML::SidingTypeNone, HPXML::ColorMedium]]
+ int_finish_types = [[HPXML::InteriorFinishGypsumBoard, 0.5],
+ [HPXML::InteriorFinishGypsumBoard, 1.0],
+ [HPXML::InteriorFinishGypsumCompositeBoard, 0.5],
+ [HPXML::InteriorFinishPlaster, 0.5],
+ [HPXML::InteriorFinishWood, 0.5],
+ [HPXML::InteriorFinishNone, nil]]
last_wall = hpxml.walls[-1]
hpxml.walls.clear
walls_map.each_with_index do |(wall_type, assembly_r), i|
@@ -1488,6 +1534,8 @@ def set_hpxml_walls(hpxml_file, hpxml)
color: siding_types[i % siding_types.size][1],
area: 1200 / walls_map.size,
emittance: 0.92,
+ interior_finish_type: int_finish_types[i % int_finish_types.size][0],
+ interior_finish_thickness: int_finish_types[i % int_finish_types.size][1],
insulation_assembly_r_value: assembly_r)
end
hpxml.walls << last_wall
@@ -1503,6 +1551,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 2080,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23)
hpxml.walls.add(id: 'WallGarageInterior',
exterior_adjacent_to: HPXML::LocationGarage,
@@ -1511,6 +1560,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 320,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23)
hpxml.walls.add(id: 'WallGarageExterior',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1540,6 +1590,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 960,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23)
hpxml.walls.add(id: 'WallGarageInterior',
exterior_adjacent_to: HPXML::LocationGarage,
@@ -1548,6 +1599,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 240,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23)
hpxml.walls.add(id: 'WallGarageExterior',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1608,6 +1660,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 294,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 4.0)
elsif ['invalid_files/invalid-assembly-effective-rvalue.xml'].include? hpxml_file
hpxml.walls[0].insulation_assembly_r_value = 0
@@ -1615,8 +1668,10 @@ def set_hpxml_walls(hpxml_file, hpxml)
hpxml.walls.each do |wall|
wall.siding = nil
wall.solar_absorptance = nil
- wall.color = HPXML::ColorMedium
+ wall.color = nil
wall.emittance = nil
+ wall.interior_finish_type = nil
+ wall.interior_finish_thickness = nil
end
elsif ['base-foundation-basement-garage.xml'].include? hpxml_file
hpxml.walls.add(id: 'WallGarageBasement',
@@ -1626,6 +1681,7 @@ def set_hpxml_walls(hpxml_file, hpxml)
area: 320,
solar_absorptance: 0.7,
emittance: 0.92,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 23)
hpxml.walls.add(id: 'WallGarageExterior',
exterior_adjacent_to: HPXML::LocationOutside,
@@ -1647,13 +1703,14 @@ def set_hpxml_walls(hpxml_file, hpxml)
def set_hpxml_foundation_walls(hpxml_file, hpxml)
if ['ASHRAE_Standard_140/L322XC.xml'].include? hpxml_file
hpxml.foundation_walls.add(id: 'FoundationWallNorth',
- exterior_adjacent_to: 'ground',
+ exterior_adjacent_to: HPXML::LocationGround,
interior_adjacent_to: HPXML::LocationBasementConditioned,
height: 7.25,
area: 413.25,
azimuth: 0,
thickness: 6,
depth_below_grade: 6.583,
+ interior_finish_type: HPXML::InteriorFinishNone,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1661,13 +1718,14 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
insulation_exterior_distance_to_top: 0,
insulation_exterior_distance_to_bottom: 0)
hpxml.foundation_walls.add(id: 'FoundationWallEast',
- exterior_adjacent_to: 'ground',
+ exterior_adjacent_to: HPXML::LocationGround,
interior_adjacent_to: HPXML::LocationBasementConditioned,
height: 7.25,
area: 195.75,
azimuth: 90,
thickness: 6,
depth_below_grade: 6.583,
+ interior_finish_type: HPXML::InteriorFinishNone,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1675,13 +1733,14 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
insulation_exterior_distance_to_top: 0,
insulation_exterior_distance_to_bottom: 0)
hpxml.foundation_walls.add(id: 'FoundationWallSouth',
- exterior_adjacent_to: 'ground',
+ exterior_adjacent_to: HPXML::LocationGround,
interior_adjacent_to: HPXML::LocationBasementConditioned,
height: 7.25,
area: 413.25,
azimuth: 180,
thickness: 6,
depth_below_grade: 6.583,
+ interior_finish_type: HPXML::InteriorFinishNone,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1689,13 +1748,14 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
insulation_exterior_distance_to_top: 0,
insulation_exterior_distance_to_bottom: 0)
hpxml.foundation_walls.add(id: 'FoundationWallWest',
- exterior_adjacent_to: 'ground',
+ exterior_adjacent_to: HPXML::LocationGround,
interior_adjacent_to: HPXML::LocationBasementConditioned,
height: 7.25,
area: 195.75,
azimuth: 270,
thickness: 6,
depth_below_grade: 6.583,
+ interior_finish_type: HPXML::InteriorFinishNone,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1707,6 +1767,8 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
hpxml.foundation_walls[i].insulation_interior_r_value = 10.2
hpxml.foundation_walls[i].insulation_interior_distance_to_top = 0.0
hpxml.foundation_walls[i].insulation_interior_distance_to_bottom = 7.25
+ hpxml.foundation_walls[i].interior_finish_type = HPXML::InteriorFinishGypsumBoard
+ hpxml.foundation_walls[i].interior_finish_thickness = 0.5
end
elsif ['base.xml'].include? hpxml_file
hpxml.foundation_walls.add(id: 'FoundationWall',
@@ -1716,6 +1778,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 1200,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1733,6 +1796,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 686,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1746,6 +1810,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 294,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1762,6 +1827,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
hpxml.foundation_walls[0].interior_adjacent_to = HPXML::LocationBasementUnconditioned
hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = 0
hpxml.foundation_walls[0].insulation_exterior_r_value = 0
+ hpxml.foundation_walls[0].interior_finish_type = HPXML::InteriorFinishNone
elsif ['base-foundation-unconditioned-basement-wall-insulation.xml'].include? hpxml_file
hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom = 4
hpxml.foundation_walls[0].insulation_exterior_r_value = 8.9
@@ -1786,6 +1852,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
hpxml.foundation_walls[0].area /= 2.0
hpxml.foundation_walls[0].depth_below_grade -= 4
hpxml.foundation_walls[0].insulation_exterior_distance_to_bottom -= 4
+ hpxml.foundation_walls[0].interior_finish_type = HPXML::InteriorFinishNone
elsif ['base-foundation-multiple.xml'].include? hpxml_file
hpxml.foundation_walls[0].area = 600
hpxml.foundation_walls.add(id: 'FoundationWallInterior',
@@ -1826,6 +1893,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 480,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1839,6 +1907,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 120,
thickness: 8,
depth_below_grade: 3,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1852,6 +1921,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 60,
thickness: 8,
depth_below_grade: 1,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1867,6 +1937,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 160,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1880,6 +1951,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 240,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1893,6 +1965,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 160,
thickness: 8,
depth_below_grade: 3,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1906,6 +1979,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 120,
thickness: 8,
depth_below_grade: 3,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1919,6 +1993,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 80,
thickness: 8,
depth_below_grade: 3,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1945,6 +2020,14 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
elsif ['base-misc-defaults.xml'].include? hpxml_file
hpxml.foundation_walls.each do |fwall|
fwall.thickness = nil
+ fwall.interior_finish_type = nil
+ fwall.interior_finish_thickness = nil
+ fwall.insulation_interior_distance_to_top = nil
+ fwall.insulation_interior_distance_to_bottom = nil
+ fwall.insulation_exterior_distance_to_top = nil
+ fwall.insulation_exterior_distance_to_bottom = nil
+ fwall.length = (fwall.area / fwall.height).round(2)
+ fwall.area = nil
end
elsif ['invalid_files/invalid-facility-type-surfaces.xml'].include? hpxml_file
hpxml.foundation_walls.add(id: 'FoundationWallOther',
@@ -1954,6 +2037,7 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
area: 294,
thickness: 8,
depth_below_grade: 7,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_interior_r_value: 0,
insulation_interior_distance_to_top: 0,
insulation_interior_distance_to_bottom: 0,
@@ -1972,12 +2056,14 @@ def set_hpxml_foundation_walls(hpxml_file, hpxml)
def set_hpxml_frame_floors(hpxml_file, hpxml)
if ['ASHRAE_Standard_140/L100AC.xml',
'ASHRAE_Standard_140/L100AL.xml'].include? hpxml_file
- hpxml.frame_floors.add(id: 'FloorUnderAttic',
+ hpxml.frame_floors.add(id: 'CeilingBelowAttic',
exterior_adjacent_to: HPXML::LocationAtticVented,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 1539,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
+ interior_finish_thickness: 0.5,
insulation_assembly_r_value: 18.45)
- hpxml.frame_floors.add(id: 'FloorOverFoundation',
+ hpxml.frame_floors.add(id: 'FloorAboveFoundation',
exterior_adjacent_to: HPXML::LocationOutside,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 1539,
@@ -1994,23 +2080,25 @@ def set_hpxml_frame_floors(hpxml_file, hpxml)
'ASHRAE_Standard_140/L324XC.xml'].include? hpxml_file
hpxml.frame_floors.delete_at(1)
elsif ['base.xml'].include? hpxml_file
- hpxml.frame_floors.add(id: 'FloorBelowAttic',
+ hpxml.frame_floors.add(id: 'CeilingBelowAttic',
exterior_adjacent_to: HPXML::LocationAtticUnvented,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 1350,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 39.3)
elsif ['base-bldgtype-multifamily.xml'].include? hpxml_file
hpxml.frame_floors.clear
- hpxml.frame_floors.add(id: 'FloorOther',
+ hpxml.frame_floors.add(id: 'FloorAboveOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 900,
insulation_assembly_r_value: 2.1,
other_space_above_or_below: HPXML::FrameFloorOtherSpaceBelow)
- hpxml.frame_floors.add(id: 'CeilingOther',
+ hpxml.frame_floors.add(id: 'CeilingBelowOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 900,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 2.1,
other_space_above_or_below: HPXML::FrameFloorOtherSpaceAbove)
elsif ['base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml'].include? hpxml_file
@@ -2145,16 +2233,17 @@ def set_hpxml_frame_floors(hpxml_file, hpxml)
hpxml.frame_floors[1].exterior_adjacent_to = HPXML::LocationOtherHeatedSpace
hpxml.frame_floors[1].other_space_above_or_below = HPXML::FrameFloorOtherSpaceAbove
elsif ['invalid_files/invalid-facility-type-surfaces.xml'].include? hpxml_file
- hpxml.frame_floors.add(id: 'FloorOther',
+ hpxml.frame_floors.add(id: 'FloorAboveOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 900,
insulation_assembly_r_value: 2.1,
other_space_above_or_below: HPXML::FrameFloorOtherSpaceBelow)
- hpxml.frame_floors.add(id: 'CeilingOther',
+ hpxml.frame_floors.add(id: 'CeilingBelowOther',
exterior_adjacent_to: HPXML::LocationOtherHousingUnit,
interior_adjacent_to: HPXML::LocationLivingSpace,
area: 900,
+ interior_finish_type: HPXML::InteriorFinishGypsumBoard,
insulation_assembly_r_value: 2.1,
other_space_above_or_below: HPXML::FrameFloorOtherSpaceAbove)
end
@@ -2441,6 +2530,15 @@ def set_hpxml_windows(hpxml_file, hpxml)
interior_shading_factor_summer: 0.7,
interior_shading_factor_winter: 0.85,
wall_idref: 'Wall')
+ elsif ['base-enclosure-orientations.xml'].include? hpxml_file
+ hpxml.windows[0].azimuth = nil
+ hpxml.windows[0].orientation = HPXML::OrientationNorth
+ hpxml.windows[1].azimuth = nil
+ hpxml.windows[1].orientation = HPXML::OrientationSouth
+ hpxml.windows[2].azimuth = nil
+ hpxml.windows[2].orientation = HPXML::OrientationEast
+ hpxml.windows[3].azimuth = nil
+ hpxml.windows[3].orientation = HPXML::OrientationWest
elsif ['base-bldgtype-multifamily.xml'].include? hpxml_file
hpxml.windows.clear
hpxml.windows.add(id: 'WindowNorth',
@@ -2769,14 +2867,19 @@ def set_hpxml_doors(hpxml_file, hpxml)
elsif ['base.xml'].include? hpxml_file
hpxml.doors.add(id: 'DoorNorth',
wall_idref: 'Wall',
- area: 40,
+ area: 20,
azimuth: 0,
r_value: 4.4)
hpxml.doors.add(id: 'DoorSouth',
wall_idref: 'Wall',
- area: 40,
+ area: 20,
azimuth: 180,
r_value: 4.4)
+ elsif ['base-enclosure-orientations.xml'].include? hpxml_file
+ hpxml.doors[0].azimuth = nil
+ hpxml.doors[0].orientation = HPXML::OrientationNorth
+ hpxml.doors[1].azimuth = nil
+ hpxml.doors[1].orientation = HPXML::OrientationSouth
elsif ['base-bldgtype-multifamily.xml'].include? hpxml_file
hpxml.doors.clear
hpxml.doors.add(id: 'Door',
@@ -2845,14 +2948,18 @@ def set_hpxml_doors(hpxml_file, hpxml)
hpxml.doors.clear
hpxml.doors.add(id: 'DoorNorth',
wall_idref: 'Wall9',
- area: 40,
+ area: 20,
azimuth: 0,
r_value: 4.4)
hpxml.doors.add(id: 'DoorSouth',
wall_idref: 'Wall10',
- area: 40,
+ area: 20,
azimuth: 180,
r_value: 4.4)
+ elsif ['base-misc-defaults.xml'].include? hpxml_file
+ hpxml.doors.each do |door|
+ door.azimuth = nil
+ end
end
end
@@ -2885,7 +2992,7 @@ def set_hpxml_heating_systems(hpxml_file, hpxml)
elsif ['base-hvac-boiler-elec-only.xml'].include? hpxml_file
hpxml.heating_systems[0].heating_system_type = HPXML::HVACTypeBoiler
hpxml.heating_systems[0].heating_system_fuel = HPXML::FuelTypeElectricity
- hpxml.heating_systems[0].heating_efficiency_afue = 1.0
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.98
elsif ['base-hvac-boiler-gas-central-ac-1-speed.xml',
'base-hvac-boiler-gas-only.xml'].include? hpxml_file
hpxml.heating_systems[0].heating_system_type = HPXML::HVACTypeBoiler
@@ -2910,7 +3017,7 @@ def set_hpxml_heating_systems(hpxml_file, hpxml)
hpxml.heating_systems[0].heating_efficiency_percent = 1
elsif ['base-hvac-furnace-elec-only.xml'].include? hpxml_file
hpxml.heating_systems[0].heating_system_fuel = HPXML::FuelTypeElectricity
- hpxml.heating_systems[0].heating_efficiency_afue = 1
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.98
elsif ['base-hvac-furnace-oil-only.xml'].include? hpxml_file
hpxml.heating_systems[0].heating_system_fuel = HPXML::FuelTypeOil
elsif ['base-hvac-furnace-propane-only.xml'].include? hpxml_file
@@ -3022,7 +3129,7 @@ def set_hpxml_heating_systems(hpxml_file, hpxml)
hpxml.heating_systems[0].distribution_system_idref = nil
hpxml.heating_systems[0].heating_system_type = HPXML::HVACTypeWallFurnace
hpxml.heating_systems[0].heating_system_fuel = HPXML::FuelTypeElectricity
- hpxml.heating_systems[0].heating_efficiency_afue = 1.0
+ hpxml.heating_systems[0].heating_efficiency_afue = 0.98
hpxml.heating_systems[0].fan_watts = 0.0
elsif ['base-hvac-furnace-x3-dse.xml'].include? hpxml_file
hpxml.heating_systems << hpxml.heating_systems[0].dup
@@ -3069,16 +3176,10 @@ def set_hpxml_heating_systems(hpxml_file, hpxml)
hpxml.heating_systems[0].fan_coil_watts = nil
hpxml.heating_systems[0].shared_loop_watts = nil
hpxml.heating_systems[0].electric_auxiliary_energy = 500.0
- elsif ['base-hvac-install-quality-none-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.heating_systems[0].airflow_defect_ratio = 0.0
- elsif ['base-hvac-install-quality-airflow-defect-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.heating_systems[0].airflow_defect_ratio = -0.25
- elsif ['base-hvac-install-quality-blower-efficiency-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.heating_systems[0].fan_watts_per_cfm = 0.365
- elsif ['base-hvac-install-quality-all-furnace-gas-only.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.xml'].include? hpxml_file
+ elsif ['base-hvac-install-quality-furnace-gas-only.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-1-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-2-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-var-speed.xml'].include? hpxml_file
hpxml.heating_systems[0].fan_watts_per_cfm = 0.365
hpxml.heating_systems[0].airflow_defect_ratio = -0.25
elsif ['invalid_files/multiple-shared-heating-systems.xml'].include? hpxml_file
@@ -3105,6 +3206,9 @@ def set_hpxml_heating_systems(hpxml_file, hpxml)
hpxml.heating_systems[0].heating_capacity = 48000
elsif hpxml_file.include?('base-hvac-autosize') && (not hpxml.heating_systems.nil?) && (hpxml.heating_systems.size > 0)
hpxml.heating_systems[0].heating_capacity = nil
+ elsif ['base-misc-defaults.xml'].include? hpxml_file
+ hpxml.heating_systems[0].heating_efficiency_afue = nil
+ hpxml.heating_systems[0].year_installed = 2009
end
end
@@ -3178,6 +3282,9 @@ def set_hpxml_cooling_systems(hpxml_file, hpxml)
elsif ['base-hvac-room-ac-only-33percent.xml'].include? hpxml_file
hpxml.cooling_systems[0].fraction_cool_load_served = 0.33
hpxml.cooling_systems[0].cooling_capacity /= 3.0
+ elsif ['base-hvac-room-ac-only-ceer.xml'].include? hpxml_file
+ hpxml.cooling_systems[0].cooling_efficiency_eer = nil
+ hpxml.cooling_systems[0].cooling_efficiency_ceer = 8.4
elsif ['base-hvac-evap-cooler-only-ducted.xml',
'base-hvac-evap-cooler-furnace-gas.xml',
'base-hvac-evap-cooler-only.xml'].include? hpxml_file
@@ -3218,25 +3325,18 @@ def set_hpxml_cooling_systems(hpxml_file, hpxml)
hpxml.cooling_systems[0].fan_watts_per_cfm = 0.55
elsif ['base-hvac-undersized.xml'].include? hpxml_file
hpxml.cooling_systems[0].cooling_capacity /= 10.0
- elsif ['base-hvac-install-quality-none-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.cooling_systems[0].airflow_defect_ratio = 0.0
- hpxml.cooling_systems[0].charge_defect_ratio = 0.0
- elsif ['base-hvac-install-quality-airflow-defect-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.cooling_systems[0].airflow_defect_ratio = -0.25
- elsif ['base-hvac-install-quality-charge-defect-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.cooling_systems[0].charge_defect_ratio = -0.25
- elsif ['base-hvac-install-quality-blower-efficiency-furnace-gas-central-ac-1-speed.xml'].include? hpxml_file
- hpxml.cooling_systems[0].fan_watts_per_cfm = 0.365
- elsif ['base-hvac-install-quality-all-mini-split-air-conditioner-only-ducted.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-1-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-2-speed.xml',
- 'base-hvac-install-quality-all-furnace-gas-central-ac-var-speed.xml'].include? hpxml_file
+ elsif ['base-hvac-install-quality-mini-split-air-conditioner-only-ducted.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-1-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-2-speed.xml',
+ 'base-hvac-install-quality-furnace-gas-central-ac-var-speed.xml'].include? hpxml_file
hpxml.cooling_systems[0].charge_defect_ratio = -0.25
hpxml.cooling_systems[0].fan_watts_per_cfm = 0.365
hpxml.cooling_systems[0].airflow_defect_ratio = -0.25
elsif ['base-misc-defaults.xml'].include? hpxml_file
hpxml.cooling_systems[0].cooling_shr = nil
hpxml.cooling_systems[0].compressor_type = nil
+ hpxml.cooling_systems[0].cooling_efficiency_seer = nil
+ hpxml.cooling_systems[0].year_installed = 2009
elsif ['base-bldgtype-multifamily-shared-chiller-only-baseboard.xml',
'base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml',
'base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml',
@@ -3383,7 +3483,7 @@ def set_hpxml_heat_pumps(hpxml_file, hpxml)
'base-hvac-ground-to-air-heat-pump-cooling-only.xml',
'base-hvac-mini-split-heat-pump-ducted-cooling-only.xml'].include? hpxml_file
hpxml.heat_pumps[0].heating_capacity = 0
- if not ['base-hvac-ground-to-air-heat-pump-cooling-only.xml'].include? hpxml_file
+ if hpxml_file != 'base-hvac-ground-to-air-heat-pump-cooling-only.xml'
hpxml.heat_pumps[0].heating_capacity_17F = 0
end
hpxml.heat_pumps[0].fraction_heat_load_served = 0
@@ -3477,18 +3577,14 @@ def set_hpxml_heat_pumps(hpxml_file, hpxml)
elsif ['base-hvac-dual-fuel-air-to-air-heat-pump-1-speed-electric.xml'].include? hpxml_file
hpxml.heat_pumps[0].backup_heating_fuel = HPXML::FuelTypeElectricity
hpxml.heat_pumps[0].backup_heating_efficiency_afue = 1.0
- elsif ['base-hvac-install-quality-all-air-to-air-heat-pump-1-speed.xml',
- 'base-hvac-install-quality-all-air-to-air-heat-pump-2-speed.xml',
- 'base-hvac-install-quality-all-air-to-air-heat-pump-var-speed.xml',
- 'base-hvac-install-quality-all-mini-split-heat-pump-ducted.xml',
- 'base-hvac-install-quality-all-ground-to-air-heat-pump.xml'].include? hpxml_file
+ elsif ['base-hvac-install-quality-air-to-air-heat-pump-1-speed.xml',
+ 'base-hvac-install-quality-air-to-air-heat-pump-2-speed.xml',
+ 'base-hvac-install-quality-air-to-air-heat-pump-var-speed.xml',
+ 'base-hvac-install-quality-mini-split-heat-pump-ducted.xml',
+ 'base-hvac-install-quality-ground-to-air-heat-pump.xml'].include? hpxml_file
hpxml.heat_pumps[0].airflow_defect_ratio = -0.25
hpxml.heat_pumps[0].fan_watts_per_cfm = 0.365
- if hpxml_file != 'base-hvac-install-quality-all-ground-to-air-heat-pump.xml'
- hpxml.heat_pumps[0].charge_defect_ratio = -0.25
- else
- hpxml.heat_pumps[0].charge_defect_ratio = 0.0
- end
+ hpxml.heat_pumps[0].charge_defect_ratio = -0.25
elsif hpxml_file.include?('base-hvac-autosize') && (not hpxml.heat_pumps.nil?) && (hpxml.heat_pumps.size > 0)
hpxml.heat_pumps[0].cooling_capacity = nil
hpxml.heat_pumps[0].heating_capacity = nil
@@ -3766,7 +3862,6 @@ def set_hpxml_hvac_distributions(hpxml_file, hpxml)
duct_location: HPXML::LocationRoofDeck,
duct_surface_area: 50)
elsif ['base-enclosure-2stories.xml'].include? hpxml_file
- elsif ['base-enclosure-2stories-garage.xml'].include? hpxml_file
hpxml.hvac_distributions[0].ducts << hpxml.hvac_distributions[0].ducts[0].dup
hpxml.hvac_distributions[0].ducts << hpxml.hvac_distributions[0].ducts[1].dup
hpxml.hvac_distributions[0].ducts[0].duct_surface_area *= 0.75
@@ -3840,6 +3935,13 @@ def set_hpxml_hvac_distributions(hpxml_file, hpxml)
duct_insulation_r_value: 0,
duct_location: HPXML::LocationAtticUnvented,
duct_surface_area: 50)
+ elsif ['base-hvac-ducts-area-fractions.xml'].include? hpxml_file
+ hpxml.hvac_distributions[0].ducts.each do |d|
+ d.duct_fraction_area = d.duct_surface_area / hpxml.hvac_distributions[0].ducts.select { |du| du.duct_type == d.duct_type }.map { |du| du.duct_surface_area }.sum
+ end
+ hpxml.hvac_distributions[0].ducts.each do |d|
+ d.duct_surface_area = nil
+ end
elsif ['base-misc-defaults.xml'].include? hpxml_file
hpxml.hvac_distributions.each do |hvac_distribution|
next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
@@ -3849,12 +3951,22 @@ def set_hpxml_hvac_distributions(hpxml_file, hpxml)
duct.duct_location = nil
end
end
+ elsif ['invalid_files/invalid-duct-area-fractions.xml'].include? hpxml_file
+ hpxml.hvac_distributions[0].ducts.each do |d|
+ d.duct_fraction_area -= 0.1
+ end
elsif ['invalid_files/missing-duct-location.xml'].include? hpxml_file
hpxml.hvac_distributions.each do |hvac_distribution|
next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
hvac_distribution.ducts[1].duct_location = nil
end
+ elsif ['invalid_files/missing-duct-area.xml'].include? hpxml_file
+ hpxml.hvac_distributions.each do |hvac_distribution|
+ next unless hvac_distribution.distribution_system_type == HPXML::HVACDistributionTypeAir
+
+ hvac_distribution.ducts[1].duct_surface_area = nil
+ end
elsif ['invalid_files/multifamily-reference-duct.xml'].include? hpxml_file
hpxml.hvac_distributions[0].ducts[0].duct_location = HPXML::LocationOtherMultifamilyBufferSpace
elsif ['invalid_files/multiple-shared-cooling-systems.xml',
@@ -4002,6 +4114,10 @@ def set_hpxml_ventilation_fans(hpxml_file, hpxml)
start_hour: 7,
used_for_local_ventilation: true)
elsif ['base-misc-defaults.xml'].include? hpxml_file
+ hpxml.ventilation_fans.add(id: 'MechanicalVentilation',
+ fan_type: HPXML::MechVentTypeExhaust,
+ tested_flow_rate: 110,
+ used_for_whole_building_ventilation: true)
hpxml.ventilation_fans.add(id: 'KitchenRangeFan',
fan_location: HPXML::LocationKitchen,
used_for_local_ventilation: true)
@@ -4291,27 +4407,27 @@ def set_hpxml_water_heating_systems(hpxml_file, hpxml)
hpxml.water_heating_systems[0].fuel_type = HPXML::FuelTypePropane
end
elsif ['base-dhw-tank-elec-uef.xml'].include? hpxml_file
- # Based on Richmond model number 6ESB30-2 in AHR directory
hpxml.water_heating_systems[0].energy_factor = nil
hpxml.water_heating_systems[0].uniform_energy_factor = 0.93
- hpxml.water_heating_systems[0].first_hour_rating = 46.0
+ hpxml.water_heating_systems[0].usage_bin = HPXML::WaterHeaterUsageBinLow
hpxml.water_heating_systems[0].tank_volume = 30.0
hpxml.water_heating_systems[0].heating_capacity = 15354.0 # 4.5 kW
elsif ['base-dhw-tank-gas-uef.xml'].include? hpxml_file
- # Based on AO Smith model number G6-MH3030NV 400 in AHRI directory
hpxml.water_heating_systems[0].fuel_type = HPXML::FuelTypeNaturalGas
hpxml.water_heating_systems[0].energy_factor = nil
hpxml.water_heating_systems[0].uniform_energy_factor = 0.59
- hpxml.water_heating_systems[0].first_hour_rating = 56.0
+ hpxml.water_heating_systems[0].usage_bin = HPXML::WaterHeaterUsageBinMedium
hpxml.water_heating_systems[0].tank_volume = 30.0
hpxml.water_heating_systems[0].heating_capacity = 30000.0
hpxml.water_heating_systems[0].recovery_efficiency = 0.75
+ elsif ['base-dhw-tank-gas-uef-fhr.xml'].include? hpxml_file
+ hpxml.water_heating_systems[0].first_hour_rating = 56.0
+ hpxml.water_heating_systems[0].usage_bin = nil
elsif ['base-dhw-tank-heat-pump-uef.xml'].include? hpxml_file
- # Based on Rheem model number XE40T10HS45U0 from AHRI directory
hpxml.water_heating_systems[0].water_heater_type = HPXML::WaterHeaterTypeHeatPump
hpxml.water_heating_systems[0].energy_factor = nil
hpxml.water_heating_systems[0].uniform_energy_factor = 3.75
- hpxml.water_heating_systems[0].first_hour_rating = 60.0
+ hpxml.water_heating_systems[0].usage_bin = HPXML::WaterHeaterUsageBinMedium
hpxml.water_heating_systems[0].tank_volume = 50.0
elsif ['base-dhw-tankless-gas-uef.xml'].include? hpxml_file
hpxml.water_heating_systems[0].water_heater_type = HPXML::WaterHeaterTypeTankless
@@ -4418,6 +4534,10 @@ def set_hpxml_water_heating_systems(hpxml_file, hpxml)
hpxml.water_heating_systems[0].heating_capacity = nil
hpxml.water_heating_systems[0].tank_volume = nil
hpxml.water_heating_systems[0].recovery_efficiency = nil
+ hpxml.water_heating_systems[0].energy_factor = nil
+ hpxml.water_heating_systems[0].year_installed = 2009
+ hpxml.water_heating_systems[0].usage_bin = nil
+ hpxml.water_heating_systems[0].first_hour_rating = nil
elsif ['base-bldgtype-multifamily-shared-water-heater.xml',
'base-bldgtype-multifamily-shared-laundry-room.xml'].include? hpxml_file
hpxml.water_heating_systems.clear
@@ -5573,6 +5693,9 @@ def display_usage(command_list)
ENV['HOME'] = 'C:' if !ENV['HOME'].nil? && ENV['HOME'].start_with?('U:')
ENV['HOMEDRIVE'] = 'C:\\' if !ENV['HOMEDRIVE'].nil? && ENV['HOMEDRIVE'].start_with?('U:')
+ require 'oga'
+ require_relative 'HPXMLtoOpenStudio/resources/xmlhelper'
+
# Create sample/test HPXMLs
hpxml_docs = create_hpxmls()
@@ -5583,7 +5706,7 @@ def display_usage(command_list)
# Apply rubocop
cops = ['Layout',
'Lint/DeprecatedClassMethods',
- # 'Lint/RedundantStringCoercion', # Enable when rubocop is upgraded
+ 'Lint/RedundantStringCoercion',
'Style/AndOr',
'Style/FrozenStringLiteralComment',
'Style/HashSyntax',
@@ -5603,9 +5726,34 @@ def display_usage(command_list)
system(command)
# Update measures XMLs
- command = "#{OpenStudio.getOpenStudioCLI} measure -t '#{File.dirname(__FILE__)}'"
puts 'Updating measure.xmls...'
- system(command, [:out, :err] => File::NULL)
+ Dir['**/measure.xml'].each do |measure_xml|
+ for n_attempt in 1..5 # For some reason CLI randomly generates errors, so try multiple times; FIXME: Fix CLI so this doesn't happen
+ measure_dir = File.dirname(measure_xml)
+ command = "#{OpenStudio.getOpenStudioCLI} measure -u '#{measure_dir}'"
+ system(command, [:out, :err] => File::NULL)
+
+ # Check for error
+ xml_doc = XMLHelper.parse_file(measure_xml)
+ err_val = XMLHelper.get_value(xml_doc, '/measure/error', :string)
+ if err_val.nil?
+ err_val = XMLHelper.get_value(xml_doc, '/error', :string)
+ end
+ if err_val.nil?
+ break # Successfully updated
+ else
+ if n_attempt == 5
+ fail "#{measure_xml}: #{err_val}" # Error generated all 5 times, fail
+ else
+ # Remove error from measure XML, try again
+ new_lines = File.readlines(measure_xml).select { |l| !l.include?('') }
+ File.open(measure_xml, 'w') do |file|
+ file.puts new_lines
+ end
+ end
+ end
+ end
+ end
puts 'Done.'
end
diff --git a/workflow/run_simulation.rb b/workflow/run_simulation.rb
index 5cc09fdee9..d1ed1998b0 100644
--- a/workflow/run_simulation.rb
+++ b/workflow/run_simulation.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-$VERBOSE = nil # Prevents ruby warnings, see https://github.com/NREL/OpenStudio/issues/4301
-
start_time = Time.now
require 'fileutils'
diff --git a/workflow/sample_files/base-appliances-coal.xml b/workflow/sample_files/base-appliances-coal.xml
index c467475382..5e32ef9738 100644
--- a/workflow/sample_files/base-appliances-coal.xml
+++ b/workflow/sample_files/base-appliances-coal.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-dehumidifier-ief-portable.xml b/workflow/sample_files/base-appliances-dehumidifier-ief-portable.xml
index bfae66113a..160037d737 100644
--- a/workflow/sample_files/base-appliances-dehumidifier-ief-portable.xml
+++ b/workflow/sample_files/base-appliances-dehumidifier-ief-portable.xml
@@ -94,7 +94,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -118,6 +118,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -142,12 +145,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -242,14 +248,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-dehumidifier-ief-whole-home.xml b/workflow/sample_files/base-appliances-dehumidifier-ief-whole-home.xml
index aafc7a3d87..761a5d08ae 100644
--- a/workflow/sample_files/base-appliances-dehumidifier-ief-whole-home.xml
+++ b/workflow/sample_files/base-appliances-dehumidifier-ief-whole-home.xml
@@ -94,7 +94,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -118,6 +118,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -142,12 +145,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -242,14 +248,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-dehumidifier-multiple.xml b/workflow/sample_files/base-appliances-dehumidifier-multiple.xml
index 68f41ff489..dc19337024 100644
--- a/workflow/sample_files/base-appliances-dehumidifier-multiple.xml
+++ b/workflow/sample_files/base-appliances-dehumidifier-multiple.xml
@@ -94,7 +94,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -118,6 +118,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -142,12 +145,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -242,14 +248,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-dehumidifier.xml b/workflow/sample_files/base-appliances-dehumidifier.xml
index 6a68181772..e649d49822 100644
--- a/workflow/sample_files/base-appliances-dehumidifier.xml
+++ b/workflow/sample_files/base-appliances-dehumidifier.xml
@@ -94,7 +94,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -118,6 +118,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -142,12 +145,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -242,14 +248,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-gas.xml b/workflow/sample_files/base-appliances-gas.xml
index 530344870d..4b86b992a5 100644
--- a/workflow/sample_files/base-appliances-gas.xml
+++ b/workflow/sample_files/base-appliances-gas.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-modified.xml b/workflow/sample_files/base-appliances-modified.xml
index bb3860b865..abf34442f2 100644
--- a/workflow/sample_files/base-appliances-modified.xml
+++ b/workflow/sample_files/base-appliances-modified.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-none.xml b/workflow/sample_files/base-appliances-none.xml
index 18c11a058c..2f06819604 100644
--- a/workflow/sample_files/base-appliances-none.xml
+++ b/workflow/sample_files/base-appliances-none.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-oil.xml b/workflow/sample_files/base-appliances-oil.xml
index d5c1d7de50..6941bbe148 100644
--- a/workflow/sample_files/base-appliances-oil.xml
+++ b/workflow/sample_files/base-appliances-oil.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-propane.xml b/workflow/sample_files/base-appliances-propane.xml
index ac6769e321..0192d80d0f 100644
--- a/workflow/sample_files/base-appliances-propane.xml
+++ b/workflow/sample_files/base-appliances-propane.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-appliances-wood.xml b/workflow/sample_files/base-appliances-wood.xml
index b7ef280e1a..7aaebd7897 100644
--- a/workflow/sample_files/base-appliances-wood.xml
+++ b/workflow/sample_files/base-appliances-wood.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-cathedral.xml b/workflow/sample_files/base-atticroof-cathedral.xml
index 31a8511333..c70b824623 100644
--- a/workflow/sample_files/base-atticroof-cathedral.xml
+++ b/workflow/sample_files/base-atticroof-cathedral.xml
@@ -93,10 +93,13 @@
living space
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
+
+ gypsum board
+
6.0
false
@@ -132,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -148,6 +154,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -163,6 +172,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -291,14 +303,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-conditioned.xml b/workflow/sample_files/base-atticroof-conditioned.xml
index 2e4ec9baee..fb812b7121 100644
--- a/workflow/sample_files/base-atticroof-conditioned.xml
+++ b/workflow/sample_files/base-atticroof-conditioned.xml
@@ -108,6 +108,9 @@
asphalt or fiberglass shingles
0.7
0.92
+
+ gypsum board
+
6.0
false
@@ -157,6 +160,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -172,6 +178,9 @@
316.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -188,6 +197,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
22.3
@@ -219,6 +231,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -242,12 +257,15 @@
-
+
attic - unvented
living space
450.0
+
+ gypsum board
+
-
+
39.3
@@ -359,14 +377,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-flat.xml b/workflow/sample_files/base-atticroof-flat.xml
index 24cf5e0e28..d44e933d0e 100644
--- a/workflow/sample_files/base-atticroof-flat.xml
+++ b/workflow/sample_files/base-atticroof-flat.xml
@@ -97,6 +97,9 @@
asphalt or fiberglass shingles
0.7
0.92
+
+ gypsum board
+
0.0
false
@@ -132,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -147,6 +153,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -257,14 +266,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-radiant-barrier.xml b/workflow/sample_files/base-atticroof-radiant-barrier.xml
index 0f5efe2a3f..072aa384fe 100644
--- a/workflow/sample_files/base-atticroof-radiant-barrier.xml
+++ b/workflow/sample_files/base-atticroof-radiant-barrier.xml
@@ -94,7 +94,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -119,6 +119,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -143,12 +146,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -243,14 +249,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml b/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml
index 2304a69667..f90e7d5556 100644
--- a/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml
+++ b/workflow/sample_files/base-atticroof-unvented-insulated-roof.xml
@@ -96,7 +96,7 @@
attic - unvented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -135,6 +135,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -166,6 +169,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -189,12 +195,15 @@
-
+
attic - unvented
living space
1350.0
+
+ gypsum board
+
-
+
2.1
@@ -288,14 +297,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-atticroof-vented.xml b/workflow/sample_files/base-atticroof-vented.xml
index 085207b556..39cb3f9530 100644
--- a/workflow/sample_files/base-atticroof-vented.xml
+++ b/workflow/sample_files/base-atticroof-vented.xml
@@ -99,7 +99,7 @@
attic - vented
- 1510.0
+ 1509.3
asphalt or fiberglass shingles
0.7
0.92
@@ -138,6 +138,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -169,6 +172,9 @@
1200.0
8.0
7.0
+
+ gypsum board
+
@@ -192,12 +198,15 @@
-
+
attic - vented
living space
1350.0
+
+ gypsum board
+
-
+
39.3
@@ -291,14 +300,14 @@
- 40.0
+ 20.0
0
4.4
- 40.0
+ 20.0
180
4.4
diff --git a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml
index 31dad685d5..7fe4a2afcf 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multifamily-buffer-space.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -106,12 +112,12 @@
-
+
other multifamily buffer space
living space
900.0
-
+
18.7
@@ -119,12 +125,15 @@
-
+
other multifamily buffer space
living space
900.0
+
+ gypsum board
+
-
+
18.7
diff --git a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multiple.xml b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multiple.xml
index e81d9e4b39..0ae57068a6 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multiple.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-multiple.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
100.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -113,6 +119,9 @@
100.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -128,6 +137,9 @@
100.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -143,6 +155,9 @@
100.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -151,12 +166,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml
index 7543d1f71b..0f5972acc8 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-non-freezing-space.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -106,12 +112,12 @@
-
+
other non-freezing space
living space
900.0
-
+
18.7
@@ -119,12 +125,15 @@
-
+
other non-freezing space
living space
900.0
+
+ gypsum board
+
-
+
18.7
diff --git a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-heated-space.xml b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-heated-space.xml
index f2853591e2..41f7965870 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-heated-space.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-heated-space.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
23.0
@@ -106,12 +112,12 @@
-
+
other heated space
living space
900.0
-
+
18.7
@@ -119,12 +125,15 @@
-
+
other heated space
living space
900.0
+
+ gypsum board
+
-
+
18.7
diff --git a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml
index 8ddf7d8ae3..9d2febaed7 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-adjacent-to-other-housing-unit.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml
index a6589b7541..b4f612be2c 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-baseboard.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml
index e2dcd773a2..3c3b1b7516 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil-ducted.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml
index 41bb24337e..20274a8572 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-fan-coil.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml
index ba37551c00..cec11c09f0 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-chiller-water-loop-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml
index d3d246d030..93821f261e 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-cooling-tower-water-loop-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-baseboard.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-baseboard.xml
index fd89eaa5ac..792909d6d5 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-baseboard.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-baseboard.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml
index 58674db9a4..2b488a9580 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-ducted.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml
index 82dd8c066b..bb8123a51b 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil-eae.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml
index 59ab1ebe16..97d7cab3d2 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-fan-coil.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml
index 288dde5510..134ef1a063 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-boiler-only-water-loop-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-baseboard.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-baseboard.xml
index 719d33f7a0..3be05120a7 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-baseboard.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-baseboard.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml
index 020cd5accb..9b2113de2f 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil-ducted.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml
index 45f227bd11..7d560c8042 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-fan-coil.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml
index 6ee7cf4feb..0de7312903 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-chiller-only-water-loop-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml
index d71f9e71a1..ac167572e9 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-cooling-tower-only-water-loop-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-generator.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-generator.xml
index f2ebc0ddd8..6569c7bbe9 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-generator.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-generator.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml
index 81c21f12e0..89d0794adf 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-ground-loop-ground-to-air-heat-pump.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-laundry-room.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-laundry-room.xml
index 6db5209935..0164bf1012 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-laundry-room.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-laundry-room.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-multiple.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-multiple.xml
index af13966c36..5dc5248925 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-multiple.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-multiple.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-preconditioning.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-preconditioning.xml
index 6585641805..86e1e2a6b4 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-preconditioning.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent-preconditioning.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent.xml
index 3fa542ad88..59a8536d84 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-mechvent.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-pv.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-pv.xml
index c89f8423dc..0a0317621d 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-pv.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-pv.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater-recirc.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater-recirc.xml
index 8b6900e154..a5520af6a1 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater-recirc.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater-recirc.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater.xml b/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater.xml
index 5242ea56d1..7e6218189e 100644
--- a/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily-shared-water-heater.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@
-
+
other housing unit
living space
900.0
-
+
2.1
@@ -119,12 +125,15 @@
-
+
other housing unit
living space
900.0
+
+ gypsum board
+
-
+
2.1
diff --git a/workflow/sample_files/base-bldgtype-multifamily.xml b/workflow/sample_files/base-bldgtype-multifamily.xml
index cb060b39cb..4fa4026ce8 100644
--- a/workflow/sample_files/base-bldgtype-multifamily.xml
+++ b/workflow/sample_files/base-bldgtype-multifamily.xml
@@ -83,6 +83,9 @@
wood siding
0.7
0.92
+
+ gypsum board
+
23.0
@@ -98,6 +101,9 @@
294.0
0.7
0.92
+
+ gypsum board
+
4.0
@@ -106,12 +112,12 @@