Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes towards general TBD solution #1

Open
wants to merge 9 commits into
base: nrcan_denis
Choose a base branch
from
19 changes: 11 additions & 8 deletions lib/openstudio-standards/btap/bridging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,9 @@ def initialize(model = nil, argh = {})
combo = "#{perform.to_s}_#{quality.to_s}".to_sym # e.g. :lp_bad
args = {} # initialize native TBD arguments

#
quality = :good if argh.key?(:quality) && argh[:quality] == :good

# If uprating, initialize native TBD args.
[:walls, :floors, :roofs].each do |stypes|
next if @model[stypes].zero?
Expand Down Expand Up @@ -1340,11 +1343,11 @@ def initialize(model = nil, argh = {})
end

if unable
puts # TEMPORARY
puts "¨¨¨ combo : #{combo}"
puts args[:io_path][:psis]
TBD.logs.each { |lg| puts lg }
puts
# puts # TEMPORARY
# puts "¨¨¨ combo : #{combo}"
# puts args[:io_path][:psis]
# TBD.logs.each { |lg| puts lg }
# puts
else
comply = true
end
Expand Down Expand Up @@ -1378,7 +1381,7 @@ def initialize(model = nil, argh = {})
comply = false unless ok
break unless ok

# Check if within range of BTAP commercially options, for:
# Check if within range of BTAP commercially-available options, for:
# - walls, floors & roofs
# - specific to each space type
@model[:sptypes].values.each do |sptype|
Expand Down Expand Up @@ -1438,12 +1441,12 @@ def initialize(model = nil, argh = {})
args.delete(option)
args.delete(ut )

# Reset OpenStudio wall, floor and/or roof Uo factors to minimum
# Yet reset OpenStudio wall, floor and/or roof Uo factors to minimum
# available BTAP (costed) values e.g.:
# - 0.130 for WOOD7
# - 0.080 for STEL2
# - 0.100 for all ROOFS
# TO_DO ...
# TO_DO ... !!!
end

break
Expand Down
61 changes: 29 additions & 32 deletions lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class NECB2011 < Standard
attr_accessor :standards_data
attr_accessor :space_type_map
attr_accessor :space_multiplier_map

