honeybee-openstudio 2.5.3 → 2.6.0

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.
@@ -49,6 +49,10 @@ module FromHoneybee
49
49
  @@schema[:components][:schemas][:FaceEnergyPropertiesAbridged][:properties]
50
50
  end
51
51
 
52
+ def crack_defaults
53
+ @@schema[:components][:schemas][:AFNCrack][:properties]
54
+ end
55
+
52
56
  def find_existing_openstudio_object(openstudio_model)
53
57
  model_surf = openstudio_model.getSurfaceByName(@hash[:identifier])
54
58
  return model_surf.get unless model_surf.empty?
@@ -56,16 +60,18 @@ module FromHoneybee
56
60
  end
57
61
 
58
62
  def to_openstudio(openstudio_model)
59
- # create the openstudio surface
63
+ # reorder the vertices to ensure they start from the upper-left corner
60
64
  os_vertices = OpenStudio::Point3dVector.new
61
65
  @hash[:geometry][:boundary].each do |vertex|
62
66
  os_vertices << OpenStudio::Point3d.new(vertex[0], vertex[1], vertex[2])
63
67
  end
64
68
  reordered_vertices = OpenStudio.reorderULC(os_vertices)
65
69
 
70
+ # create the openstudio surface and assign the type
66
71
  os_surface = OpenStudio::Model::Surface.new(reordered_vertices, openstudio_model)
67
72
  os_surface.setName(@hash[:identifier])
68
73
  os_surface.setSurfaceType(@hash[:face_type])
74
+
69
75
  # assign the construction if it is present
70
76
  if @hash[:properties][:energy][:construction]
71
77
  construction_identifier = @hash[:properties][:energy][:construction]
@@ -76,6 +82,32 @@ module FromHoneybee
76
82
  end
77
83
  end
78
84
 
85
+ # assign the AFN crack if it's specified and we are not using simple infiltration
86
+ if !$use_simple_vent && @hash[:properties][:energy][:vent_crack]
87
+ unless $interior_afn_srf_hash[@hash[:identifier]] # interior crack that's been accounted for
88
+ vent_crack = @hash[:properties][:energy][:vent_crack]
89
+ # create the crack object for using default values
90
+ flow_exponent = crack_defaults[:flow_exponent][:default].to_f
91
+ os_crack = OpenStudio::Model::AirflowNetworkCrack.new(
92
+ openstudio_model, vent_crack[:flow_coefficient], flow_exponent,
93
+ $afn_reference_crack)
94
+
95
+ # assign the flow exponent if it's specified
96
+ if vent_crack[:flow_exponent]
97
+ os_crack. setAirMassFlowExponent(vent_crack[:flow_exponent])
98
+ end
99
+
100
+ # if it's a Surface boundary condition ensure the neighbor is not written as a duplicate
101
+ if @hash[:boundary_condition][:type] == 'Surface'
102
+ $interior_afn_srf_hash[@hash[:boundary_condition][:boundary_condition_objects][0]] = true
103
+ end
104
+
105
+ # create the AirflowNetworkSurface
106
+ os_afn_srf = os_surface.getAirflowNetworkSurface(os_crack)
107
+
108
+ end
109
+ end
110
+
79
111
  # assign the boundary condition
80
112
  boundary_condition = (@hash[:boundary_condition][:type])
81
113
  case boundary_condition
@@ -43,6 +43,7 @@ require 'from_honeybee/load/ventilation'
43
43
  require 'from_honeybee/load/setpoint_thermostat'
44
44
  require 'from_honeybee/load/setpoint_humidistat'
45
45
  require 'from_honeybee/ventcool/opening'
46
+ require 'from_honeybee/ventcool/control'
46
47
 
47
48
  require 'openstudio'
48
49
 
@@ -185,17 +186,19 @@ module FromHoneybee
185
186
  os_surface.setConstruction(air_construction)
186
187
  end
187
188
  # add air mixing properties to the global list that tracks them
