lib/measures/tbd/resources/psi.rb in tbd-3.1.1 vs lib/measures/tbd/resources/psi.rb in tbd-3.2.0
- old
+ new
@@ -1,8 +1,8 @@
# MIT License
#
-# Copyright (c) 2020-2022 Denis Bourgeois & Dan Macumber
+# Copyright (c) 2020-2023 Denis Bourgeois & Dan Macumber
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -911,10 +911,11 @@
return mismatch("model", model, cl, mth, DBG, tbd) unless model.is_a?(cl)
return mismatch("argh", argh, Hash, mth, DBG, tbd) unless argh.is_a?(Hash)
argh = {} if argh.empty?
+ argh[:sub_tol ] = TBD::TOL unless argh.key?(:sub_tol )
argh[:option ] = "" unless argh.key?(:option )
argh[:io_path ] = nil unless argh.key?(:io_path )
argh[:schema_path ] = nil unless argh.key?(:schema_path )
argh[:uprate_walls ] = false unless argh.key?(:uprate_walls )
argh[:uprate_roofs ] = false unless argh.key?(:uprate_roofs )
@@ -1172,13 +1173,10 @@
farther = point_V_magnitude > farthest_V.magnitude
farthest = point if farther
farthest_V = origin_point_V if farther
end
- puts "ADDITION!!" if id == "ADDITION"
- puts "#{reference_V} vs #{farthest_V}" if id == "ADDITION"
-
angle = reference_V.angle(farthest_V)
invalid("#{id} polar angle", mth, 0, ERROR, 0) if angle.nil?
angle = 0 if angle.nil?
adjust = false # adjust angle [180°, 360°] if necessary
@@ -1769,17 +1767,124 @@
edge[:psi][edge[:io_type]] = sh[:val][safer]
end
end
+ # Fetch edge multipliers for subsurfaces, if applicable.
+ edges.values.each do |edge|
+ next if edge.key?(:mult) # skip if already assigned
+ next unless edge.key?(:surfaces)
+ next unless edge.key?(:psi)
+ ok = false
+
+ edge[:psi].keys.each do |k|
+ break if ok
+
+ jamb = k.to_s.include?("jamb")
+ sill = k.to_s.include?("sill")
+ head = k.to_s.include?("head")
+ ok = jamb || sill || head
+ end
+
+ next unless ok # if OK, edge links subsurface(s) ... yet which one(s)?
+
+ edge[:surfaces].each do |id, surface|
+ next unless tbd[:surfaces].key?(id) # look up parent (opaque) surface
+
+ [:windows, :doors, :skylights].each do |subtypes|
+ next unless tbd[:surfaces][id].key?(subtypes)
+
+ tbd[:surfaces][id][subtypes].each do |nom, sub|
+ next unless edge[:surfaces].key?(nom)
+ next unless sub[:mult] > 1
+
+ # An edge may be tagged with (potentially conflicting) multipliers.
+ # This is only possible if the edge links 2 subsurfaces, e.g. a
+ # shared jamb between window & door. By default, TBD tags common
+ # subsurface edges as (mild) "transitions" (i.e. PSI 0 W/K.m), so
+ # there would be no point in assigning an edge multiplier. Users
+ # can however reset an edge type via a TBD JSON input file (e.g.
+ # "joint" instead of "transition"). It would be a very odd choice,
+ # but TBD doesn't prohibit it. If linked subsurfaces have different
+ # multipliers (e.g. 2 vs 3), TBD tracks the highest value.
+ edge[:mult] = sub[:mult] unless edge.key?(:mult)
+ edge[:mult] = sub[:mult] if sub[:mult] > edge[:mult]
+ end
+ end
+ end
+ end
+
+ # Unless a user has set the thermal bridge type of an individual edge via
+ # JSON input, reset any subsurface's head, sill or jamb edges as (mild)
+ # transitions when in close proximity to another subsurface edge. Both
+ # edges' origin and terminal vertices must be in close proximity. Edges
+ # of unhinged subsurfaces are ignored.
+ edges.each do |id, edge|
+ nb = 0 # linked subsurfaces (i.e. "holes")
+ match = false
+ next if edge.key?(:io_type) # skip if set in JSON
+ next unless edge.key?(:v0)
+ next unless edge.key?(:v1)
+ next unless edge.key?(:psi)
+ next unless edge.key?(:surfaces)
+
+ edge[:surfaces].keys.each do |identifier|
+ break if match
+ next unless holes.key?(identifier)
+
+ if holes[identifier].attributes.key?(:unhinged)
+ nb = 0 if holes[identifier].attributes[:unhinged]
+ break if holes[identifier].attributes[:unhinged]
+ end
+
+ nb += 1
+ match = true if nb > 1
+ end
+
+ if nb == 1 # linking 1x subsurface, search for 1x other.
+ e1 = { v0: edge[:v0].point, v1: edge[:v1].point }
+
+ edges.each do |nom, e|
+ nb = 0
+ break if match
+ next if nom == id
+ next if e.key?(:io_type)
+ next unless e.key?(:psi)
+ next unless e.key?(:surfaces)
+
+ e[:surfaces].keys.each do |identifier|
+ next unless holes.key?(identifier)
+
+ if holes[identifier].attributes.key?(:unhinged)
+ nb = 0 if holes[identifier].attributes[:unhinged]
+ break if holes[identifier].attributes[:unhinged]
+ end
+
+ nb += 1
+ end
+
+ next unless nb == 1 # only process edge if linking 1x subsurface
+
+ e2 = { v0: e[:v0].point, v1: e[:v1].point }
+ match = matches?(e1, e2, argh[:sub_tol])
+ end
+ end
+
+ next unless match
+
+ edge[:psi] = { transition: 0.000 }
+ edge[:set] = json[:io][:building][:psi]
+ end
+
# Loop through each edge and assign heat loss to linked surfaces.
edges.each do |identifier, edge|
next unless edge.key?(:psi)
rsi = 0
- max = edge[:psi].values.max
- type = edge[:psi].key(max)
+ max = edge[:psi ].values.max
+ type = edge[:psi ].key(max)
length = edge[:length]
+ length *= edge[:mult ] if edge.key?(:mult)
bridge = { psi: max, type: type, length: length }
deratables = {}
apertures = {}
if edge.key?(:sets) && edge[:sets].key?(type)
@@ -1867,11 +1972,11 @@
# :wall_option
# (same triple arguments for roofs and exposed floors)
# ... first 'uprate' targeted insulation layers (see ua.rb) before derating.
# Check for new argh keys [:wall_uo], [:roof_uo] and/or [:floor_uo].
up = argh[:uprate_walls] || argh[:uprate_roofs] || argh[:uprate_floors]
- uprate(model, tbd[:surfaces], argh) if up
+ uprate(model, tbd[:surfaces], argh) if up
# Derated (cloned) constructions are unique to each deratable surface.
# Unique construction names are prefixed with the surface name,
# and suffixed with " tbd", indicating that the construction is
# henceforth thermally derated. The " tbd" expression is also key in
@@ -1973,9 +2078,10 @@
next unless e.key?(:set)
v = e[:psi].values.max
set = e[:set]
t = e[:psi].key(v)
l = e[:length]
+ l *= e[:mult] if e.key?(:mult)
edge = { psi: set, type: t, length: l, surfaces: e[:surfaces].keys }
edge[:v0x] = e[:v0].point.x
edge[:v0y] = e[:v0].point.y
edge[:v0z] = e[:v0].point.z
edge[:v1x] = e[:v1].point.x