-
Notifications
You must be signed in to change notification settings - Fork 2
Tweaks 'genConstruction' (tested) #22
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 from 1 commit
0114e28
0c41d04
4394d0c
3f315a0
fa96a39
5b9a052
7c289b3
6ec6ce8
aab9a57
c53fe28
a1a8612
699d8aa
b462885
ba28585
f2d5b55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -220,13 +220,14 @@ def genConstruction(model = nil, specs = {}) | |
| chk = @@uo.keys.include?(specs[:type]) | ||
| return invalid("surface type", mth, 2, ERR) unless chk | ||
|
|
||
| specs[:uo] = @@uo[ specs[:type] ] unless specs.key?(:uo) | ||
| specs[:uo] = @@uo[ specs[:type] ] unless specs.key?(:uo) # can be nil | ||
| u = specs[:uo] | ||
|
|
||
| if u | ||
| return mismatch("#{id} Uo", u, Numeric, mth) unless u.is_a?(Numeric) | ||
| return invalid("#{id} Uo (> 5.678)", mth, 2, ERR) if u > 5.678 | ||
| return negative("#{id} Uo" , mth, ERR) if u < 0 | ||
| return mismatch("#{id} Uo", u, Numeric, mth) unless u.is_a?(Numeric) | ||
| return invalid("#{id} Uo (> 5.678)", mth, 2, ERR) if u > 5.678 | ||
| return zero("#{id} Uo", mth, ERR) if u.round(2) == 0.00 | ||
| return negative("#{id} Uo", mth, ERR) if u < 0 | ||
| end | ||
|
|
||
| # Optional specs. Log/reset if invalid. | ||
|
|
@@ -466,14 +467,14 @@ def genConstruction(model = nil, specs = {}) | |
| a[:compo ][:d ] = d | ||
| a[:compo ][:id ] = "OSut|#{mt}|#{format('%03d', d*1000)[-3..-1]}" | ||
| when :window | ||
| a[:glazing][:u ] = specs[:uo ] | ||
| a[:glazing][:u ] = u ? u : @@uo[:window] | ||
| a[:glazing][:shgc] = 0.450 | ||
| a[:glazing][:shgc] = specs[:shgc] if specs.key?(:shgc) | ||
| a[:glazing][:id ] = "OSut|window" | ||
| a[:glazing][:id ] += "|U#{format('%.1f', a[:glazing][:u])}" | ||
| a[:glazing][:id ] += "|SHGC#{format('%d', a[:glazing][:shgc]*100)}" | ||
| when :skylight | ||
| a[:glazing][:u ] = specs[:uo ] | ||
| a[:glazing][:u ] = u ? u : @@uo[:skylight] | ||
| a[:glazing][:shgc] = 0.450 | ||
| a[:glazing][:shgc] = specs[:shgc] if specs.key?(:shgc) | ||
| a[:glazing][:id ] = "OSut|skylight" | ||
|
|
@@ -482,25 +483,11 @@ def genConstruction(model = nil, specs = {}) | |
| end | ||
|
|
||
| # Initiate layers. | ||
| glazed = true | ||
| glazed = false if a[:glazing].empty? | ||
| layers = OpenStudio::Model::OpaqueMaterialVector.new unless glazed | ||
| layers = OpenStudio::Model::FenestrationMaterialVector.new if glazed | ||
| unglazed = a[:glazing].empty? ? true : false | ||
|
|
||
| if glazed | ||
| u = a[:glazing][:u ] | ||
| shgc = a[:glazing][:shgc] | ||
| lyr = model.getSimpleGlazingByName(a[:glazing][:id]) | ||
|
|
||
| if lyr.empty? | ||
| lyr = OpenStudio::Model::SimpleGlazing.new(model, u, shgc) | ||
| lyr.setName(a[:glazing][:id]) | ||
| else | ||
| lyr = lyr.get | ||
| end | ||
| if unglazed | ||
| layers = OpenStudio::Model::OpaqueMaterialVector.new | ||
|
|
||
| layers << lyr | ||
| else | ||
| # Loop through each layer spec, and generate construction. | ||
| a.each do |i, l| | ||
| next if l.empty? | ||
|
|
@@ -524,44 +511,68 @@ def genConstruction(model = nil, specs = {}) | |
|
|
||
| layers << lyr | ||
| end | ||
| else | ||
| layers = OpenStudio::Model::FenestrationMaterialVector.new | ||
|
|
||
| u0 = a[:glazing][:u ] | ||
| shgc = a[:glazing][:shgc] | ||
| lyr = model.getSimpleGlazingByName(a[:glazing][:id]) | ||
|
|
||
| if lyr.empty? | ||
| lyr = OpenStudio::Model::SimpleGlazing.new(model, u0, shgc) | ||
| lyr.setName(a[:glazing][:id]) | ||
| else | ||
| lyr = lyr.get | ||
| end | ||
|
|
||
| layers << lyr | ||
| end | ||
|
|
||
| c = OpenStudio::Model::Construction.new(layers) | ||
| c.setName(id) | ||
|
|
||
| # Adjust insulating layer thickness or conductivity to match requested Uo. | ||
| unless glazed | ||
| ro = 0 | ||
| ro = 1 / specs[:uo] - @@film[ specs[:type] ] if specs[:uo] | ||
|
|
||
| if specs[:type] == :door # 1x layer, adjust conductivity | ||
| layer = c.getLayer(0).to_StandardOpaqueMaterial | ||
| return invalid("#{id} standard material?", mth, 0) if layer.empty? | ||
|
|
||
| layer = layer.get | ||
| k = layer.thickness / ro | ||
| layer.setConductivity(k) | ||
| elsif ro > 0 # multiple layers, adjust insulating layer thickness | ||
| lyr = insulatingLayer(c) | ||
| return invalid("#{id} construction", mth, 0) if lyr[:index].nil? | ||
| return invalid("#{id} construction", mth, 0) if lyr[:type ].nil? | ||
| return invalid("#{id} construction", mth, 0) if lyr[:r ].zero? | ||
|
|
||
| index = lyr[:index] | ||
| layer = c.getLayer(index).to_StandardOpaqueMaterial | ||
| return invalid("#{id} material @#{index}", mth, 0) if layer.empty? | ||
|
|
||
| layer = layer.get | ||
| k = layer.conductivity | ||
| d = (ro - rsi(c) + lyr[:r]) * k | ||
| return invalid("#{id} adjusted m", mth, 0) if d < 0.03 | ||
|
|
||
| nom = "OSut|" | ||
| nom += layer.nameString.gsub(/[^a-z]/i, "").gsub("OSut", "") | ||
| nom += "|" | ||
| nom += format("%03d", d*1000)[-3..-1] | ||
| layer.setName(nom) if model.getStandardOpaqueMaterialByName(nom).empty? | ||
| layer.setThickness(d) | ||
| if u and unglazed | ||
| ro = 1 / u - film | ||
|
|
||
| if ro > 0 | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For opaque construction, adjusting insulating layer thickness (to meet a requested assembly Uo factor) is skipped entirely if the requested Uo isn't:
|
||
| if specs[:type] == :door # 1x layer, adjust conductivity | ||
| layer = c.getLayer(0).to_StandardOpaqueMaterial | ||
| return invalid("#{id} standard material?", mth, 0) if layer.empty? | ||
|
|
||
| layer = layer.get | ||
| k = layer.thickness / ro | ||
| layer.setConductivity(k) | ||
| else # multiple layers, adjust insulating layer thickness | ||
| lyr = insulatingLayer(c) | ||
| return invalid("#{id} construction", mth, 0) if lyr[:index].nil? | ||
| return invalid("#{id} construction", mth, 0) if lyr[:type ].nil? | ||
| return invalid("#{id} construction", mth, 0) if lyr[:r ].zero? | ||
|
|
||
| index = lyr[:index] | ||
| layer = c.getLayer(index).to_StandardOpaqueMaterial | ||
| return invalid("#{id} material @#{index}", mth, 0) if layer.empty? | ||
|
|
||
| layer = layer.get | ||
| k = layer.conductivity | ||
| d = (ro - rsi(c) + lyr[:r]) * k | ||
| return invalid("#{id} adjusted m", mth, 0) if d < 0.03 | ||
|
|
||
| nom = "OSut|" | ||
| nom += layer.nameString.gsub(/[^a-z]/i, "").gsub("OSut", "") | ||
| nom += "|" | ||
| nom += format("%03d", d*1000)[-3..-1] | ||
|
|
||
| lyr = model.getStandardOpaqueMaterialByName(nom) | ||
|
|
||
| if lyr.empty? | ||
| layer.setName(nom) | ||
| layer.setThickness(d) | ||
| else | ||
| omat = lyr.get | ||
| c.setLayer(index, omat) | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
|
|
@@ -746,7 +757,7 @@ def genMass(sps = OpenStudio::Model::SpaceVector.new, ratio = 2.0) | |
| # Validates if a default construction set holds a base construction. | ||
| # | ||
| # @param set [OpenStudio::Model::DefaultConstructionSet] a default set | ||
| # @param bse [OpensStudio::Model::ConstructionBase] a construction base | ||
| # @param bse [OpenStudio::Model::ConstructionBase] a construction base | ||
| # @param gr [Bool] if ground-facing surface | ||
| # @param ex [Bool] if exterior-facing surface | ||
| # @param tp [#to_s] a surface type | ||
|
|
@@ -1048,7 +1059,7 @@ def insulatingLayer(lc = nil) | |
| return invalid("lc", mth, 1, DBG, res) unless lc.respond_to?(NS) | ||
|
|
||
| id = lc.nameString | ||
| return mismatch(id, lc, cl1, mth, DBG, res) unless lc.is_a?(cl) | ||
| return mismatch(id, lc, cl, mth, DBG, res) unless lc.is_a?(cl) | ||
|
|
||
| lc.layers.each do |m| | ||
| unless m.to_MasslessOpaqueMaterial.empty? | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -291,6 +291,22 @@ | |
| u = 1 / cls1::rsi(surface) | ||
| expect(u).to be_within(TOL).of(uo9) | ||
|
|
||
| # Invalid Uo (here, skylights and windows inherit default Uo values) | ||
| specs = {type: :skylight, uo: nil} | ||
| surface = cls1::genConstruction(model, specs) | ||
| expect(surface).to be_a(OpenStudio::Model::LayeredConstruction) | ||
| expect(surface.layers.size).to eq(1) | ||
| u = 1 / cls1::rsi(surface) | ||
| expect(u).to be_within(TOL).of(uo[:skylight]) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the case of fenestrated assemblies, an invalid Uo request is ignored and the glazing assembly inherits a default OSut Uo (here 3.5 W/m2.K for a skylight). |
||
|
|
||
| # Invalid Uo (here, Uo-adjustments are ignored altogether) | ||
| specs = {type: :wall, uo: nil} | ||
| surface = cls1::genConstruction(model, specs) | ||
| expect(surface).to be_a(OpenStudio::Model::LayeredConstruction) | ||
| expect(surface.layers.size).to eq(4) | ||
| u = 1 / cls1::rsi(surface) | ||
| expect(u).to be_within(TOL).of(2.23) # not matching any defaults | ||
|
|
||
| expect(cls1.status.zero?).to be true | ||
| end | ||
|
|
||
|
|
@@ -790,8 +806,12 @@ | |
| expect(model).to_not be_empty | ||
| model = model.get | ||
|
|
||
| m = "OSut::insulatingLayer" | ||
| m1 = "Invalid 'lc' arg #1 (#{m})" | ||
| m = "OSut::insulatingLayer" | ||
| cl1 = OpenStudio::Model::Surface | ||
| cl2 = OpenStudio::Model::LayeredConstruction | ||
| n1 = "Entryway Wall 1" | ||
| m1 = "Invalid 'lc' arg #1 (#{m})" | ||
| m2 = "'#{n1}' #{cl1}? expecting #{cl2} (#{m})" | ||
|
|
||
| model.getLayeredConstructions.each do |lc| | ||
| lyr = mod1.insulatingLayer(lc) | ||
|
|
@@ -838,7 +858,6 @@ | |
| end | ||
|
|
||
| lyr = mod1.insulatingLayer(nil) | ||
| expect(mod1.debug?).to be true | ||
| expect(lyr[:index]).to be_nil | ||
| expect(lyr[:type ]).to be_nil | ||
| expect(lyr[:r ]).to be_zero | ||
|
|
@@ -848,7 +867,6 @@ | |
|
|
||
| expect(mod1.clean!).to eq(DBG) | ||
| lyr = mod1.insulatingLayer("") | ||
| expect(mod1.debug?).to be true | ||
| expect(lyr[:index]).to be_nil | ||
| expect(lyr[:type ]).to be_nil | ||
| expect(lyr[:r ]).to be_zero | ||
|
|
@@ -858,13 +876,25 @@ | |
|
|
||
| expect(mod1.clean!).to eq(DBG) | ||
| lyr = mod1.insulatingLayer(model) | ||
| expect(mod1.debug?).to be true | ||
| expect(lyr[:index]).to be_nil | ||
| expect(lyr[:type ]).to be_nil | ||
| expect(lyr[:r ]).to be_zero | ||
| expect(mod1.debug?).to be true | ||
| expect(mod1.logs.size).to eq(1) | ||
| expect(mod1.logs.first[:message]).to eq(m1) | ||
|
|
||
| eWall1 = model.getSurfaceByName(n1) | ||
| expect(eWall1).to_not be_empty | ||
| eWall1 = eWall1.get | ||
|
|
||
| expect(mod1.clean!).to eq(DBG) | ||
| lyr = mod1.insulatingLayer(eWall1) | ||
| expect(lyr[:index]).to be_nil | ||
| expect(lyr[:type ]).to be_nil | ||
| expect(lyr[:r ]).to be_zero | ||
| expect(mod1.debug?).to be true | ||
| expect(mod1.logs.size).to eq(1) | ||
| expect(mod1.logs.first[:message]).to eq(m2) | ||
| end | ||
|
|
||
| it "checks for spandrels" do | ||
|
|
||
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 user could set a glazing assembly's
specs["uo"]to nil. This is caught and reset here.