188
- air_hash = $air_boundary_hash[air_construction.name.to_s]
189
- if air_hash[:air_mixing_per_area]
190
- air_mix_area = air_hash[:air_mixing_per_area]
191
- else
192
- air_default = @@schema[:components][:schemas][:AirBoundaryConstructionAbridged]
193
- air_mix_area = air_default[:properties][:air_mixing_per_area][:default]
189
+ if $use_simple_vent # only use air mixing objects when simple ventilation is requested
190
+ air_hash = $air_boundary_hash[air_construction.name.to_s]
191
+ if air_hash[:air_mixing_per_area]
192
+ air_mix_area = air_hash[:air_mixing_per_area]
193
+ else
194
+ air_default = @@schema[:components][:schemas][:AirBoundaryConstructionAbridged]
195
+ air_mix_area = air_default[:properties][:air_mixing_per_area][:default]
196
+ end
197
+ flow_rate = os_surface.netArea * air_mix_area
198
+ flow_sch_id = air_hash[:air_mixing_schedule]
199
+ adj_zone_id = face[:boundary_condition][:boundary_condition_objects][-1]
200
+ $air_mxing_array << [os_thermal_zone, flow_rate, flow_sch_id, adj_zone_id]
194
201
  end
195
- flow_rate = os_surface.netArea * air_mix_area
196
- flow_sch_id = air_hash[:air_mixing_schedule]
197
- adj_zone_id = face[:boundary_condition][:boundary_condition_objects][-1]
198
- $air_mxing_array << [os_thermal_zone, flow_rate, flow_sch_id, adj_zone_id]
199
202
  end
200
203
  end
201
204
  end
@@ -265,7 +268,7 @@ module FromHoneybee
265
268
  end
266
269
 
267
270
  # assign infiltration if it exists
268
- if @hash[:properties][:energy][:infiltration]
271
+ if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
269
272
  infiltration = openstudio_model.getSpaceInfiltrationDesignFlowRateByName(
270
273
  @hash[:properties][:energy][:infiltration][:identifier])
271
274
  unless infiltration.empty?
@@ -308,7 +311,7 @@ module FromHoneybee
308
311
  end
309
312
 
310
313
  # assign window ventilation objects if they exist
311
- unless window_vent.empty?
314
+ if $use_simple_vent && !window_vent.empty? # write simple WindAndStack ventilation
312
315
  window_vent.each do |sub_f_id, opening|
313
316
  opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
314
317
  unless opt_sub_f.empty?
@@ -319,6 +322,31 @@ module FromHoneybee
319
322
  os_window_vent.addToThermalZone(os_thermal_zone)
320
323
  end
321
324
  end
325
+ elsif !$use_simple_vent # we're using the AFN!
326
+ # write an AirflowNetworkZone object in for the Room
327
+ os_afn_room_node = os_thermal_zone.getAirflowNetworkZone
328
+ os_afn_room_node.setVentilationControlMode('NoVent')
329
+ # write the opening objects for each Aperture / Door
330
+ operable_subfs = [] # collect the sub-face objects for the EMS
331
+ opening_factors = [] # collect the maximum opening factors for the EMS
332
+ window_vent.each do |sub_f_id, opening|
333
+ opt_sub_f = openstudio_model.getSubSurfaceByName(sub_f_id)
334
+ unless opt_sub_f.empty?
335
+ sub_f = opt_sub_f.get
336
+ if sub_f.adjacentSubSurface.empty? # not an interior window that's already in the AFN
337
+ window_vent = VentilationOpening.new(opening)
338
+ open_fac = window_vent.to_openstudio_afn(openstudio_model, sub_f)
339
+ operable_subfs << sub_f
340
+ opening_factors << open_fac
341
+ end
342
+ end
343
+ end
344
+ # add the control startegy of the ventilation openings using the EMS
345
+ if @hash[:properties][:energy][:window_vent_control]
346
+ vent_control = VentilationControl.new(@hash[:properties][:energy][:window_vent_control])
347
+ vent_control.to_openstudio(
348
+ openstudio_model, os_thermal_zone, operable_subfs, opening_factors)
349
+ end
322
350
  end
