-
Notifications
You must be signed in to change notification settings - Fork 2
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
Adding array(s) of (varied-size) sub surfaces #11
Conversation
lib/osut/utils.rb
Outdated
# @param surface [OpenStudio::Model::PlanarSurface] a surface | ||
# | ||
# @return [Bool] true if valid surface | ||
def valid(surface = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A clone of TBD's validate - to be deprecated within TBD (in favour of OSut's valid?
... note: add question mark).
lib/osut/utils.rb
Outdated
sub[:multiplier] = 1 unless sub.key?(:multiplier) | ||
sub[:centerline] = 1.0 unless sub.key?(:centerline) | ||
sub[:offset ] = 3.0 unless sub.key?(:offset ) | ||
sub[:ratio ] = 40 unless sub.key?(:ratio ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention is to support multiple options when inserting sub surfaces, e.g. simple a 40% FWR band, arrays of regularly-spaced windows, totally customized insertions (e.g. multiple, custom-sized windows & doors, with unique anchor points).
it "checks subsurface insertions on tilted surfaces" do | ||
# Examples of how to harness OpenStudio's Boost geometry methods to safely | ||
# insert subsurfaces along rotated/tilted/slanted host/parent/base | ||
# surfaces. First step, modify SEB.osm model. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# At this point, "head", "sill" and/or "height" have been tentatively | ||
# validated (and/or have been corrected) independently from one another. | ||
# Log/reset "head" & "sill" heights if conflicting. | ||
if sub.key?(:head) && sub.key?(:sill) && sub[:head] < sub[:sill] + glass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An example of one of many validation checks of user-set arguments. There are several options offered to users, e.g. sub surface (ww) ratio, height, width, head, sill, spacing (if an array of sub surfaces), and hence many possible conflicts. Most of the code in addSubs is a (longish), sequential series of validation checks. In many cases, the method resets conflicting input (while logging warnings). In other instances, it skips over an invalid combo of user arguments (while logging errors). This may be broken down into more than one method in the future ... maybe.
spec/osut_tests_spec.rb
Outdated
@@ -1545,5 +1545,13 @@ module M | |||
expect(mod1.reset(DBG)).to eq(DBG) | |||
expect(mod1.level).to eq(DBG) | |||
expect(mod1.clean!).to eq(DBG) | |||
|
|||
subs = [] | |||
subs << {height: 0.2, width: 0.2} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most basic (minimal) call to addSubs (all other arguments are defaulted). This generates the tiny, illustrated 8" x 8" side window. All EnergyPlus checks pass. Simulation runs are good.
The method also allows users to request a WWR-calculated sub surface addition, or instead an array of equally-sized sub surfaces. The method can be run on the same base surface over and over, without deleting previously-added sub surfaces, e.g. adding a corner door AFTER adding a WWR-calculated horizontal window band, adding a transom window above a door (or vice versa). A LOT more testing needs to be completed before merging ...
expect(mod1.addSubs(model, roof, [sub], false)).to be(true) | ||
expect(mod1.warn?).to be(true) | ||
expect(mod1.logs.size).to eq(1) | ||
message = "' sill height to 0.005 m (OSut::addSubs)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spec/osut_tests_spec.rb
Outdated
expect(sub.key?(:head)).to be(false) | ||
sub[:sill] = 0.0 # will be reset to 5mm | ||
sub[:type] = "Skylight" | ||
expect(mod1.addSubs(model, roof, [sub], false)).to be(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General approach to using the method:
- same sub surface Hash may be reused from one base surface to another (ensuring consistency)
- Hash key:value pairs may be deleted or added, as needed
- some key:value pairs are safe to default
# meaning 100mm between w1, w2, t1 vs t2 vertices. In addition, all 4x | ||
# openings (grouped together) should align towards the left of wall4, | ||
# leaving a 200mm gap between the left vertical wall edge and the left | ||
# frame jamb edge of w1 & t1. First initialize Frame & Divider object. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests/demos:
- head/sill alignment of new sub surface with those of an existing one (e.g. bottom wwr% strip)
- recovery of OSut default head/sill (if missing), e.g. top wwr% strip
- left/right offset of 4x grouped sub surfaces (from base surface centreline)
- frame & divider enabled (4x grouped sub surfaces)
- E+ simulations (no related warnings or errors)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty cool!
# | ||
# @return [Bool] true if successful (check for logged messages if failures) | ||
def addSubs(model = nil, s = nil, subs = [], clear = false) | ||
def addSubs(model = nil, s = nil, subs = [], clear = false, bfr = 0.005) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now an option (i.e. not hardwired).
@@ -1449,6 +1449,9 @@ def overlaps?(p1 = nil, p2 = nil, id1 = "", id2 = "") | |||
area = area.get | |||
return false if area < TOL | |||
|
|||
delta = (area - area1 - area2).abs | |||
return false if delta < TOL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Big oversight: overlaps?
previously returned true if a successful union of both polygons had a valid area ... without checking if the area simply equaled the sum of both individual polygon areas (i.e. 2x side-by-side polygons). This oversight should have been caught in this TBD test: a more detailed look revealed that both tested polygons were a fraction of a mm from aligning, which failed to trigger a false positive. This is only an issue for users aligning subsurfaces (with or without frame÷rs).
fr = 0 if fd.empty? | ||
fr = fd.get.frameWidth unless fd.empty? | ||
vk = sb.vertices | ||
vk = offset(vk, fr, 300) if fr > 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to offset subsurface vertices if frame÷r-enabled. Mea culpa.
# sub[:offset ] # if array (+ m) | ||
# sub[:centreline] # left or right of base surface centreline (+/- m) | ||
# sub[:r_buffer ] # buffer between sub/array and right-side corner (+ m) | ||
# sub[:l_buffer ] # buffer between sub/array and left-side corner (+ m) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2x new options, in response to this desired feature. Left/right buffers are distances (in m, always positive numbers) from either left or right edges of the base surface (e.g. wall corners). Also frame÷r-enabled; the buffers are between e.g. a glazing jamb and either wall corner, not between rough opening jambs and wall corner.
w = area / h | ||
width = w - frames | ||
x0 = centre - w/2 | ||
xf = centre + w/2 | ||
|
||
if sub.key?(:l_buffer) | ||
if sub.key?(:centreline) | ||
log(WRN, "Skip #{id} left buffer (vs centreline) (#{mth})") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute :centreline has precedence over either left or right buffer attributes. If both left and right buffers are requested by the user, left is favoured over right.
a7[:sill ] = sub6_min | ||
a7[:width ] = a7[:head ] - a7[:sill] | ||
a7[:offset ] = a7[:width] + gap | ||
a7[:r_buffer ] = gap |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests left/right buffer-alignment (instead of centred or off-centred) of 5x ~square-shaped windows, in the 2x (fairly narrow) walls in the centre of the Figure:
- 1x array of 2x windows added to the left wall ("right-aligned")
- 1x array of 3x windows added to the right wall ("left-aligned)
A "gap" (200mm or 8") separates the glazing areas between each other, and between the left (or right) wall corner and the nearest window glazing edge. EnergyPlus simulations run fine (no related warnings/errors).
No description provided.