openstudio-ee 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +7 -0
- data/Rakefile +0 -2
- data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.rb +1 -1
- data/lib/measures/GLHEProExportLoadsforGroundHeatExchangerSizing/measure.xml +3 -4
- data/lib/measures/nze_hvac/measure.rb +8 -6
- data/lib/measures/nze_hvac/measure.xml +9 -9
- data/lib/openstudio/ee_measures/version.rb +1 -1
- data/openstudio-ee.gemspec +6 -8
- metadata +11 -50
- data/lib/measures/ImproveFanTotalEfficiencybyPercentage/measure.rb +0 -333
- data/lib/measures/ImproveFanTotalEfficiencybyPercentage/measure.xml +0 -150
- data/lib/measures/ReplaceFanTotalEfficiency/measure.rb +0 -330
- data/lib/measures/ReplaceFanTotalEfficiency/measure.xml +0 -150
- data/lib/measures/add_apszhp_to_each_zone/measure.rb +0 -607
- data/lib/measures/add_apszhp_to_each_zone/measure.xml +0 -184
- data/lib/measures/add_energy_recovery_ventilator/measure.rb +0 -354
- data/lib/measures/add_energy_recovery_ventilator/measure.xml +0 -78
- data/lib/measures/improve_simple_glazing_by_percentage/measure.rb +0 -81
- data/lib/measures/improve_simple_glazing_by_percentage/measure.xml +0 -70
- data/lib/measures/reduce_water_use_by_percentage/measure.rb +0 -61
- data/lib/measures/reduce_water_use_by_percentage/measure.xml +0 -62
- data/lib/measures/replace_hvac_with_gshp_and_doas/measure.rb +0 -511
- data/lib/measures/replace_hvac_with_gshp_and_doas/measure.xml +0 -375
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_AedgMeasures.rb +0 -454
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Constructions.rb +0 -221
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Geometry.rb +0 -41
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_HVAC.rb +0 -1682
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_HelperMethods.rb +0 -114
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_LightingAndEquipment.rb +0 -99
- data/lib/measures/replace_hvac_with_gshp_and_doas/resources/OsLib_Schedules.rb +0 -142
- data/lib/measures/replace_simple_glazing/measure.rb +0 -86
- data/lib/measures/replace_simple_glazing/measure.xml +0 -78
- data/lib/measures/set_boiler_thermal_efficiency/measure.rb +0 -520
- data/lib/measures/set_boiler_thermal_efficiency/measure.xml +0 -78
- data/lib/measures/set_water_heater_efficiency_heat_lossand_peak_water_flow_rate/measure.rb +0 -207
- data/lib/measures/set_water_heater_efficiency_heat_lossand_peak_water_flow_rate/measure.xml +0 -78
- data/lib/measures/tenant_star_internal_loads/measure.rb +0 -134
- data/lib/measures/tenant_star_internal_loads/measure.xml +0 -67
- data/lib/measures/tenant_star_internal_loads/resources/os_lib_helper_methods.rb +0 -401
- data/lib/measures/vr_fwith_doas/measure.rb +0 -468
- data/lib/measures/vr_fwith_doas/measure.xml +0 -298
- data/lib/measures/vr_fwith_doas/resources/OsLib_AedgMeasures.rb +0 -454
- data/lib/measures/vr_fwith_doas/resources/OsLib_Constructions.rb +0 -221
- data/lib/measures/vr_fwith_doas/resources/OsLib_Geometry.rb +0 -41
- data/lib/measures/vr_fwith_doas/resources/OsLib_HVAC.rb +0 -1516
- data/lib/measures/vr_fwith_doas/resources/OsLib_HelperMethods.rb +0 -114
- data/lib/measures/vr_fwith_doas/resources/OsLib_LightingAndEquipment.rb +0 -99
- data/lib/measures/vr_fwith_doas/resources/OsLib_Schedules.rb +0 -142
@@ -1,150 +0,0 @@
|
|
1
|
-
<measure>
|
2
|
-
<schema_version>3.0</schema_version>
|
3
|
-
<name>replace_fan_total_efficiency</name>
|
4
|
-
<uid>ebeca0aa-a432-4283-a714-17116f7c8f8c</uid>
|
5
|
-
<version_id>348976a4-526f-4a56-b819-74c78f8a07e3</version_id>
|
6
|
-
<version_modified>20190212T002510Z</version_modified>
|
7
|
-
<xml_checksum>F78494F2</xml_checksum>
|
8
|
-
<class_name>ReplaceFanTotalEfficiency</class_name>
|
9
|
-
<display_name>Replace Fan Total Efficiency</display_name>
|
10
|
-
<description></description>
|
11
|
-
<modeler_description></modeler_description>
|
12
|
-
<arguments>
|
13
|
-
<argument>
|
14
|
-
<name>object</name>
|
15
|
-
<display_name>Choose an Air Loop to Alter.</display_name>
|
16
|
-
<type>Choice</type>
|
17
|
-
<required>true</required>
|
18
|
-
<model_dependent>false</model_dependent>
|
19
|
-
<default_value>*All Air Loops*</default_value>
|
20
|
-
<choices>
|
21
|
-
<choice>
|
22
|
-
<value>{7d3f0300-6b06-458a-ad5e-0d5d7ec180cc}</value>
|
23
|
-
<display_name>*All Air Loops*</display_name>
|
24
|
-
</choice>
|
25
|
-
</choices>
|
26
|
-
</argument>
|
27
|
-
<argument>
|
28
|
-
<name>motor_eff</name>
|
29
|
-
<display_name>Fan Total Efficiency Replacement in %</display_name>
|
30
|
-
<type>Double</type>
|
31
|
-
<required>true</required>
|
32
|
-
<model_dependent>false</model_dependent>
|
33
|
-
<default_value>70</default_value>
|
34
|
-
</argument>
|
35
|
-
<argument>
|
36
|
-
<name>remove_costs</name>
|
37
|
-
<display_name>Remove Baseline Costs From Effected Fans?</display_name>
|
38
|
-
<type>Boolean</type>
|
39
|
-
<required>true</required>
|
40
|
-
<model_dependent>false</model_dependent>
|
41
|
-
<default_value>false</default_value>
|
42
|
-
<choices>
|
43
|
-
<choice>
|
44
|
-
<value>true</value>
|
45
|
-
<display_name>true</display_name>
|
46
|
-
</choice>
|
47
|
-
<choice>
|
48
|
-
<value>false</value>
|
49
|
-
<display_name>false</display_name>
|
50
|
-
</choice>
|
51
|
-
</choices>
|
52
|
-
</argument>
|
53
|
-
<argument>
|
54
|
-
<name>material_cost</name>
|
55
|
-
<display_name>Material and Installation Costs per Motor ($).</display_name>
|
56
|
-
<type>Double</type>
|
57
|
-
<required>true</required>
|
58
|
-
<model_dependent>false</model_dependent>
|
59
|
-
<default_value>0</default_value>
|
60
|
-
</argument>
|
61
|
-
<argument>
|
62
|
-
<name>demolition_cost</name>
|
63
|
-
<display_name>Demolition Costs per Motor ($).</display_name>
|
64
|
-
<type>Double</type>
|
65
|
-
<required>true</required>
|
66
|
-
<model_dependent>false</model_dependent>
|
67
|
-
<default_value>0</default_value>
|
68
|
-
</argument>
|
69
|
-
<argument>
|
70
|
-
<name>years_until_costs_start</name>
|
71
|
-
<display_name>Years Until Costs Start (whole years).</display_name>
|
72
|
-
<type>Integer</type>
|
73
|
-
<required>true</required>
|
74
|
-
<model_dependent>false</model_dependent>
|
75
|
-
<default_value>0</default_value>
|
76
|
-
</argument>
|
77
|
-
<argument>
|
78
|
-
<name>demo_cost_initial_const</name>
|
79
|
-
<display_name>Demolition Costs Occur During Initial Construction?</display_name>
|
80
|
-
<type>Boolean</type>
|
81
|
-
<required>true</required>
|
82
|
-
<model_dependent>false</model_dependent>
|
83
|
-
<default_value>false</default_value>
|
84
|
-
<choices>
|
85
|
-
<choice>
|
86
|
-
<value>true</value>
|
87
|
-
<display_name>true</display_name>
|
88
|
-
</choice>
|
89
|
-
<choice>
|
90
|
-
<value>false</value>
|
91
|
-
<display_name>false</display_name>
|
92
|
-
</choice>
|
93
|
-
</choices>
|
94
|
-
</argument>
|
95
|
-
<argument>
|
96
|
-
<name>expected_life</name>
|
97
|
-
<display_name>Expected Life (whole years).</display_name>
|
98
|
-
<type>Integer</type>
|
99
|
-
<required>true</required>
|
100
|
-
<model_dependent>false</model_dependent>
|
101
|
-
<default_value>20</default_value>
|
102
|
-
</argument>
|
103
|
-
<argument>
|
104
|
-
<name>om_cost</name>
|
105
|
-
<display_name>O & M Costs per Motor ($).</display_name>
|
106
|
-
<type>Double</type>
|
107
|
-
<required>true</required>
|
108
|
-
<model_dependent>false</model_dependent>
|
109
|
-
<default_value>0</default_value>
|
110
|
-
</argument>
|
111
|
-
<argument>
|
112
|
-
<name>om_frequency</name>
|
113
|
-
<display_name>O & M Frequency (whole years).</display_name>
|
114
|
-
<type>Integer</type>
|
115
|
-
<required>true</required>
|
116
|
-
<model_dependent>false</model_dependent>
|
117
|
-
<default_value>1</default_value>
|
118
|
-
</argument>
|
119
|
-
</arguments>
|
120
|
-
<outputs/>
|
121
|
-
<provenances/>
|
122
|
-
<tags>
|
123
|
-
<tag>HVAC.Distribution</tag>
|
124
|
-
</tags>
|
125
|
-
<attributes>
|
126
|
-
<attribute>
|
127
|
-
<name>Measure Type</name>
|
128
|
-
<value>ModelMeasure</value>
|
129
|
-
<datatype>string</datatype>
|
130
|
-
</attribute>
|
131
|
-
<attribute>
|
132
|
-
<name>Uses SketchUp API</name>
|
133
|
-
<value>false</value>
|
134
|
-
<datatype>boolean</datatype>
|
135
|
-
</attribute>
|
136
|
-
</attributes>
|
137
|
-
<files>
|
138
|
-
<file>
|
139
|
-
<version>
|
140
|
-
<software_program>OpenStudio</software_program>
|
141
|
-
<identifier>1.0.3</identifier>
|
142
|
-
<min_compatible>1.0.3</min_compatible>
|
143
|
-
</version>
|
144
|
-
<filename>measure.rb</filename>
|
145
|
-
<filetype>rb</filetype>
|
146
|
-
<usage_type>script</usage_type>
|
147
|
-
<checksum>FCCFD3DA</checksum>
|
148
|
-
</file>
|
149
|
-
</files>
|
150
|
-
</measure>
|
@@ -1,607 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Author: Julien Marrec
|
4
|
-
# email: julien.marrec@gmail.com
|
5
|
-
|
6
|
-
# start the measure
|
7
|
-
class AddAPSZHPToEachZone < OpenStudio::Ruleset::ModelUserScript
|
8
|
-
# define the name that a user will see, this method may be deprecated as
|
9
|
-
# the display name in PAT comes from the name field in measure.xml
|
10
|
-
def name
|
11
|
-
return 'Add a PSZ-HP to each zone'
|
12
|
-
end
|
13
|
-
|
14
|
-
def description
|
15
|
-
return 'This will add a Rooftop Packaged Single Zone Heat Pump (RTU with DX cooling and DX heating coils) to each zone of the model.'
|
16
|
-
end
|
17
|
-
|
18
|
-
def modeler_description
|
19
|
-
return "Add a System 4 - PSZ-HP - unit for each zone. This is a single zone system.
|
20
|
-
Parameters:
|
21
|
-
- Double: COP cooling and COP heating (Double)
|
22
|
-
- Boolean: supplementary electric heating coil (Boolean)
|
23
|
-
- Pressure rise (Optional Double)
|
24
|
-
- Deletion of existing HVAC equipment (Boolean)
|
25
|
-
- DCV enabled or not (Boolean)
|
26
|
-
- Fan type: Variable Volume Fan (VFD) or not (Constant Volume) (Choice)
|
27
|
-
- Filter for the zone name (String): only zones that contains the string you input in filter will receive this system."
|
28
|
-
end
|
29
|
-
|
30
|
-
# define the arguments that the user will input
|
31
|
-
def arguments(model)
|
32
|
-
args = OpenStudio::Ruleset::OSArgumentVector.new
|
33
|
-
|
34
|
-
delete_existing = OpenStudio::Ruleset::OSArgument.makeBoolArgument('delete_existing', true)
|
35
|
-
delete_existing.setDisplayName('Delete any existing HVAC equipment?')
|
36
|
-
args << delete_existing
|
37
|
-
|
38
|
-
cop_cooling = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('cop_cooling', true)
|
39
|
-
cop_cooling.setDisplayName('COP Cooling (SI)')
|
40
|
-
cop_cooling.setDefaultValue(3.1)
|
41
|
-
args << cop_cooling
|
42
|
-
|
43
|
-
cop_heating = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('cop_heating', true)
|
44
|
-
cop_heating.setDisplayName('COP Heating (SI)')
|
45
|
-
cop_heating.setDefaultValue(3.1)
|
46
|
-
args << cop_heating
|
47
|
-
|
48
|
-
has_electric_coil = OpenStudio::Ruleset::OSArgument.makeBoolArgument('has_electric_coil', false)
|
49
|
-
has_electric_coil.setDisplayName('Include supplementary electric heating coils?')
|
50
|
-
has_electric_coil.setDefaultValue(true)
|
51
|
-
args << has_electric_coil
|
52
|
-
|
53
|
-
has_dcv = OpenStudio::Ruleset::OSArgument.makeBoolArgument('has_dcv', false)
|
54
|
-
has_dcv.setDisplayName('Enable Demand Controlled Ventilation?')
|
55
|
-
has_dcv.setDefaultValue(false)
|
56
|
-
args << has_dcv
|
57
|
-
|
58
|
-
chs = OpenStudio::StringVector.new
|
59
|
-
chs << 'Constant Volume (default)'
|
60
|
-
chs << 'Variable Volume (VFD)'
|
61
|
-
fan_type = OpenStudio::Ruleset::OSArgument.makeChoiceArgument('fan_type', chs, true)
|
62
|
-
fan_type.setDisplayName('Select fan type:')
|
63
|
-
args << fan_type
|
64
|
-
|
65
|
-
fan_pressure_rise = OpenStudio::Ruleset::OSArgument.makeDoubleArgument('fan_pressure_rise', false)
|
66
|
-
fan_pressure_rise.setDisplayName('Fan Pressure Rise (Pa)')
|
67
|
-
fan_pressure_rise.setDescription('Leave blank for default value')
|
68
|
-
# fan_pressure_rise.setDefaultValue(0)
|
69
|
-
args << fan_pressure_rise
|
70
|
-
|
71
|
-
chs = OpenStudio::StringVector.new
|
72
|
-
chs << 'By Space Type'
|
73
|
-
chs << "By Space Type's 'Standards Space Type'"
|
74
|
-
chs << 'By Zone Filter'
|
75
|
-
filter_type = OpenStudio::Ruleset::OSArgument.makeChoiceArgument('filter_type', chs, true)
|
76
|
-
filter_type.setDisplayName('How do you want to choose the affected zones?')
|
77
|
-
args << filter_type
|
78
|
-
|
79
|
-
# create an argument for a space type to be used in the model. Only return those that are used
|
80
|
-
spaceTypes = model.getSpaceTypes
|
81
|
-
usedSpaceTypes_handle = OpenStudio::StringVector.new
|
82
|
-
usedSpaceTypes_displayName = OpenStudio::StringVector.new
|
83
|
-
|
84
|
-
# Should normally be an OpenStudio::StringVector.new but it doesn't have a uniq! method and it works with a regular hash..
|
85
|
-
standardsSpaceType = []
|
86
|
-
|
87
|
-
spaceTypes.each do |spaceType|
|
88
|
-
if !spaceType.spaces.empty? # only show space types used in the building
|
89
|
-
usedSpaceTypes_handle << spaceType.handle.to_s
|
90
|
-
usedSpaceTypes_displayName << spaceType.name.to_s
|
91
|
-
|
92
|
-
if !spaceType.standardsSpaceType.empty?
|
93
|
-
standardsSpaceType << spaceType.standardsSpaceType.get
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# make an argument for space type
|
99
|
-
space_type = OpenStudio::Ruleset::OSArgument.makeChoiceArgument('space_type', usedSpaceTypes_handle, usedSpaceTypes_displayName, false)
|
100
|
-
space_type.setDisplayName('a. Which Space Type?')
|
101
|
-
args << space_type
|
102
|
-
|
103
|
-
# Argument for Standards Space Type
|
104
|
-
|
105
|
-
# First, make it unique
|
106
|
-
standardsSpaceType.uniq!
|
107
|
-
standards_space_type = OpenStudio::Ruleset::OSArgument.makeChoiceArgument('standards_space_type', standardsSpaceType, false)
|
108
|
-
standards_space_type.setDisplayName('b. Which Standards Space Type')
|
109
|
-
args << standards_space_type
|
110
|
-
|
111
|
-
zone_filter = OpenStudio::Ruleset::OSArgument.makeStringArgument('zone_filter', false)
|
112
|
-
zone_filter.setDisplayName('c. Only Apply to Zones that contain the following string')
|
113
|
-
zone_filter.setDescription("Case insensitive. For example, type 'retail' to apply to zones that have the word 'retail' or 'REtaiL' in their name. Leave blank to apply to all zones")
|
114
|
-
args << zone_filter
|
115
|
-
|
116
|
-
return args
|
117
|
-
end # end the arguments method
|
118
|
-
|
119
|
-
# define what happens when the measure is run
|
120
|
-
def run(model, runner, user_arguments)
|
121
|
-
super(model, runner, user_arguments)
|
122
|
-
|
123
|
-
# use the built-in error checking
|
124
|
-
if !runner.validateUserArguments(arguments(model), user_arguments)
|
125
|
-
return false
|
126
|
-
end
|
127
|
-
|
128
|
-
# Retrieve arguments' values
|
129
|
-
delete_existing = runner.getBoolArgumentValue('delete_existing', user_arguments)
|
130
|
-
cop_cooling = runner.getDoubleArgumentValue('cop_cooling', user_arguments)
|
131
|
-
cop_heating = runner.getDoubleArgumentValue('cop_heating', user_arguments)
|
132
|
-
has_electric_coil = runner.getBoolArgumentValue('has_electric_coil', user_arguments)
|
133
|
-
has_dcv = runner.getBoolArgumentValue('has_dcv', user_arguments)
|
134
|
-
|
135
|
-
# Get fan_pressure_rise: this is an OptionalDouble - we'll use '.get' later
|
136
|
-
fan_pressure_rise = runner.getOptionalDoubleArgumentValue('fan_pressure_rise', user_arguments)
|
137
|
-
|
138
|
-
# FanType
|
139
|
-
fan_type = runner.getStringArgumentValue('fan_type', user_arguments)
|
140
|
-
runner.registerInfo("Fan type: #{fan_type}")
|
141
|
-
|
142
|
-
if fan_type == 'Variable Volume (VFD)'
|
143
|
-
has_vfd = true
|
144
|
-
else
|
145
|
-
has_vfd = false
|
146
|
-
end
|
147
|
-
|
148
|
-
filter_type = runner.getStringArgumentValue('filter_type', user_arguments)
|
149
|
-
|
150
|
-
if filter_type == 'By Space Type'
|
151
|
-
space_type = runner.getOptionalWorkspaceObjectChoiceValue('space_type', user_arguments, model)
|
152
|
-
if !space_type.empty?
|
153
|
-
space_type = space_type.get
|
154
|
-
if !space_type.to_SpaceType.empty?
|
155
|
-
space_type = space_type.to_SpaceType.get
|
156
|
-
zones = []
|
157
|
-
space_type.spaces.each do |space|
|
158
|
-
if !space.thermalZone.empty?
|
159
|
-
z = space.thermalZone.get
|
160
|
-
zones << z
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
elsif filter_type == "By Space Type's 'Standards Space Type'"
|
167
|
-
|
168
|
-
standards_space_type = runner.getOptionalStringArgumentValue('standards_space_type', user_arguments)
|
169
|
-
puts standards_space_type.class
|
170
|
-
|
171
|
-
if !standards_space_type.empty?
|
172
|
-
standards_space_type = standards_space_type.get
|
173
|
-
puts standards_space_type
|
174
|
-
space_types = model.getSpaceTypes
|
175
|
-
|
176
|
-
zones = []
|
177
|
-
|
178
|
-
space_types.each do |space_type|
|
179
|
-
if space_type.standardsSpaceType.to_s.casecmp(standards_space_type).zero?
|
180
|
-
space_type.spaces.each do |space|
|
181
|
-
if !space.thermalZone.empty?
|
182
|
-
z = space.thermalZone.get
|
183
|
-
# We MUST check if zone isn't in there yet (or at the end do zones.uniq!) because several spaces can refer to the same thermal zone!
|
184
|
-
if !zones.include?(z)
|
185
|
-
zones << z
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
else
|
194
|
-
# Zone filter
|
195
|
-
zone_filter = runner.getOptionalStringArgumentValue('zone_filter', user_arguments)
|
196
|
-
|
197
|
-
# Get all thermal zones
|
198
|
-
all_zones = model.getThermalZones
|
199
|
-
|
200
|
-
# Array to store the zones that match the filter
|
201
|
-
zones = []
|
202
|
-
all_zones.each do |z|
|
203
|
-
# Skip zone if name doesn't include zone_filter
|
204
|
-
# Putting everything in Upper Case to make it case insensitive
|
205
|
-
if !zone_filter.empty?
|
206
|
-
if z.name.to_s.upcase.include? zone_filter.to_s.upcase
|
207
|
-
zones << z
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
if zones.empty?
|
213
|
-
runner.registerError("Your zone filter #{zone_filter} did not match anything")
|
214
|
-
return false
|
215
|
-
end
|
216
|
-
|
217
|
-
end # End of if filter_type
|
218
|
-
|
219
|
-
# Output zone names to console
|
220
|
-
puts "\n\n================ ZONES THAT MATCHED THE FILTER ================\n"
|
221
|
-
zones.each do |z|
|
222
|
-
puts z.name
|
223
|
-
end
|
224
|
-
|
225
|
-
# info for initial condition
|
226
|
-
initial_num_air_loops_demand_control = 0
|
227
|
-
final_num_air_loops_demand_control = 0
|
228
|
-
initial_num_fan_VFD = 0
|
229
|
-
final_num_fan_VFD = 0
|
230
|
-
delete_existing_air_loops = 0
|
231
|
-
delete_existing_chiller_loops = 0
|
232
|
-
delete_existing_condenser_loops = 0
|
233
|
-
affected_loops = 0
|
234
|
-
|
235
|
-
# If we need to delete existing HVAC loops, we'll store the PRE-EXISTING Loops in the following variables,
|
236
|
-
# They will be used for clean up at the end
|
237
|
-
if delete_existing
|
238
|
-
air_loops = model.getAirLoopHVACs
|
239
|
-
runner.registerInfo("Number of initial AirLoopHVACs: #{air_loops.size}")
|
240
|
-
plant_loops = model.getPlantLoops
|
241
|
-
runner.registerInfo("Number of initial PlantLoops: #{plant_loops.size}")
|
242
|
-
end
|
243
|
-
|
244
|
-
# For each thermal zones (zones is initialized above, depending on which filter you chose)
|
245
|
-
zones.each do |z|
|
246
|
-
# Create a system 4 (PSZ-HP)
|
247
|
-
air_handler = OpenStudio::Model.addSystemType4(model).to_AirLoopHVAC.get
|
248
|
-
|
249
|
-
# Set name of Air Loop to be thermal_zone + 'Airloop'
|
250
|
-
# Local variable name convention for a non-constant (dynamic) value is 'snake_case'
|
251
|
-
base_name = z.name.to_s
|
252
|
-
air_handler.setName(base_name + ' AirLoop')
|
253
|
-
|
254
|
-
# Get existing fan, created with System 4, constant volume by default
|
255
|
-
old_fan = air_handler.supplyComponents(OpenStudio::Model::FanConstantVolume.iddObjectType).first
|
256
|
-
old_fan = old_fan.to_FanConstantVolume.get
|
257
|
-
|
258
|
-
# If you want a VFD, we replace it with a Variable Volume one
|
259
|
-
if has_vfd
|
260
|
-
|
261
|
-
# Get the outlet node after the existing fan on the loop
|
262
|
-
next_node = old_fan.outletModelObject.get.to_Node.get
|
263
|
-
|
264
|
-
# Create the new Variable speed fan
|
265
|
-
fan = OpenStudio::Model::FanVariableVolume.new(model)
|
266
|
-
|
267
|
-
# Add the new fan to the oulet node of the existing fan
|
268
|
-
# before deleting the existing one
|
269
|
-
fan.addToNode(next_node)
|
270
|
-
|
271
|
-
# Remove the existing fan. When this happens, either the pump's
|
272
|
-
# inlet or outlet node will be deleted and the other will remain
|
273
|
-
old_fan.remove
|
274
|
-
|
275
|
-
# Rename the fan clearly
|
276
|
-
fan.setName(base_name + ' Variable Volume Fan')
|
277
|
-
|
278
|
-
# If fan_pressure_rise has a non zero null value, assign it.
|
279
|
-
if !fan_pressure_rise.empty?
|
280
|
-
# We need the .get because this is an OptionalDouble. the .get will return a Double (float)
|
281
|
-
fan.setPressureRise(fan_pressure_rise.get)
|
282
|
-
runner.registerInfo("Fan '#{fan.name}' was assigned pressure rise of '#{fan_pressure_rise.get}' Pa")
|
283
|
-
end
|
284
|
-
|
285
|
-
final_num_fan_VFD += 1
|
286
|
-
|
287
|
-
else
|
288
|
-
# If VFD isn't wanted, we just rename the constant volume fan
|
289
|
-
old_fan.setName(base_name + ' Constant Volume Fan')
|
290
|
-
|
291
|
-
# If fan_pressure_rise has a non zero null value, assign it.
|
292
|
-
if !fan_pressure_rise.empty?
|
293
|
-
# We need the .get because this is an OptionalDouble. the .get will return a Double (float)
|
294
|
-
old_fan.setPressureRise(fan_pressure_rise.get)
|
295
|
-
puts "Fan '#{old_fan.name}' was assigned pressure rise of '#{fan_pressure_rise.get}' Pa"
|
296
|
-
end
|
297
|
-
|
298
|
-
end
|
299
|
-
|
300
|
-
# The Cooling coil expects an OptionalDouble
|
301
|
-
coil = air_handler.supplyComponents(OpenStudio::Model::CoilCoolingDXSingleSpeed.iddObjectType).first
|
302
|
-
coil = coil.to_CoilCoolingDXSingleSpeed.get
|
303
|
-
# Set CoolingCoil COP
|
304
|
-
coil.setRatedCOP(OpenStudio::OptionalDouble.new(cop_cooling))
|
305
|
-
# Set CoolingCoil Name
|
306
|
-
coil.setName(base_name + ' Coil Cooling DX Single Speed')
|
307
|
-
|
308
|
-
# The Heating coil expects a Double
|
309
|
-
coilheating = air_handler.supplyComponents(OpenStudio::Model::CoilHeatingDXSingleSpeed.iddObjectType).first
|
310
|
-
coilheating = coilheating.to_CoilHeatingDXSingleSpeed.get
|
311
|
-
# Set HeatingCoil COP
|
312
|
-
coilheating.setRatedCOP(cop_heating)
|
313
|
-
# Set HeatingCoil Name
|
314
|
-
coilheating.setName(base_name + ' Coil Heating DX Single Speed')
|
315
|
-
|
316
|
-
# Delete the electric heating coil if unwanted
|
317
|
-
if !has_electric_coil
|
318
|
-
coilheatingelec = air_handler.supplyComponents(OpenStudio::Model::CoilHeatingElectric.iddObjectType).first
|
319
|
-
coilheatingelec.remove
|
320
|
-
end
|
321
|
-
|
322
|
-
# Enable DCV (dunno if working)
|
323
|
-
if has_dcv
|
324
|
-
|
325
|
-
# get air_handler supply components
|
326
|
-
supply_components = air_handler.supplyComponents
|
327
|
-
|
328
|
-
# find AirLoopHVACOutdoorAirSystem on loop
|
329
|
-
supply_components.each do |supply_component|
|
330
|
-
hVACComponent = supply_component.to_AirLoopHVACOutdoorAirSystem
|
331
|
-
if !hVACComponent.empty?
|
332
|
-
hVACComponent = hVACComponent.get
|
333
|
-
|
334
|
-
# get ControllerOutdoorAir
|
335
|
-
controller_oa = hVACComponent.getControllerOutdoorAir
|
336
|
-
controller_oa.setName(base_name + ' Controller Outdoor Air')
|
337
|
-
|
338
|
-
# get ControllerMechanicalVentilation
|
339
|
-
controller_mv = controller_oa.controllerMechanicalVentilation
|
340
|
-
|
341
|
-
# check if demand control is enabled, if not, then enable it
|
342
|
-
if controller_mv.demandControlledVentilation == true
|
343
|
-
initial_num_air_loops_demand_control += 1
|
344
|
-
else
|
345
|
-
controller_mv.setDemandControlledVentilation(true)
|
346
|
-
puts "Enabling demand control ventilation for #{air_handler.name}"
|
347
|
-
end # End of if
|
348
|
-
final_num_air_loops_demand_control += 1
|
349
|
-
|
350
|
-
end # End of HVACComponent.empty?
|
351
|
-
end # end of supply component do loop
|
352
|
-
|
353
|
-
end # End of has_dcv loop
|
354
|
-
|
355
|
-
# Add a branch for the zone in question
|
356
|
-
air_handler.addBranchForZone(z)
|
357
|
-
|
358
|
-
# Counter
|
359
|
-
affected_loops += 1
|
360
|
-
end # end of do loop on each thermal zone
|
361
|
-
|
362
|
-
# CLEAN-UP SECTION
|
363
|
-
# Idea: loop on PRE-EXISTING AirLoops, delete all that don't have any zones anymore
|
364
|
-
# Then loop on chiller loop, delete all that don't have a coil connected to an air loop
|
365
|
-
# then loop on condenser water, delette all that don't have a chiller anymore
|
366
|
-
|
367
|
-
# If we need to delete existing HVAC loops, we'll loop on the PRE-EXISTING Loops we stored earlier
|
368
|
-
if delete_existing
|
369
|
-
|
370
|
-
# Arrays to store the affected loops
|
371
|
-
chiller_plant_loops = []
|
372
|
-
boiler_plant_loops = []
|
373
|
-
condenser_plant_loops = []
|
374
|
-
|
375
|
-
# Display separator for clarity
|
376
|
-
runner.registerInfo('')
|
377
|
-
runner.registerInfo('========================== CLEAN-UP: AIR LOOPS ==========================')
|
378
|
-
|
379
|
-
# Loop on the pre-existing air loops (not the ones that were created above)
|
380
|
-
air_loops.each do |air_loop|
|
381
|
-
# Check if it's got a thermal zone attached left or not..
|
382
|
-
# We assume we'll delete it unless...
|
383
|
-
delete_flag = true
|
384
|
-
|
385
|
-
air_loop.demandComponents.each do |comp|
|
386
|
-
# If there is at least a single zone left, we can't delete it
|
387
|
-
if comp.to_ThermalZone.is_initialized
|
388
|
-
delete_flag = false
|
389
|
-
end # end of if
|
390
|
-
end # end of do loop on comp
|
391
|
-
|
392
|
-
# If deletion is warranted
|
393
|
-
if delete_flag
|
394
|
-
# before deletion, let's get the potential associated plant loop.
|
395
|
-
if air_loop.supplyComponents(OpenStudio::Model::CoilCoolingWater.iddObjectType).empty?
|
396
|
-
puts "Air loop '#{air_loop.name}' DOES NOT HAVE a CoilHeatingWater"
|
397
|
-
else
|
398
|
-
cooling_coil = air_loop.supplyComponents(OpenStudio::Model::CoilCoolingWater.iddObjectType).first.to_CoilCoolingWater.get
|
399
|
-
chiller_plant_loop = cooling_coil.plantLoop.get
|
400
|
-
# Store handle in array
|
401
|
-
chiller_plant_loops << chiller_plant_loop
|
402
|
-
runner.registerInfo("Air loop '#{air_loop.name}' has a CoilCoolingWater, connected to CHILLER plant loop '#{chiller_plant_loop.name}'")
|
403
|
-
end
|
404
|
-
if air_loop.supplyComponents(OpenStudio::Model::CoilHeatingWater.iddObjectType).empty?
|
405
|
-
puts "Air loop '#{air_loop.name}' DOES NOT HAVE a CoilHeatingWater"
|
406
|
-
else
|
407
|
-
heating_coil = air_loop.supplyComponents(OpenStudio::Model::CoilCoolingWater.iddObjectType).first.to_CoilCoolingWater.get
|
408
|
-
boiler_plant_loop = heating_coil.plantLoop.get
|
409
|
-
# Store handle in array
|
410
|
-
boiler_plant_loops << boiler_plant_loop
|
411
|
-
runner.registerInfo("Air loop '#{air_loop.name}' has a CoilHeatinggWater, connected to BOILER plant loop '#{boiler_plant_loop.name}'")
|
412
|
-
end
|
413
|
-
|
414
|
-
# Now we can delete and report.
|
415
|
-
air_loop.remove
|
416
|
-
runner.registerInfo("DELETED: Air loop '#{air_loop.name}' doesn't have Thermal zones attached and was removed")
|
417
|
-
delete_existing_air_loops += 1
|
418
|
-
else
|
419
|
-
runner.registerInfo("Air Loop '#{air_loop.name}' has thermal zones and was not deleted")
|
420
|
-
end # end if delete_flag
|
421
|
-
end # end air_loops.each do
|
422
|
-
|
423
|
-
# Display separator for clarity
|
424
|
-
runner.registerInfo('')
|
425
|
-
runner.registerInfo('====================== CLEAN-UP: CHILLER PLANT LOOPS ======================')
|
426
|
-
|
427
|
-
# First pass on plant loops: chilled water loops.
|
428
|
-
chiller_plant_loops.each do |chiller_plant_loop|
|
429
|
-
puts "Chiller plant loop name: #{chiller_plant_loop.name}"
|
430
|
-
|
431
|
-
# Check if the chiller plant loop has remaining demand components
|
432
|
-
|
433
|
-
# Delete flag: first assumption is that yes... unless!
|
434
|
-
delete_flag = true
|
435
|
-
|
436
|
-
if chiller_plant_loop.demandComponents(OpenStudio::Model::CoilCoolingWater.iddObjectType).empty?
|
437
|
-
puts "Chiller Plant loop '#{chiller_plant_loop.name}' DOES NOT HAVE a CoilCoolingWater"
|
438
|
-
else
|
439
|
-
puts "Chiller Plant loop '#{chiller_plant_loop.name}' has a CoilCoolingWater"
|
440
|
-
cooling_coil = chiller_plant_loop.demandComponents(OpenStudio::Model::CoilCoolingWater.iddObjectType).first.to_CoilCoolingWater.get
|
441
|
-
if cooling_coil.airLoopHVAC.empty?
|
442
|
-
puts "But Cooling coil '#{cooling_coil.name}' is not connected to any airloopHVAC"
|
443
|
-
else
|
444
|
-
runner.registerInfo("And Cooling coil '#{cooling_coil.name}' is connected to airloopHVAC '#{cooling_coil.airLoopHVAC.get.name}' and therefore can't be deleted")
|
445
|
-
# In this case, we can't delete the chiller plant loop
|
446
|
-
delete_flag = false
|
447
|
-
end # end cooling_coil.airLoopHVAC.empty?
|
448
|
-
|
449
|
-
end # end of chiller_plant_loop.demandComponents CoilCoolingWater
|
450
|
-
|
451
|
-
# We know it's a chiller plant so this is likely unnecessary, but better safe than sorry
|
452
|
-
if chiller_plant_loop.demandComponents(OpenStudio::Model::WaterUseConnections.iddObjectType).empty?
|
453
|
-
puts "Chiller Plant loop '#{chiller_plant_loop.name}' DOES NOT HAVE WaterUseConnections"
|
454
|
-
else
|
455
|
-
runner.registerInfo("Chiller Plant loop '#{chiller_plant_loop.name}' has WaterUseConnections and therefore can't be deleted")
|
456
|
-
delete_flag = false
|
457
|
-
end
|
458
|
-
|
459
|
-
# If deletion is warranted
|
460
|
-
if delete_flag
|
461
|
-
|
462
|
-
# This section below is actually optional (but it's nice to only delete affected ones
|
463
|
-
# before deletion, let's get the potential associated condenser water plant loop.
|
464
|
-
if chiller_plant_loop.supplyComponents(OpenStudio::Model::ChillerElectricEIR.iddObjectType).empty?
|
465
|
-
puts "Chiller Plant loop '#{chiller_plant_loop.name}' DOES NOT HAVE an electric chiller"
|
466
|
-
else
|
467
|
-
chiller = chiller_plant_loop.supplyComponents(OpenStudio::Model::ChillerElectricEIR.iddObjectType).first.to_ChillerElectricEIR.get
|
468
|
-
puts "Chiller Plant loop '#{chiller_plant_loop.name}' has an electric chiller '#{chiller.name}' with condenser type '#{chiller.condenserType}'"
|
469
|
-
# Check directly if chiller has a secondaryPlantLoop (no need to check if chiller.condenserType == 'WaterCooled' first)
|
470
|
-
if chiller.secondaryPlantLoop.is_initialized
|
471
|
-
# Chiller is WaterCooled therefore should be connected to a condenser water loop
|
472
|
-
condenser_plant_loop = chiller.secondaryPlantLoop.get
|
473
|
-
condenser_plant_loops << condenser_plant_loop
|
474
|
-
runner.registerInfo("Chiller PlantLoop '#{chiller_plant_loop.name}' has a Water Cooled chiller connected to Condenser Plant Loop '#{condenser_plant_loop.name}'")
|
475
|
-
end
|
476
|
-
end
|
477
|
-
|
478
|
-
# Now we can delete and report.
|
479
|
-
chiller_plant_loop.remove
|
480
|
-
delete_existing_chiller_loops += 1
|
481
|
-
# Should I delete the chiller as well? It remains...
|
482
|
-
|
483
|
-
runner.registerInfo("DELETED: Chiller PlantLoop '#{chiller_plant_loop.name}' wasn't connected to any AirLoopHVAC nor WaterUseConnections and therefore was removed")
|
484
|
-
|
485
|
-
end # end of delete_flag
|
486
|
-
end # end of chiller_plant_loops.each do
|
487
|
-
|
488
|
-
# Display separator for clarity
|
489
|
-
runner.registerInfo('')
|
490
|
-
runner.registerInfo('===================== CLEAN-UP: CONDENSER PLANT LOOPS ====================')
|
491
|
-
# Second pass on plant loops: condenser water loops.
|
492
|
-
condenser_plant_loops.each do |condenser_plant_loop|
|
493
|
-
delete_flag = true
|
494
|
-
|
495
|
-
# If it has got a chiller as a demand component, it could still be empty
|
496
|
-
if !condenser_plant_loop.demandComponents(OpenStudio::Model::ChillerElectricEIR.iddObjectType).empty?
|
497
|
-
|
498
|
-
chiller = condenser_plant_loop.demandComponents(OpenStudio::Model::ChillerElectricEIR.iddObjectType).first.to_ChillerElectricEIR.get
|
499
|
-
|
500
|
-
# If chiller is actually connected to a chilled water node, then we shall not delete it
|
501
|
-
if !chiller.chilledWaterInletNodeName.empty?
|
502
|
-
runner.registerInfo("On Condenser PlantLoop '#{condenser_plant_loop.name}, there is a demand component of type Chiller '#{chiller.name}'" \
|
503
|
-
' that is connected to a chilled water loop and therefore cannot be deleted')
|
504
|
-
delete_flag = false
|
505
|
-
else
|
506
|
-
puts "Plant loop '#{condenser_plant_loop.name}, Chiller '#{chiller.name}' isn't connected to a chilled water loop"
|
507
|
-
end # end of if chiller.chilledWaterInletNodeName
|
508
|
-
end # end of plant_loop.demandComponents
|
509
|
-
|
510
|
-
# if deletion is warranted
|
511
|
-
if delete_flag
|
512
|
-
condenser_plant_loop.remove
|
513
|
-
delete_existing_condenser_loops += 1
|
514
|
-
runner.registerInfo("DELETED: Plant loop '#{condenser_plant_loop.name}' isn't connected to any chilled water loop")
|
515
|
-
end
|
516
|
-
end
|
517
|
-
|
518
|
-
runner.registerInfo('')
|
519
|
-
runner.registerInfo("For more information, go to 'Advanced Output'")
|
520
|
-
|
521
|
-
# This is the generic way of looping on all loops, checking if it's a condenser plant loop, and to delete it unless it's got a chiller that is connected to chilled water plant loop
|
522
|
-
# plant_loops.each do |plant_loop|
|
523
|
-
# # Skip the chiller_plant_loops
|
524
|
-
# #next if chiller_plant_loops.include? plant_loop
|
525
|
-
# if chiller_plant_loops.include? plant_loop
|
526
|
-
# runner.registerInfo("Skipping Plant loop '#{plant_loop.name}' because it is a chiller plant")
|
527
|
-
# next
|
528
|
-
# end
|
529
|
-
# runner.registerInfo("Plant loop '#{plant_loop.name}'")
|
530
|
-
#
|
531
|
-
# # Until we know that it is a condenser loop for sure, we assume we can't delete it
|
532
|
-
# delete_flag = false
|
533
|
-
#
|
534
|
-
# # If it has got a chiller as a demand component, it's a condenser water loop
|
535
|
-
# if not plant_loop.demandComponents(OpenStudio::Model::ChillerElectricEIR::iddObjectType).empty?
|
536
|
-
# # Now, we assume we'll delete the loop unless it's actually connected and therefore usefull
|
537
|
-
# delete_flag = true
|
538
|
-
# chiller = plant_loop.demandComponents(OpenStudio::Model::ChillerElectricEIR::iddObjectType).first.to_ChillerElectricEIR.get
|
539
|
-
# # If chiller is actually connected to a chilled water node, then we shall not delete it
|
540
|
-
# if not chiller.chilledWaterInletNodeName.empty?
|
541
|
-
# runner.registerInfo("On Condenser PlantLoop '#{plant_loop.name}, there is a demand component of type Chiller '#{chiller.name}'" +
|
542
|
-
# " that is connected to a chilled water loop and therefore cannot be deleted")
|
543
|
-
# delete_flag = false
|
544
|
-
# else
|
545
|
-
# runner.registerInfo("Plant loop '#{plant_loop.name}, Chiller '#{chiller.name}' isn't connected to a chilled water loop")
|
546
|
-
# end #end of if chiller.chilledWaterInletNodeName
|
547
|
-
# end #end of plant_loop.demandComponents
|
548
|
-
#
|
549
|
-
# # if deletion is warranted
|
550
|
-
# if delete_flag
|
551
|
-
# plant_loop.remove
|
552
|
-
# delete_existing_condenser_loops += 1
|
553
|
-
# runner.registerInfo("DELETED: Plant loop '#{plant_loop.name}'")
|
554
|
-
# end
|
555
|
-
#
|
556
|
-
# end #end of plant_loops.each do
|
557
|
-
|
558
|
-
# Third pass on plant loops: boiler water loops.
|
559
|
-
# TO WRITE
|
560
|
-
|
561
|
-
end # end of if delete_existing
|
562
|
-
|
563
|
-
# Report Initial Condition
|
564
|
-
if delete_existing
|
565
|
-
air_loop_str = "\n #{delete_existing_air_loops} existing AirLoopHVACs have been deleted"
|
566
|
-
chiller_plant_loop_str = "\n #{delete_existing_chiller_loops} existing Chiller PlantLoops have been deleted"
|
567
|
-
condenser_plant_loop_str = "\n #{delete_existing_condenser_loops} existing Condenser PlantLoops have been deleted"
|
568
|
-
else
|
569
|
-
air_loop_str = ''
|
570
|
-
chiller_plant_loop_str = ''
|
571
|
-
condenser_plant_loop_str = ''
|
572
|
-
end # end of delete_existing
|
573
|
-
|
574
|
-
runner.registerInitialCondition("Initially #{initial_num_air_loops_demand_control} air loops had demand controlled ventilation enabled" +
|
575
|
-
air_loop_str + chiller_plant_loop_str + condenser_plant_loop_str + "\n")
|
576
|
-
|
577
|
-
# Report final condition
|
578
|
-
base_str = "There are #{OpenStudio.toNeatString(affected_loops, 0, true)} zones for which a PSZ-HP system was " \
|
579
|
-
"created with a Cooling COP (SI) of #{OpenStudio.toNeatString(cop_cooling, 2, true)} " \
|
580
|
-
"and a Heating COP (SI) of #{OpenStudio.toNeatString(cop_heating, 2, true)}."
|
581
|
-
|
582
|
-
if has_electric_coil
|
583
|
-
elec_str = 'Supplementary electric heating coils were added.'
|
584
|
-
else
|
585
|
-
elec_str = 'Supplementary electrical heating coils were NOT included.'
|
586
|
-
end # end of has_electric_coil
|
587
|
-
|
588
|
-
if has_vfd
|
589
|
-
fan_str = "Fan type was changed to be Variable Volume (VFD) for #{final_num_fan_VFD} fans."
|
590
|
-
else
|
591
|
-
fan_str = 'Fan type was chosen to be Constant Volume.'
|
592
|
-
end # end of has_vfd
|
593
|
-
|
594
|
-
if final_num_air_loops_demand_control == 0
|
595
|
-
dcv_str = "Demand Controlled Ventilation wasn't enabled for the new air loops"
|
596
|
-
else
|
597
|
-
dcv_str = "#{final_num_air_loops_demand_control} air loops now have demand controlled ventilation enabled"
|
598
|
-
end
|
599
|
-
|
600
|
-
runner.registerFinalCondition(base_str + "\n" + elec_str + "\n" + fan_str + "\n" + dcv_str + "\n \n")
|
601
|
-
|
602
|
-
return true
|
603
|
-
end # end the run method
|
604
|
-
end # end the measure
|
605
|
-
|
606
|
-
# this allows the measure to be used by the application
|
607
|
-
AddAPSZHPToEachZone.new.registerWithApplication
|