323
351
 
324
352
  os_space
@@ -75,6 +75,9 @@ require 'from_honeybee/schedule/ruleset'
75
75
  require 'from_honeybee/load/setpoint_thermostat'
76
76
  require 'from_honeybee/load/setpoint_humidistat'
77
77
 
78
+ # import the ventilative cooling objects
79
+ require 'from_honeybee/ventcool/simulation'
80
+
78
81
  require 'openstudio'
79
82
 
80
83
 
@@ -158,11 +161,23 @@ module FromHoneybee
158
161
  building = @openstudio_model.getBuilding
159
162
  building.setStandardsBuildingType('MediumOffice')
160
163
 
164
+ # initialize a global variable for whether the AFN is used instead of simple ventilation
165
+ $use_simple_vent = true
166
+ if @hash[:properties][:energy][:ventilation_simulation_control]
167
+ vent_sim_control = @hash[:properties][:energy][:ventilation_simulation_control]
168
+ if vent_sim_control[:vent_control_type] && vent_sim_control[:vent_control_type] != 'SingleZone'
169
+ $use_simple_vent = false
170
+ vsim_cntrl = VentilationSimulationControl.new(vent_sim_control)
171
+ $afn_reference_crack = vsim_cntrl.to_openstudio(@openstudio_model)
172
+ end
173
+ end
174
+
161
175
  # initialize global hashes for various model properties
162
176
  $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
163
177
  $air_boundary_hash = Hash.new # hash to track any air boundary constructions
164
178
  $window_shade_hash = Hash.new # hash to track any window constructions with shade
165
179
  $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
180
+ $interior_afn_srf_hash = Hash.new # track whether an adjacent surface is already in the AFN
166
181
 
167
182
  # create all of the non-geometric model elements
168
183
  if log_report
@@ -94,14 +94,14 @@ module FromHoneybee
94
94
  os_gas_equipment = gas_equipment.to_openstudio(openstudio_model)
95
95
  os_gas_equipment.setSpaceType(os_space_type)
96
96
  end
97
-
97
+
98
98
  # assign infiltration