# This is a helper method to convert arguments that may support 'NECB_Default, and nils to convert to float'
def convert_arg_to_f(variable:, default:)
return variable if variable.kind_of?(Numeric)
Expand Down Expand Up @@ -230,12 +230,10 @@ def model_create_prototype_model(template:,
output_meters: nil,
airloop_economizer_type: nil,
baseline_system_zones_map_option: nil,
derate: false,
uprate: false)
tbd_option: :none)
model = load_building_type_from_library(building_type: building_type)
return model_apply_standard(model: model,
derate: derate,
uprate: uprate,
tbd_option: :none, # 4x options: (1) :none (TBD is ignored), (2) :poor or (3) :good PSI factors (BTAP-costed), and (4) :uprate (i.e. iterative process)
epw_file: epw_file,
sizing_run_dir: sizing_run_dir,
necb_reference_hp: necb_reference_hp,
Expand Down Expand Up @@ -308,8 +306,7 @@ def load_building_type_from_library(building_type:)
# Created this method so that additional methods can be addded for bulding the prototype model in later
# code versions without modifying the build_protoype_model method or copying it wholesale for a few changes.
def model_apply_standard(model:,
derate: false,
uprate: false,
tbd_option: :none,
epw_file:,
sizing_run_dir: Dir.pwd,
necb_reference_hp: false,
Expand Down Expand Up @@ -377,8 +374,7 @@ def model_apply_standard(model:,
electrical_loads_scale: electrical_loads_scale,
oa_scale: oa_scale)
apply_envelope(model: model,
derate: derate,
uprate: uprate,
tbd_option: :none,
ext_wall_cond: ext_wall_cond,
ext_floor_cond: ext_floor_cond,
ext_roof_cond: ext_roof_cond,
Expand Down Expand Up @@ -514,7 +510,7 @@ def apply_systems_and_efficiencies(model:,
necb_reference_hp: necb_reference_hp, necb_reference_hp_supp_fuel: necb_reference_hp_supp_fuel, baseline_system_zones_map_option: baseline_system_zones_map_option)

# Apply new ECM system. Overwrite standard as required.
ecm.apply_system_ecm(model: model, ecm_system_name: ecm_system_name, template_standard: self, primary_heating_fuel: primary_heating_fuel,
ecm.apply_system_ecm(model: model, ecm_system_name: ecm_system_name, template_standard: self, primary_heating_fuel: primary_heating_fuel,
ecm_system_zones_map_option: ecm_system_zones_map_option)

# -------- Performace, Efficiencies, Controls and Sensors ------------
Expand Down Expand Up @@ -611,8 +607,7 @@ def apply_weather_data(model:, epw_file:)
end

def apply_envelope(model:,
derate: false,
uprate: false,
tbd_option: :none,
ext_wall_cond: nil,
ext_floor_cond: nil,
ext_roof_cond: nil,
Expand Down Expand Up @@ -653,27 +648,29 @@ def apply_envelope(model:,
skylight_solar_trans: skylight_solar_trans)
model_create_thermal_zones(model, @space_multiplier_map)

if derate
unless tbd_option == :none
argh = {} # BTAP/TBD arguments (Uo/Ut factors may be nilled)
argh[:walls ] = { uo: ext_wall_cond }
argh[:floors] = { uo: ext_floor_cond }
argh[:roofs ] = { uo: ext_roof_cond }

if uprate
if tbd_option == :uprate
argh[:walls ][:ut] = ext_wall_cond
argh[:floors][:ut] = ext_floor_cond
argh[:roofs ][:ut] = ext_roof_cond
elsif tbd_option == :poor || tbd_option == :good
argh[:quality] = tbd_option
else
argh[:quality] = :poor
end

tbd = BTAP::Bridging.new(model, argh)
# To-do output to json for costing... - Phylroy
tbd.tally

tbd.feedback[:logs].each do |log|
puts log
end

# tbd.tally

# tbd.feedback[:logs].each do |log|
# puts log
# end

# tbd.feedback ... report (how?) failed attempts (e.g. uprating) to users.
end
Expand Down Expand Up @@ -736,10 +733,10 @@ def apply_kiva_foundation(model)
kiva_settings = model.getFoundationKivaSettings if !model.getFoundationKivas.empty?
end

# check if two surfaces are in contact. For every two consecutive vertices on surface 1,
# loop through two consecutive vertices of surface two. Then check whether the vertices
# of surfaces 2 are on the same line as the vertices from surface 1. If the two vectors
# defined by the two vertices on surface 1 and those on surface 2 overlap, then the two
# check if two surfaces are in contact. For every two consecutive vertices on surface 1,
# loop through two consecutive vertices of surface two. Then check whether the vertices
# of surfaces 2 are on the same line as the vertices from surface 1. If the two vectors
# defined by the two vertices on surface 1 and those on surface 2 overlap, then the two
# surfaces are in contact. If a side from surface 2 is in contact with a side from surface 1,
# the length of the side from surface 2 is limited to the length of the side from surface 1.
# created by: Kamel Haddad ([email protected])
Expand Down Expand Up @@ -779,9 +776,9 @@ def surfaces_are_in_contact?(surf1,surf2)
return surfaces_in_contact
end

# Loop through the layers of the construction of the surface and replace any massless material with
# a standard one. The material used instead is from the EnergyPlus dataset file 'ASHRAE_2005_HOF_Materials.idf'
# with the name: 'Insulation: Expanded polystyrene - extruded (smooth skin surface) (HCFC-142b exp.)'.
# Loop through the layers of the construction of the surface and replace any massless material with
# a standard one. The material used instead is from the EnergyPlus dataset file 'ASHRAE_2005_HOF_Materials.idf'
# with the name: 'Insulation: Expanded polystyrene - extruded (smooth skin surface) (HCFC-142b exp.)'.
# The thickness of the new material is based on the thermal resistance of the massless material it replaces.
# created by: Kamel Haddad ([email protected])
def replace_massless_material_with_std_material(model,surf)
Expand Down Expand Up @@ -820,8 +817,8 @@ def replace_massless_material_with_std_material(model,surf)

end

# Find the exposed perimeter of a floor surface. For each side of the floor loop through
# the walls and find the walls that share sides with the floor. Then sum the lengths of
# Find the exposed perimeter of a floor surface. For each side of the floor loop through
# the walls and find the walls that share sides with the floor. Then sum the lengths of
# the sides of the walls that come in contact with sides of the floor.
# created by: Kamel Haddad ([email protected])
def get_surface_exp_per(floor,walls)
Expand Down Expand Up @@ -856,7 +853,7 @@ def get_surface_exp_per(floor,walls)
vert3 = vert4
end
end
# increment the exposed perimeter of the floor. Limit the length of the walls in contact with the
# increment the exposed perimeter of the floor. Limit the length of the walls in contact with the
# side of the floor to the length of the side of the floor.
floor_exp_per += [walls_exp_per,side_length].min
vert1 = vert2
Expand All @@ -865,7 +862,7 @@ def get_surface_exp_per(floor,walls)
return floor_exp_per
end

# check that three vertices are on the same line. Also check that the vectors
# check that three vertices are on the same line. Also check that the vectors
# from vert1 and vert2 and from vert1 and vert3 are in the same direction.
# created by: Kamel Haddad ([email protected])
def three_vertices_same_line_and_dir?(vert1,vert2,vert3)
Expand Down Expand Up @@ -896,7 +893,7 @@ def three_vertices_same_line_and_dir?(vert1,vert2,vert3)

return same_line_same_dir
end

# Thermal zones need to be set to determine conditioned spaces when applying fdwr and srr limits.
# # fdwr_set/srr_set settings:
# # 0-1: Remove all windows/skylights and add windows/skylights to match this fdwr/srr
Expand Down
116 changes: 56 additions & 60 deletions test/necb/unit_tests/tests/test_NECB_TBD.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def test_necb_tbd()
@expected_results_file = File.join(__dir__, '../expected_results/necb_tbd_expected_results.json')
@test_results_file = File.join(__dir__, '../expected_results/necb_tbd_test_results.json')
@sizing_run_dir = File.join(@output_folder, 'sizing_folder')
@test_results_array = [] # test results storage array

# Intial test condition.
@test_passed = true
Expand Down Expand Up @@ -44,71 +45,66 @@ def test_necb_tbd()

@fuels = ['Electricity']

@derating = [true]

@uprating = [true]

@test_results_array = [] # test results storage array

@templates.sort.each do |template|
@epws.sort.each do |epw |
@buildings.sort.each do |building|
@fuels.sort.each do |fuel |
@derating.each do |derate |
@uprating.each do |uprate |
st = Standard.build(template)
model = st.model_create_prototype_model(template:template,
building_type: building,
derate: derate,
uprate: uprate,
epw_file: epw,
sizing_run_dir: @sizing_run_dir,
primary_heating_fuel: fuel)

puts "TBD ---"

model.getSurfaces.each do |surface|
id = surface.nameString
conditions = surface.outsideBoundaryCondition.downcase
next unless conditions == "outdoors"
lc = surface.construction
puts "WHAT THE? #{id}?" if lc.empty?
next if lc.empty?

lc = lc.get.to_LayeredConstruction
puts "WHAT NOW? #{id}?" if lc.empty?
next if lc.empty?

lc = lc.get
nom = lc.nameString

if surface.isConstructionDefaulted
next if id.downcase.include?("roof") # unconditioned attic
next if derate == false

puts "Hmm ... #{nom} vs #{id}?" # shouldn't happen ...
else
puts "#{nom}: unique to #{id} surface"
next if nom.downcase.include?("c tbd")

puts "Hmmm ... #{nom} vs #{id}?"
end
end

puts "TBD --"

end # @uprating.each do |uprate|
end # @derating.each do |derate |
end # @fuels.sort.each do |fuel |
# Optional PSI factor sets (e.g. optional for pre-NECB2017 templates. If
# :none, neither TBD 'uprating' nor 'derating' calculations (and subsequent
# modifications to generated OpenStudio models) are carried out. If instead
# set to :uprate, psi factor sets are determined iteratively, see:
#
# lib/openstudio-standards/btap/bridging.rb
#
# Otherwise, :bad vs :good PSI factor sets refer to costed BTAP details.
Copy link
Owner Author

Choose a reason for hiding this comment

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

Boils down to a single TBD parameter.

@qualities = [:none, :bad, :good, :uprate]

@templates.sort.each do |template|
@epws.sort.each do |epw |
@buildings.sort.each do |building|
@fuels.sort.each do |fuel |
@qualities.sort.each do |quality |

st = Standard.build(template)
model = st.model_create_prototype_model(template:template,
epw_file: epw,
building_type: building,
primary_heating_fuel: fuel,
tbd_option: quality,
sizing_run_dir: @sizing_run_dir)

model.getSurfaces.each do |surface|
id = surface.nameString
conditions = surface.outsideBoundaryCondition.downcase
next unless conditions == "outdoors"

lc = surface.construction
assert(lc.is_initialized, "Empty #{id} construction")
next unless lc.is_initialized

lc = lc.get.to_LayeredConstruction
assert(lc.is_initialized, "Empty #{id} layered construction")
next unless lc.is_initialized

derated = lc.get.nameString.downcase.include?(" c tbd")
err_msg = "Failed TBD processes for #{template}: #{building}"

assert(derated == false, err_msg) if quality == :none
assert(derated == true, err_msg) unless quality == :none

# Additional assertions could include:
# - which uprated buildings fail to uprate
# - 'assert_in_delta' checks of heat loss from thermal
# bridging for some key, pre-selected surfaces
end

end # @qualities.each do |quality |
end # @fuels.sort.each do |fuel |
end # @buildings.sort.each do |building|
end # @epws.sort.each do |epw |
end # @epws.sort.each do |epw |
end # @templates.sort.each do |template|


# Save test results to file.
File.open(@test_results_file, 'w') do |f|
f.write(JSON.pretty_generate(@test_results_array))
end
# File.open(@test_results_file, 'w') do |f|
# f.write(JSON.pretty_generate(@test_results_array))
# end
end

end