honeybee-openstudio 2.31.8 → 2.31.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/honeybee-openstudio.gemspec +1 -1
- data/lib/from_openstudio/geometry/room.rb +11 -0
- data/lib/from_openstudio/hvac/ideal_air.rb +75 -0
- data/lib/from_openstudio/load/electric_equipment.rb +1 -1
- data/lib/from_openstudio/model.rb +2 -0
- data/lib/from_openstudio/schedule/ruleset.rb +9 -0
- data/lib/from_openstudio.rb +3 -0
- data/lib/to_openstudio/geometry/aperture.rb +2 -2
- data/lib/to_openstudio/geometry/door.rb +2 -2
- data/lib/to_openstudio/geometry/face.rb +31 -29
- data/lib/to_openstudio/geometry/room.rb +169 -161
- data/lib/to_openstudio/geometry/shade.rb +18 -15
- data/lib/to_openstudio/model.rb +65 -59
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9cfa9e82e9efaedde24e6ccfe30c4d7fe6cbd4259a81d36de9b8a9936b8259b
|
4
|
+
data.tar.gz: 6c47a045cf0684fdc33521ca96b6bd1fe3f27a52658fe774a6f76165ab3c87b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ceefaa71ad6fe18240c21b2738ddf5741fc9620dcf63088c67511a0fedb132f1ea063879527183624f88a196826f7a58bef62ac9211e605f815264ae3add17c4
|
7
|
+
data.tar.gz: 4b6e648afaa694daa0e2246f4f5f6cf6c5dadb714e4b4fa7681919447fa24a37cb9bba9e6edbbb77a216e04005a0d23b5da7c8f38df07c60ad2ed2543767ad7d
|
data/honeybee-openstudio.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'honeybee-openstudio'
|
7
|
-
spec.version = '2.31.
|
7
|
+
spec.version = '2.31.9'
|
8
8
|
spec.authors = ['Tanushree Charan', 'Dan Macumber', 'Chris Mackey', 'Mostapha Sadeghipour Roudsari']
|
9
9
|
spec.email = ['tanushree.charan@nrel.gov', 'chris@ladybug.tools']
|
10
10
|
|
@@ -201,6 +201,17 @@ module Honeybee
|
|
201
201
|
thermal_zone = space.thermalZone
|
202
202
|
unless thermal_zone.empty?
|
203
203
|
thermal_zone = space.thermalZone.get
|
204
|
+
# Create ideal_air_system if present
|
205
|
+
unless thermal_zone.equipment.nil?
|
206
|
+
thermal_zone.equipment.each do |equipment|
|
207
|
+
if equipment.to_ZoneHVACIdealLoadsAirSystem.is_initialized
|
208
|
+
ideal_air_hash = Honeybee::IdealAirSystemAbridged.from_hvac(
|
209
|
+
equipment.to_ZoneHVACIdealLoadsAirSystem.get)
|
210
|
+
$hvacs << ideal_air_hash
|
211
|
+
hash[:hvac] = ideal_air_hash[:identifier]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
204
215
|
unless thermal_zone.thermostatSetpointDualSetpoint.empty?
|
205
216
|
hash[:setpoint] = {}
|
206
217
|
hash[:setpoint][:type] = 'SetpointAbridged'
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# 4ju0 d/zf OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
|
3
|
+
# Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
16
|
+
# may be used to endorse or promote products derived from this software without
|
17
|
+
# specific prior written permission from the respective party.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
20
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
21
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
23
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
24
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
25
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
26
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
28
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
# *******************************************************************************
|
31
|
+
|
32
|
+
require 'honeybee/hvac/ideal_air'
|
33
|
+
require 'to_openstudio/model_object'
|
34
|
+
|
35
|
+
module Honeybee
|
36
|
+
class IdealAirSystemAbridged
|
37
|
+
|
38
|
+
def self.from_hvac(hvac)
|
39
|
+
# create an empty hash
|
40
|
+
hash = {}
|
41
|
+
hash[:type] = 'IdealAirSystemAbridged'
|
42
|
+
hash[:identifier] = clean_name(hvac.nameString)
|
43
|
+
unless hvac.displayName.empty?
|
44
|
+
hash[:display_name] = (hvac.displayName.get).force_encoding("UTF-8")
|
45
|
+
end
|
46
|
+
hash[:economizer_type] = hvac.outdoorAirEconomizerType
|
47
|
+
if hvac.demandControlledVentilationType.downcase == 'none'
|
48
|
+
hash[:demand_controlled_ventilation] = false
|
49
|
+
else
|
50
|
+
hash[:demand_controlled_ventilation] = true
|
51
|
+
end
|
52
|
+
hash[:sensible_heat_recovery] = hvac.sensibleHeatRecoveryEffectiveness
|
53
|
+
hash[:latent_heat_recovery] = hvac.latentHeatRecoveryEffectiveness
|
54
|
+
hash[:heating_air_temperature] = hvac.maximumHeatingSupplyAirTemperature
|
55
|
+
hash[:cooling_air_temperature] = hvac.minimumCoolingSupplyAirTemperature
|
56
|
+
if hvac.heatingLimit == 'NoLimit'
|
57
|
+
hash[:heating_limit] = hvac.heatingLimit
|
58
|
+
end
|
59
|
+
if hvac.coolingLimit == 'NoLimit'
|
60
|
+
hash[:cooling_limit] = hvac.coolingLimit
|
61
|
+
end
|
62
|
+
unless hvac.heatingAvailabilitySchedule.empty?
|
63
|
+
schedule = hvac.heatingAvailabilitySchedule.get
|
64
|
+
hash[:heating_availability] = schedule.nameString
|
65
|
+
end
|
66
|
+
unless hvac.coolingAvailabilitySchedule.empty?
|
67
|
+
schedule = hvac.coolingAvailabilitySchedule.get
|
68
|
+
hash[:coolingAvailabilitySchedule]
|
69
|
+
end
|
70
|
+
|
71
|
+
hash
|
72
|
+
end
|
73
|
+
|
74
|
+
end #IdealAirSystemAbridged
|
75
|
+
end #Honeybee
|
@@ -51,6 +51,7 @@ module Honeybee
|
|
51
51
|
$opaque_constructions = {}
|
52
52
|
$window_constructions = {}
|
53
53
|
$shade_constructions = {}
|
54
|
+
$hvacs = []
|
54
55
|
|
55
56
|
hash[:properties] = properties_from_model(openstudio_model)
|
56
57
|
|
@@ -126,6 +127,7 @@ module Honeybee
|
|
126
127
|
hash[:schedule_type_limits] = schedtypelimits_from_model(openstudio_model)
|
127
128
|
hash[:schedules] = schedules_from_model(openstudio_model)
|
128
129
|
hash[:program_types] = programtype_from_model(openstudio_model)
|
130
|
+
hash[:hvacs] = $hvacs
|
129
131
|
|
130
132
|
hash
|
131
133
|
end
|
@@ -81,6 +81,15 @@ module Honeybee
|
|
81
81
|
hash[:day_schedules] << ScheduleRulesetAbridged.from_day_schedule(schedule_day)
|
82
82
|
end
|
83
83
|
|
84
|
+
# remove the bogus default day schedule that OpenStudio adds upon import from IDF
|
85
|
+
if hash[:default_day_schedule].start_with?('Schedule Day ')
|
86
|
+
if hash[:day_schedules][0][:values] == [0] && hash[:schedule_rules].length() > 0
|
87
|
+
hash[:default_day_schedule] = hash[:schedule_rules][0][:schedule_day]
|
88
|
+
hash[:schedule_rules].pop(0)
|
89
|
+
hash[:day_schedules].pop(0)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
84
93
|
# assing any schedule type limits if they exist
|
85
94
|
unless schedule_ruleset.scheduleTypeLimits.empty?
|
86
95
|
typ_lim = schedule_ruleset.scheduleTypeLimits.get
|
data/lib/from_openstudio.rb
CHANGED
@@ -44,6 +44,9 @@ require 'from_openstudio/geometry/face'
|
|
44
44
|
require 'from_openstudio/geometry/room'
|
45
45
|
require 'from_openstudio/geometry/shade'
|
46
46
|
|
47
|
+
# extend the hvac objects
|
48
|
+
require 'from_openstudio/hvac/ideal_air'
|
49
|
+
|
47
50
|
# extend the construction objects
|
48
51
|
require 'from_openstudio/construction/opaque'
|
49
52
|
require 'from_openstudio/construction/window'
|
@@ -118,7 +118,7 @@ module Honeybee
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# assign the construction if it exists
|
121
|
-
if @hash[:properties][:energy][:construction]
|
121
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
|
122
122
|
construction_identifier = @hash[:properties][:energy][:construction]
|
123
123
|
construction = openstudio_model.getConstructionByName(construction_identifier)
|
124
124
|
if !construction.empty?
|
@@ -182,7 +182,7 @@ module Honeybee
|
|
182
182
|
|
183
183
|
# get the approriate construction id
|
184
184
|
construction_id = nil
|
185
|
-
if @hash[:properties][:energy][:construction]
|
185
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
|
186
186
|
construction_id = @hash[:properties][:energy][:construction]
|
187
187
|
else
|
188
188
|
construction_id = 'Generic Double Pane'
|
@@ -118,7 +118,7 @@ module Honeybee
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# assign the construction if it exists
|
121
|
-
if @hash[:properties][:energy][:construction]
|
121
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
|
122
122
|
construction_identifier = @hash[:properties][:energy][:construction]
|
123
123
|
construction = openstudio_model.getConstructionByName(construction_identifier)
|
124
124
|
if !construction.empty?
|
@@ -176,7 +176,7 @@ module Honeybee
|
|
176
176
|
|
177
177
|
# get the approriate construction id
|
178
178
|
construction_id = nil
|
179
|
-
if @hash[:properties][:energy][:construction]
|
179
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
|
180
180
|
construction_id = @hash[:properties][:energy][:construction]
|
181
181
|
elsif @hash[:is_glass] == true
|
182
182
|
construction_id = 'Generic Double Pane'
|
@@ -64,39 +64,41 @@ module Honeybee
|
|
64
64
|
end
|
65
65
|
os_surface.setSurfaceType(@hash[:face_type])
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
67
|
+
if @hash[:properties].key?(:energy)
|
68
|
+
# assign the construction if it is present
|
69
|
+
if @hash[:properties][:energy][:construction]
|
70
|
+
construction_identifier = @hash[:properties][:energy][:construction]
|
71
|
+
construction = openstudio_model.getConstructionByName(construction_identifier)
|
72
|
+
unless construction.empty?
|
73
|
+
os_construction = construction.get
|
74
|
+
os_surface.setConstruction(os_construction)
|
75
|
+
end
|
74
76
|
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# assign the AFN crack if it's specified and we are not using simple infiltration
|
78
|
-
if !$use_simple_vent && @hash[:properties][:energy][:vent_crack]
|
79
|
-
unless $interior_afn_srf_hash[@hash[:identifier]] # interior crack that's been accounted for
|
80
|
-
vent_crack = @hash[:properties][:energy][:vent_crack]
|
81
|
-
# create the crack object for using default values
|
82
|
-
flow_exponent = crack_defaults[:flow_exponent][:default].to_f
|
83
|
-
os_crack = OpenStudio::Model::AirflowNetworkCrack.new(
|
84
|
-
openstudio_model, vent_crack[:flow_coefficient], flow_exponent,
|
85
|
-
$afn_reference_crack)
|
86
77
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
78
|
+
# assign the AFN crack if it's specified and we are not using simple infiltration
|
79
|
+
if !$use_simple_vent && @hash[:properties][:energy][:vent_crack]
|
80
|
+
unless $interior_afn_srf_hash[@hash[:identifier]] # interior crack that's been accounted for
|
81
|
+
vent_crack = @hash[:properties][:energy][:vent_crack]
|
82
|
+
# create the crack object for using default values
|
83
|
+
flow_exponent = crack_defaults[:flow_exponent][:default].to_f
|
84
|
+
os_crack = OpenStudio::Model::AirflowNetworkCrack.new(
|
85
|
+
openstudio_model, vent_crack[:flow_coefficient], flow_exponent,
|
86
|
+
$afn_reference_crack)
|
87
|
+
|
88
|
+
# assign the flow exponent if it's specified
|
89
|
+
if vent_crack[:flow_exponent]
|
90
|
+
os_crack.setAirMassFlowExponent(vent_crack[:flow_exponent])
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
# if it's a Surface boundary condition ensure the neighbor is not written as a duplicate
|
94
|
+
if @hash[:boundary_condition][:type] == 'Surface'
|
95
|
+
$interior_afn_srf_hash[@hash[:boundary_condition][:boundary_condition_objects][0]] = true
|
96
|
+
end
|
96
97
|
|
97
|
-
|
98
|
-
|
98
|
+
# create the AirflowNetworkSurface
|
99
|
+
os_afn_srf = os_surface.getAirflowNetworkSurface(os_crack)
|
99
100
|
|
101
|
+
end
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
@@ -206,7 +208,7 @@ module Honeybee
|
|
206
208
|
|
207
209
|
# get the approriate construction id
|
208
210
|
construction_id = nil
|
209
|
-
if @hash[:properties][:energy][:construction]
|
211
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:construction]
|
210
212
|
construction_id = @hash[:properties][:energy][:construction]
|
211
213
|
elsif @hash[:face_type] == 'Wall'
|
212
214
|
construction_id = 'Generic Exterior Wall'
|
@@ -84,26 +84,6 @@ module Honeybee
|
|
84
84
|
os_thermal_zone.setDisplayName(@hash[:display_name])
|
85
85
|
end
|
86
86
|
|
87
|
-
# assign the programtype
|
88
|
-
if @hash[:properties][:energy][:program_type]
|
89
|
-
space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
|
90
|
-
unless space_type.empty?
|
91
|
-
space_type_object = space_type.get
|
92
|
-
os_space.setSpaceType(space_type_object)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# assign the constructionset
|
97
|
-
if @hash[:properties][:energy][:construction_set]
|
98
|
-
construction_set_identifier = @hash[:properties][:energy][:construction_set]
|
99
|
-
# gets default construction set assigned to room from openstudio_model
|
100
|
-
construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
|
101
|
-
unless construction_set.empty?
|
102
|
-
default_construction_set = construction_set.get
|
103
|
-
os_space.setDefaultConstructionSet(default_construction_set)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
87
|
# assign the multiplier
|
108
88
|
if @hash[:multiplier] and @hash[:multiplier] != 1
|
109
89
|
os_thermal_zone.setMultiplier(@hash[:multiplier])
|
@@ -142,6 +122,28 @@ module Honeybee
|
|
142
122
|
end
|
143
123
|
os_space.setBuildingStory(story)
|
144
124
|
|
125
|
+
if @hash[:properties].key?(:energy)
|
126
|
+
# assign the programtype
|
127
|
+
if @hash[:properties][:energy][:program_type]
|
128
|
+
space_type = openstudio_model.getSpaceTypeByName(@hash[:properties][:energy][:program_type])
|
129
|
+
unless space_type.empty?
|
130
|
+
space_type_object = space_type.get
|
131
|
+
os_space.setSpaceType(space_type_object)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# assign the constructionset
|
136
|
+
if @hash[:properties][:energy][:construction_set]
|
137
|
+
construction_set_identifier = @hash[:properties][:energy][:construction_set]
|
138
|
+
# gets default construction set assigned to room from openstudio_model
|
139
|
+
construction_set = openstudio_model.getDefaultConstructionSetByName(construction_set_identifier)
|
140
|
+
unless construction_set.empty?
|
141
|
+
default_construction_set = construction_set.get
|
142
|
+
os_space.setDefaultConstructionSet(default_construction_set)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
145
147
|
# keep track of all window ventilation objects
|
146
148
|
window_vent = {}
|
147
149
|
|
@@ -162,9 +164,11 @@ module Honeybee
|
|
162
164
|
# assign aperture-level shades if they exist
|
163
165
|
if face[:apertures]
|
164
166
|
face[:apertures].each do |aperture|
|
165
|
-
if aperture[:properties]
|
166
|
-
|
167
|
-
[aperture[:
|
167
|
+
if aperture[:properties].key?(:energy)
|
168
|
+
if aperture[:properties][:energy][:vent_opening]
|
169
|
+
window_vent[aperture[:identifier]] = \
|
170
|
+
[aperture[:properties][:energy][:vent_opening], aperture[:boundary_condition][:type]]
|
171
|
+
end
|
168
172
|
end
|
169
173
|
if aperture[:outdoor_shades]
|
170
174
|
unless os_shd_group
|
@@ -180,9 +184,11 @@ module Honeybee
|
|
180
184
|
# assign door-level shades if they exist
|
181
185
|
if face[:doors]
|
182
186
|
face[:doors].each do |door|
|
183
|
-
if door[:properties]
|
184
|
-
|
185
|
-
[door[:
|
187
|
+
if door[:properties].key?(:energy)
|
188
|
+
if door[:properties][:energy][:vent_opening]
|
189
|
+
window_vent[door[:identifier]] = \
|
190
|
+
[door[:properties][:energy][:vent_opening], door[:boundary_condition][:type]]
|
191
|
+
end
|
186
192
|
end
|
187
193
|
if door[:outdoor_shades]
|
188
194
|
unless os_shd_group
|
@@ -196,7 +202,7 @@ module Honeybee
|
|
196
202
|
end
|
197
203
|
|
198
204
|
# assign interior constructions for adiabatic Faces
|
199
|
-
if !face[:properties][:energy][:construction]
|
205
|
+
if face[:properties].key?(:energy) && !face[:properties][:energy][:construction]
|
200
206
|
if face[:boundary_condition][:type] == 'Adiabatic'
|
201
207
|
# assign default interior construction for Adiabatic Faces
|
202
208
|
if face[:face_type] != 'Wall'
|
@@ -212,7 +218,7 @@ module Honeybee
|
|
212
218
|
if face[:face_type] == 'AirBoundary'
|
213
219
|
# assign default air boundary construction for AirBoundary face types
|
214
220
|
air_construction = closest_air_construction(openstudio_model, os_space)
|
215
|
-
if !face[:properties][:energy][:construction]
|
221
|
+
if face[:properties].key?(:energy) && !face[:properties][:energy][:construction]
|
216
222
|
unless air_construction.nil?
|
217
223
|
os_surface.setConstruction(air_construction)
|
218
224
|
end
|
@@ -256,164 +262,166 @@ module Honeybee
|
|
256
262
|
end
|
257
263
|
|
258
264
|
#check whether there are any load objects on the room overriding the programtype
|
259
|
-
if @hash[:properties]
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
unique_program_ppl
|
265
|
+
if @hash[:properties].key?(:energy)
|
266
|
+
if @hash[:properties][:energy][:people]
|
267
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
268
|
+
unique_program_ppl = unique_program.people
|
269
|
+
unless unique_program_ppl.empty? # remove the previous load definition
|
270
|
+
unique_program_ppl[0].remove()
|
271
|
+
end
|
272
|
+
custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
|
273
|
+
os_custom_people = custom_people.to_openstudio(openstudio_model)
|
274
|
+
os_custom_people.setSpaceType(unique_program) # assign the new load definition
|
264
275
|
end
|
265
|
-
custom_people = PeopleAbridged.new(@hash[:properties][:energy][:people])
|
266
|
-
os_custom_people = custom_people.to_openstudio(openstudio_model)
|
267
|
-
os_custom_people.setSpaceType(unique_program) # assign the new load definition
|
268
|
-
end
|
269
276
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
277
|
+
# assign lighting if it exists
|
278
|
+
if @hash[:properties][:energy][:lighting]
|
279
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
280
|
+
unique_program_lght = unique_program.lights
|
281
|
+
unless unique_program_lght.empty? # remove the previous load definition
|
282
|
+
unique_program_lght[0].remove()
|
283
|
+
end
|
284
|
+
custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
|
285
|
+
os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
|
286
|
+
os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
|
276
287
|
end
|
277
|
-
custom_lighting = LightingAbridged.new(@hash[:properties][:energy][:lighting])
|
278
|
-
os_custom_lighting = custom_lighting.to_openstudio(openstudio_model)
|
279
|
-
os_custom_lighting.setSpaceType(unique_program) # assign the new load definition
|
280
|
-
end
|
281
288
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
289
|
+
# assign electric equipment if it exists
|
290
|
+
if @hash[:properties][:energy][:electric_equipment]
|
291
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
292
|
+
unique_program_ele = unique_program.electricEquipment
|
293
|
+
unless unique_program_ele.empty? # remove the previous load definition
|
294
|
+
unique_program_ele[0].remove()
|
295
|
+
end
|
296
|
+
custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
|
297
|
+
os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
|
298
|
+
os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
|
288
299
|
end
|
289
|
-
custom_electric_equipment = ElectricEquipmentAbridged.new(@hash[:properties][:energy][:electric_equipment])
|
290
|
-
os_custom_electric_equipment = custom_electric_equipment.to_openstudio(openstudio_model)
|
291
|
-
os_custom_electric_equipment.setSpaceType(unique_program) # assign the new load definition
|
292
|
-
end
|
293
300
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
301
|
+
# assign gas equipment if it exists
|
302
|
+
if @hash[:properties][:energy][:gas_equipment]
|
303
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
304
|
+
unique_program_gas = unique_program.gasEquipment
|
305
|
+
unless unique_program_gas.empty? # remove the previous load definition
|
306
|
+
unique_program_gas[0].remove()
|
307
|
+
end
|
308
|
+
custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
|
309
|
+
os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
|
310
|
+
os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
|
300
311
|
end
|
301
|
-
custom_gas_equipment = GasEquipmentAbridged.new(@hash[:properties][:energy][:gas_equipment])
|
302
|
-
os_custom_gas_equipment = custom_gas_equipment.to_openstudio(openstudio_model)
|
303
|
-
os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
|
304
|
-
end
|
305
312
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
+
# assign service hot water if it exists
|
314
|
+
if @hash[:properties][:energy][:service_hot_water]
|
315
|
+
shw_space = ServiceHotWaterAbridged.new(@hash[:properties][:energy][:service_hot_water])
|
316
|
+
os_shw_space = shw_space.to_openstudio(
|
317
|
+
openstudio_model, os_space, @hash[:properties][:energy][:shw])
|
318
|
+
$shw_for_plant = shw_space
|
319
|
+
end
|
313
320
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
321
|
+
# assign infiltration if it exists
|
322
|
+
if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
|
323
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
324
|
+
unique_program_inf = unique_program.spaceInfiltrationDesignFlowRates
|
325
|
+
unless unique_program_inf.empty? # remove the previous load definition
|
326
|
+
unique_program_inf[0].remove()
|
327
|
+
end
|
328
|
+
custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
|
329
|
+
os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
|
330
|
+
os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
|
320
331
|
end
|
321
|
-
custom_infiltration = InfiltrationAbridged.new(@hash[:properties][:energy][:infiltration])
|
322
|
-
os_custom_infiltration = custom_infiltration.to_openstudio(openstudio_model)
|
323
|
-
os_custom_infiltration.setSpaceType(unique_program) # assign the new load definition
|
324
|
-
end
|
325
332
|
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
333
|
+
# assign ventilation if it exists
|
334
|
+
if @hash[:properties][:energy][:ventilation]
|
335
|
+
unique_program = get_unique_space_type(openstudio_model, os_space)
|
336
|
+
unique_program.resetDesignSpecificationOutdoorAir()
|
337
|
+
custom_ventilation = VentilationAbridged.new(@hash[:properties][:energy][:ventilation])
|
338
|
+
os_custom_ventilation = custom_ventilation.to_openstudio(openstudio_model)
|
339
|
+
unique_program.setDesignSpecificationOutdoorAir(os_custom_ventilation)
|
340
|
+
end
|
334
341
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
342
|
+
# assign setpoint if it exists
|
343
|
+
if @hash[:properties][:energy][:setpoint]
|
344
|
+
# thermostat object is created because heating and cooling schedule are required
|
345
|
+
setpoint_thermostat_space = SetpointThermostat.new(@hash[:properties][:energy][:setpoint])
|
346
|
+
os_setpoint_thermostat_space = setpoint_thermostat_space.to_openstudio(openstudio_model)
|
347
|
+
#set thermostat to thermal zone
|
348
|
+
os_thermal_zone.setThermostatSetpointDualSetpoint(os_setpoint_thermostat_space)
|
349
|
+
# humidistat object is created if humidifying or dehumidifying schedule is specified
|
350
|
+
if @hash[:properties][:energy][:setpoint][:humidifying_schedule] or @hash[:properties][:energy][:setpoint][:dehumidifying_schedule]
|
351
|
+
setpoint_humidistat_space = SetpointHumidistat.new(@hash[:properties][:energy][:setpoint])
|
352
|
+
os_setpoint_humidistat_space = setpoint_humidistat_space.to_openstudio(openstudio_model)
|
353
|
+
os_thermal_zone.setZoneControlHumidistat(os_setpoint_humidistat_space)
|
354
|
+
end
|
347
355
|
end
|
348
|
-
end
|
349
356
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
357
|
+
# assign daylight control if it exists
|
358
|
+
if @hash[:properties][:energy][:daylighting_control]
|
359
|
+
dl_control = DaylightingControl.new(@hash[:properties][:energy][:daylighting_control])
|
360
|
+
os_dl_control = dl_control.to_openstudio(openstudio_model, os_thermal_zone, os_space)
|
361
|
+
end
|
355
362
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
363
|
+
# assign window ventilation objects if they exist
|
364
|
+
if $use_simple_vent && !window_vent.empty? # write simple WindAndStack ventilation
|
365
|
+
window_vent.each do |sub_f_id, open_prop|
|
366
|
+
opening = open_prop[0]
|
367
|
+
bc = open_prop[1]
|
368
|
+
if bc == 'Outdoors'
|
369
|
+
opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
|
370
|
+
unless opt_sub_f.empty?
|
371
|
+
sub_f = opt_sub_f.get
|
372
|
+
vent_open = VentilationOpening.new(opening)
|
373
|
+
os_vent_open = vent_open.to_openstudio(
|
374
|
+
openstudio_model, sub_f, @hash[:properties][:energy][:window_vent_control])
|
375
|
+
os_vent_open.addToThermalZone(os_thermal_zone)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
elsif !$use_simple_vent # we're using the AFN!
|
380
|
+
# write an AirflowNetworkZone object in for the Room
|
381
|
+
os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
|
382
|
+
os_afn_room_node.setVentilationControlMode('NoVent')
|
383
|
+
# write the opening objects for each Aperture / Door
|
384
|
+
operable_subfs = [] # collect the sub-face objects for the EMS
|
385
|
+
opening_factors = [] # collect the maximum opening factors for the EMS
|
386
|
+
window_vent.each do |sub_f_id, open_prop|
|
387
|
+
opening = open_prop[0]
|
362
388
|
opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
|
363
389
|
unless opt_sub_f.empty?
|
364
390
|
sub_f = opt_sub_f.get
|
365
|
-
|
366
|
-
|
367
|
-
openstudio_model, sub_f
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
elsif !$use_simple_vent # we're using the AFN!
|
373
|
-
# write an AirflowNetworkZone object in for the Room
|
374
|
-
os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
|
375
|
-
os_afn_room_node.setVentilationControlMode('NoVent')
|
376
|
-
# write the opening objects for each Aperture / Door
|
377
|
-
operable_subfs = [] # collect the sub-face objects for the EMS
|
378
|
-
opening_factors = [] # collect the maximum opening factors for the EMS
|
379
|
-
window_vent.each do |sub_f_id, open_prop|
|
380
|
-
opening = open_prop[0]
|
381
|
-
opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
|
382
|
-
unless opt_sub_f.empty?
|
383
|
-
sub_f = opt_sub_f.get
|
384
|
-
if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
|
385
|
-
vent_open = VentilationOpening.new(opening)
|
386
|
-
open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
|
387
|
-
unless open_fac.nil? # nil is used for horizontal exterior skylights
|
388
|
-
operable_subfs << sub_f
|
389
|
-
opening_factors << open_fac
|
391
|
+
if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
|
392
|
+
vent_open = VentilationOpening.new(opening)
|
393
|
+
open_fac = vent_open.to_openstudio_afn(openstudio_model, sub_f)
|
394
|
+
unless open_fac.nil? # nil is used for horizontal exterior skylights
|
395
|
+
operable_subfs << sub_f
|
396
|
+
opening_factors << open_fac
|
397
|
+
end
|
390
398
|
end
|
391
399
|
end
|
392
400
|
end
|
401
|
+
# add the control startegy of the ventilation openings using the EMS
|
402
|
+
if @hash[:properties][:energy][:window_vent_control]
|
403
|
+
vent_control = VentilationControlAbridged.new(@hash[:properties][:energy][:window_vent_control])
|
404
|
+
vent_control.to_openstudio(
|
405
|
+
openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
|
406
|
+
end
|
393
407
|
end
|
394
|
-
# add the control startegy of the ventilation openings using the EMS
|
395
|
-
if @hash[:properties][:energy][:window_vent_control]
|
396
|
-
vent_control = VentilationControlAbridged.new(@hash[:properties][:energy][:window_vent_control])
|
397
|
-
vent_control.to_openstudio(
|
398
|
-
openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
|
399
|
-
end
|
400
|
-
end
|
401
408
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
409
|
+
# assign any internal masses if specified
|
410
|
+
if @hash[:properties][:energy][:internal_masses]
|
411
|
+
@hash[:properties][:energy][:internal_masses].each do |int_mass|
|
412
|
+
hb_int_mass = InternalMassAbridged.new(int_mass)
|
413
|
+
os_int_mass = hb_int_mass.to_openstudio(openstudio_model, os_space)
|
414
|
+
os_int_mass.setSpace(os_space)
|
415
|
+
end
|
408
416
|
end
|
409
|
-
end
|
410
417
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
418
|
+
# assign any process loads if specified
|
419
|
+
if @hash[:properties][:energy][:process_loads]
|
420
|
+
@hash[:properties][:energy][:process_loads].each do |p_load|
|
421
|
+
hb_p_load = ProcessAbridged.new(p_load)
|
422
|
+
os_p_load = hb_p_load.to_openstudio(openstudio_model)
|
423
|
+
os_p_load.setSpace(os_space)
|
424
|
+
end
|
417
425
|
end
|
418
426
|
end
|
419
427
|
|
@@ -61,23 +61,26 @@ module Honeybee
|
|
61
61
|
unless @hash[:display_name].nil?
|
62
62
|
os_shading_surface.setDisplayName(@hash[:display_name])
|
63
63
|
end
|
64
|
-
|
65
|
-
if @hash[:properties]
|
66
|
-
|
67
|
-
construction
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
|
65
|
+
if @hash[:properties].key?(:energy)
|
66
|
+
# assign the construction if it exists
|
67
|
+
if @hash[:properties][:energy][:construction]
|
68
|
+
construction_identifier = @hash[:properties][:energy][:construction]
|
69
|
+
construction = openstudio_model.getConstructionByName(construction_identifier)
|
70
|
+
unless construction.empty?
|
71
|
+
os_construction = construction.get
|
72
|
+
os_shading_surface.setConstruction(os_construction)
|
73
|
+
end
|
71
74
|
end
|
72
|
-
end
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
# assign the transmittance schedule if it exists
|
77
|
+
if @hash[:properties][:energy][:transmittance_schedule]
|
78
|
+
schedule_identifier = @hash[:properties][:energy][:transmittance_schedule]
|
79
|
+
schedule = openstudio_model.getScheduleByName(schedule_identifier)
|
80
|
+
unless schedule.empty?
|
81
|
+
os_schedule = schedule.get
|
82
|
+
os_shading_surface.setTransmittanceSchedule(os_schedule)
|
83
|
+
end
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
data/lib/to_openstudio/model.rb
CHANGED
@@ -109,7 +109,7 @@ module Honeybee
|
|
109
109
|
|
110
110
|
# initialize a global variable for whether the AFN is used instead of simple ventilation
|
111
111
|
$use_simple_vent = true
|
112
|
-
if @hash[:properties][:energy][:ventilation_simulation_control]
|
112
|
+
if @hash[:properties].key?(:energy) && @hash[:properties][:energy][:ventilation_simulation_control]
|
113
113
|
vent_sim_control = @hash[:properties][:energy][:ventilation_simulation_control]
|
114
114
|
if vent_sim_control[:vent_control_type] && vent_sim_control[:vent_control_type] != 'SingleZone'
|
115
115
|
$use_simple_vent = false
|
@@ -129,42 +129,44 @@ module Honeybee
|
|
129
129
|
$shw_for_plant = nil # track whether a hot water plant is needed
|
130
130
|
|
131
131
|
# create all of the non-geometric model elements
|
132
|
-
if
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
132
|
+
if @hash[:properties].key?(:energy)
|
133
|
+
if log_report # schedules are used by all other objects and come first
|
134
|
+
puts 'Translating Schedules'
|
135
|
+
end
|
136
|
+
if @hash[:properties][:energy][:schedule_type_limits]
|
137
|
+
create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
|
138
|
+
end
|
139
|
+
if @hash[:properties][:energy][:schedules]
|
140
|
+
create_schedules(@hash[:properties][:energy][:schedules], false, true)
|
141
|
+
end
|
141
142
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
143
|
+
if log_report
|
144
|
+
puts 'Translating Materials'
|
145
|
+
end
|
146
|
+
if @hash[:properties][:energy][:materials]
|
147
|
+
create_materials(@hash[:properties][:energy][:materials])
|
148
|
+
end
|
148
149
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
150
|
+
if log_report
|
151
|
+
puts 'Translating Constructions'
|
152
|
+
end
|
153
|
+
if @hash[:properties][:energy][:constructions]
|
154
|
+
create_constructions(@hash[:properties][:energy][:constructions])
|
155
|
+
end
|
155
156
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
157
|
+
if log_report
|
158
|
+
puts 'Translating ConstructionSets'
|
159
|
+
end
|
160
|
+
if @hash[:properties][:energy][:construction_sets]
|
161
|
+
create_construction_sets(@hash[:properties][:energy][:construction_sets])
|
162
|
+
end
|
162
163
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
164
|
+
if log_report
|
165
|
+
puts 'Translating ProgramTypes'
|
166
|
+
end
|
167
|
+
if @hash[:properties][:energy][:program_types]
|
168
|
+
create_program_types(@hash[:properties][:energy][:program_types])
|
169
|
+
end
|
168
170
|
end
|
169
171
|
|
170
172
|
# create the default construction set to catch any cases of unassigned constructions
|
@@ -196,8 +198,10 @@ module Honeybee
|
|
196
198
|
if log_report
|
197
199
|
puts 'Translating HVAC Systems'
|
198
200
|
end
|
199
|
-
|
200
|
-
|
201
|
+
if @hash[:properties].key?(:energy)
|
202
|
+
create_hvacs
|
203
|
+
create_hot_water_plant
|
204
|
+
end
|
201
205
|
|
202
206
|
if log_report
|
203
207
|
puts 'Translating Context Shade Geometry'
|
@@ -445,32 +449,34 @@ module Honeybee
|
|
445
449
|
openstudio_room = room_object.to_openstudio(@openstudio_model)
|
446
450
|
|
447
451
|
# for rooms with hot water objects definied in the ProgramType, make a new WaterUse:Equipment
|
448
|
-
if room[:properties]
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
452
|
+
if room[:properties].key?(:energy)
|
453
|
+
if room[:properties][:energy][:program_type] && !room[:properties][:energy][:service_hot_water]
|
454
|
+
program_type_id = room[:properties][:energy][:program_type]
|
455
|
+
shw_hash = $programtype_shw_hash[program_type_id]
|
456
|
+
unless shw_hash.nil?
|
457
|
+
shw_object = ServiceHotWaterAbridged.new(shw_hash)
|
458
|
+
openstudio_shw = shw_object.to_openstudio(
|
459
|
+
@openstudio_model, openstudio_room, room[:properties][:energy][:shw])
|
460
|
+
$shw_for_plant = shw_object
|
461
|
+
end
|
456
462
|
end
|
457
|
-
end
|
458
463
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
464
|
+
# for rooms with setpoint objects defined in the ProgramType, make a new thermostat
|
465
|
+
if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
|
466
|
+
thermal_zone = openstudio_room.thermalZone()
|
467
|
+
unless thermal_zone.empty?
|
468
|
+
thermal_zone_object = thermal_zone.get
|
469
|
+
program_type_id = room[:properties][:energy][:program_type]
|
470
|
+
setpoint_hash = $programtype_setpoint_hash[program_type_id]
|
471
|
+
unless setpoint_hash.nil? # program type has no setpoint
|
472
|
+
thermostat_object = SetpointThermostat.new(setpoint_hash)
|
473
|
+
openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
|
474
|
+
thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
|
475
|
+
if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
|
476
|
+
humidistat_object = SetpointHumidistat.new(setpoint_hash)
|
477
|
+
openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
|
478
|
+
thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
|
479
|
+
end
|
474
480
|
end
|
475
481
|
end
|
476
482
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honeybee-openstudio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.31.
|
4
|
+
version: 2.31.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tanushree Charan
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date: 2022-05-
|
14
|
+
date: 2022-05-26 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -177,6 +177,7 @@ files:
|
|
177
177
|
- lib/from_openstudio/geometry/face.rb
|
178
178
|
- lib/from_openstudio/geometry/room.rb
|
179
179
|
- lib/from_openstudio/geometry/shade.rb
|
180
|
+
- lib/from_openstudio/hvac/ideal_air.rb
|
180
181
|
- lib/from_openstudio/load/daylight.rb
|
181
182
|
- lib/from_openstudio/load/electric_equipment.rb
|
182
183
|
- lib/from_openstudio/load/gas_equipment.rb
|