99
- if @hash[:infiltration]
99
+ if @hash[:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
100
100
  infiltration = InfiltrationAbridged.new(@hash[:infiltration])
101
101
  os_infiltration = infiltration.to_openstudio(openstudio_model)
102
102
  os_infiltration.setSpaceType(os_space_type)
103
103
  end
104
-
104
+
105
105
  # assign ventilation
106
106
  if @hash[:ventilation]
107
107
  ventilation = VentilationAbridged.new(@hash[:ventilation])
@@ -0,0 +1,161 @@
1
+ # *******************************************************************************
2
+ # Honeybee 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 'from_honeybee/model_object'
33
+
34
+ require 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class VentilationControl < ModelObject
38
+ attr_reader :errors, :warnings
39
+ @@outdoor_node = nil
40
+ @@program_manager = nil
41
+
42
+ def initialize(hash = {})
43
+ super(hash)
44
+ end
45
+
46
+ def defaults
47
+ @@schema[:components][:schemas][:VentilationControlAbridged][:properties]
48
+ end
49
+
50
+ def get_outdoor_node(openstudio_model)
51
+ # get the EMS sensor for the outdoor node if it exists or generate it if it doesn't
52
+ if @@outdoor_node.nil?
53
+ out_var = OpenStudio::Model::OutputVariable.new(
54
+ 'Site Outdoor Air Drybulb Temperature', openstudio_model)
55
+ out_var.setReportingFrequency('Timestep')
56
+ out_var.setKeyValue('Environment')
57
+ @@outdoor_node = OpenStudio::Model::EnergyManagementSystemSensor.new(
58
+ openstudio_model, out_var)
59
+ @@outdoor_node.setName('Outdoor_Sensor')
60
+ end
61
+ @@outdoor_node
62
+ end
63
+
64
+ def get_program_manager(openstudio_model)
65
+ # get the EMS Program Manager for all window opening if it exists or generate it if it doesn't
66
+ if @@program_manager.nil?
67
+ @@program_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(
68
+ openstudio_model)
69
+ @@program_manager.setName('Temperature_Controlled_Window_Opening')
70
+ @@program_manager.setCallingPoint('BeginTimestepBeforePredictor')
71
+ end
72
+ @@program_manager
73
+ end
74
+
75
+ def to_openstudio(openstudio_model, parent_zone, vent_opening_surfaces, vent_opening_factors)
76
+ # Get the outdoor temperature sensor and the room air temperature sensor
77
+ out_air_temp = get_outdoor_node(openstudio_model)
78
+ in_var = OpenStudio::Model::OutputVariable.new('Zone Air Temperature', openstudio_model)
79
+ in_var.setReportingFrequency('Timestep')
80
+ zone_name = parent_zone.name
81
+ os_zone_name = 'Indoor'
82
+ unless zone_name.empty?
83
+ os_zone_name = zone_name.get
84
+ in_var.setKeyValue(os_zone_name)
85
+ end
86
+ in_air_temp = OpenStudio::Model::EnergyManagementSystemSensor.new(openstudio_model, in_var)
87
+ in_sensor_name = os_zone_name.delete(' ').delete('.') + '_Sensor'
88
+ in_air_temp.setName(in_sensor_name)
89
+
90
+ # create the actuators for each of the operaable windows
91
+ actuator_names = []
92
+ vent_opening_surfaces.each do |vent_srf|
93
+ window_act = OpenStudio::Model::EnergyManagementSystemActuator.new(
94
+ vent_srf, 'AirFlow Network Window/Door Opening', 'Venting Opening Factor')
95
+ vent_srf_name = vent_srf.name
96
+ unless vent_srf_name.empty?
97
+ act_name = vent_srf_name.get.delete(' ').delete('.') + '_OpenFactor'
98
+ window_act.setName(act_name)
99
+ actuator_names << act_name
100
+ end
101
+ end
102
+
103
+ # create the first line of the EMS Program to open each window according to the control logic
104
+ logic_statements = []
105
+ # check the minimum indoor tempertaure for ventilation
106
+ min_in = @hash[:min_indoor_temperature]
107
+ if min_in && min_in != defaults[:min_indoor_temperature][:default]
108
+ logic_statements << '(' + in_sensor_name + ' > ' + min_in.to_s + ')'
109
+ end
110
+ # check the maximum indoor tempertaure for ventilation
111
+ max_in = @hash[:max_indoor_temperature]
112
+ if max_in && max_in != defaults[:max_indoor_temperature][:default]
113
+ logic_statements << '(' + in_sensor_name + ' < ' + max_in.to_s + ')'
114
+ end
115
+ # check the minimum outdoor tempertaure for ventilation
116
+ min_out = @hash[:min_outdoor_temperature]
117
+ if min_out && min_out != defaults[:min_outdoor_temperature][:default]
118
+ logic_statements << '(Outdoor_Sensor > ' + min_out.to_s + ')'
119
+ end
120
+ # check the maximum outdoor tempertaure for ventilation
121
+ max_out = @hash[:max_outdoor_temperature]
122
+ if max_out && max_out != defaults[:max_outdoor_temperature][:default]
123
+ logic_statements << '(Outdoor_Sensor < ' + max_out.to_s + ')'
124
+ end
125
+ # check the delta tempertaure for ventilation
126
+ delta_in_out = @hash[:delta_temperature]
127
+ if delta_in_out && delta_in_out != defaults[:delta_temperature][:default]
128
+ logic_statements << '((' + in_sensor_name + ' - Outdoor_Sensor) > ' + delta_in_out.to_s + ')'
129
+ end
130
+ # create the complete logic statement for opening windows
131
+ if logic_statements.empty?
132
+ complete_logic = 'IF (Outdoor_Sensor < 100)' # no logic has been provided; always open windows
133
+ else
134
+ complete_logic = 'IF ' + logic_statements.join(' && ')
135
+ end
136
+
137
+ # initialize the program and add the complete logic
138
+ ems_program = OpenStudio::Model::EnergyManagementSystemProgram.new(openstudio_model)
139
+ ems_program.setName(os_zone_name.delete(' ').delete('.') + '_WindowOpening')
140
+ ems_program.addLine(complete_logic)
141
+
142
+ # loop through each of the actuators and open each window
143
+ actuator_names.zip(vent_opening_factors).each do |act_name, open_factor|
144
+ ems_program.addLine('SET ' + act_name + ' = ' + open_factor.to_s)
145
+ end
146
+ # loop through each of the actuators and close each window
147
+ ems_program.addLine('ELSE')
148
+ actuator_names.each do |act_name|
149
+ ems_program.addLine('SET ' + act_name + ' = 0')
150
+ end
151
+ ems_program.addLine('ENDIF')
152
+
153
+ # add the program object the the global program manager for all window opening
154
+ prog_manager = get_program_manager(openstudio_model)
155
+ prog_manager.addProgram(ems_program)
156
+
157
+ ems_program
158
+ end
159
+
160
+ end #VentilationControl
161
+ end #FromHoneybee
@@ -46,8 +46,8 @@ module FromHoneybee
46
46
  end
47
47
 
48
48
  def defaults_control
49
- @@schema[:components][:schemas][:VentilationControlAbridged][:properties]
50
- end
49
+ @@schema[:components][:schemas][:VentilationControlAbridged][:properties]
50
+ end
51
51
 
52
52
  def to_openstudio(openstudio_model, parent, vent_control_hash)
53
53
  # create wind and stack object and set identifier
@@ -140,6 +140,48 @@ module FromHoneybee
140
140
  os_opening
141
141
  end
142
142
 
143
+ def to_openstudio_afn(openstudio_model, parent)
144
+ # process the flow_coefficient_closed and set it to a very small number if it's 0
145
+ if @hash[:flow_coefficient_closed] and @hash[:flow_coefficient_closed] != 0
146
+ flow_coefficient = @hash[:flow_coefficient_closed]
147
+ else
148
+ flow_coefficient = 1.0e-09 # set it to a very small number
149
+ end
150
+
151
+ # create the simple opening object for the Aperture or Door using default values
152
+ flow_exponent = defaults[:flow_exponent_closed][:default].to_f
153
+ two_way_thresh= defaults[:two_way_threshold][:default].to_f
154
+ discharge_coeff = defaults[:discharge_coefficient][:default].to_f
155
+ os_opening = OpenStudio::Model::AirflowNetworkSimpleOpening.new(
156
+ openstudio_model, flow_coefficient, flow_exponent, two_way_thresh, discharge_coeff)
157
+
158
+ # assign the flow exponent when the opening is closed
159
+ if @hash[:flow_exponent_closed]
160
+ os_opening.setAirMassFlowExponentWhenOpeningisClosed(@hash[:flow_exponent_closed])
161
+ end
162
+ # assign the minimum difference for two-way flow
163
+ if @hash[:two_way_threshold]
164
+ os_opening.setMinimumDensityDifferenceforTwoWayFlow(@hash[:two_way_threshold])
165
+ end
166
+ # assign the discharge coefficient
167
+ if @hash[:discharge_coefficient]
168
+ os_opening.setDischargeCoefficient(@hash[:discharge_coefficient])
169
+ end
170
+
171
+ # create the AirflowNetworkSurface
172
+ os_afn_srf = parent.getAirflowNetworkSurface(os_opening)
173
+
174
+ # assign the opening area
175
+ if @hash[:fraction_area_operable]
176
+ open_fac = @hash[:fraction_area_operable]
177
+ else
178
+ open_fac = defaults[:fraction_area_operable][:default]
179
+ end
180
+ os_afn_srf.setWindowDoorOpeningFactorOrCrackFactor(open_fac)
181
+
182
+ open_fac
183
+ end
184
+
143
185
  def compute_height(surface)
144
186
  # derive the height (difference in z values) of a surface
145
187
  verts = surface.vertices
@@ -0,0 +1,110 @@
1
+ # *******************************************************************************
2
+ # Honeybee 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 'from_honeybee/model_object'
33
+
34
+ require 'openstudio'
35
+
36
+ module FromHoneybee
37
+ class VentilationSimulationControl < ModelObject
38
+ attr_reader :errors, :warnings
39
+
40
+ def initialize(hash = {})
41
+ super(hash)
42
+ end
43
+
44
+ def defaults
45
+ @@schema[:components][:schemas][:VentilationSimulationControl][:properties]
46
+ end
47
+
48
+ def to_openstudio(openstudio_model)
49
+ # create the AirflowNetworkSimulationControl object
50
+ os_vsim_control = openstudio_model.getAirflowNetworkSimulationControl
51
+ os_vsim_control.setName('Window Based Ventilative Cooling')
52
+
53
+ # assign the control type
54
+ if @hash[:vent_control_type]
55
+ os_vsim_control.setAirflowNetworkControl(@hash[:vent_control_type])
56
+ else
57
+ os_vsim_control.setAirflowNetworkControl('MultizoneWithoutDistribution')
58
+ end
59
+
60
+ # assign the building type
61
+ if @hash[:building_type]
62
+ os_vsim_control.setBuildingType(@hash[:building_type])
63
+ else
64
+ os_vsim_control.setBuildingType(defaults[:building_type][:default])
65
+ end
66
+
67
+ # assign the long axis azimth angle of the building
68
+ if @hash[:long_axis_angle]
69
+ os_vsim_control.setAzimuthAngleofLongAxisofBuilding(@hash[:long_axis_angle])
70
+ else
71
+ os_vsim_control.setAzimuthAngleofLongAxisofBuilding(defaults[:long_axis_angle][:default])
72
+ end
73
+
74
+ # assign the aspect ratio of the building
75
+ if @hash[:aspect_ratio]
76
+ os_vsim_control.setBuildingAspectRatio(@hash[:aspect_ratio])
77
+ else
78
+ os_vsim_control.setBuildingAspectRatio(defaults[:aspect_ratio][:default])
79
+ end
80
+
81
+ # create the AirflowNetworkReferenceCrackConditions object that all other cracks reference
82
+ os_ref_crack = OpenStudio::Model::AirflowNetworkReferenceCrackConditions.new(openstudio_model)
83
+ os_ref_crack.setName('Reference Crack Conditions')
84
+
85
+ # assign the reference temperature
86
+ if @hash[:reference_temperature]
87
+ os_ref_crack.setTemperature(@hash[:reference_temperature])
88
+ else
89
+ os_ref_crack.setTemperature(defaults[:reference_temperature][:default])
90
+ end
91
+
92
+ # assign the reference pressure
93
+ if @hash[:reference_pressure]
94
+ os_ref_crack.setBarometricPressure(@hash[:reference_pressure])
95
+ else
96
+ os_ref_crack.setBarometricPressure(defaults[:reference_pressure][:default])
97
+ end
98
+
99
+ # assign the reference humidity ratio
100
+ if @hash[:reference_humidity_ratio]
101
+ os_ref_crack.setHumidityRatio(@hash[:reference_humidity_ratio])
102
+ else
103
+ os_ref_crack.setHumidityRatio(defaults[:reference_humidity_ratio][:default])
104
+ end
105
+
106
+ os_ref_crack
107
+ end
108
+
109
+ end #VentilationSimulationControl
110
+ end #FromHoneybee