openstudio-standards 0.6.3 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
- data/data/standards/manage_OpenStudio_Standards.rb +2 -49
- data/data/standards/openstudio_standards_duplicates_log.csv +1 -7962
- data/data/standards/test_performance_expected_dd_results.csv +2005 -97
- data/lib/openstudio-standards/create_typical/space_type_ratios.rb +47 -57
- data/lib/openstudio-standards/geometry/create.rb +8 -2
- data/lib/openstudio-standards/geometry/create_bar.rb +6 -3
- data/lib/openstudio-standards/geometry/create_shape.rb +1 -1
- data/lib/openstudio-standards/geometry/group.rb +1 -1
- data/lib/openstudio-standards/geometry/information.rb +1 -1
- data/lib/openstudio-standards/geometry/modify.rb +53 -1
- data/lib/openstudio-standards/infiltration/nist_infiltration.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +11 -11
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +11 -11
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +44 -47
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +43 -48
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CentralAirSourceHeatPump.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +44 -24
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +24 -24
- data/lib/openstudio-standards/schedules/information.rb +1 -1
- data/lib/openstudio-standards/schedules/parametric.rb +1 -1
- data/lib/openstudio-standards/service_water_heating/create_piping_losses.rb +152 -0
- data/lib/openstudio-standards/service_water_heating/create_water_heater.rb +544 -0
- data/lib/openstudio-standards/service_water_heating/create_water_heating_loop.rb +303 -0
- data/lib/openstudio-standards/service_water_heating/create_water_use.rb +95 -0
- data/lib/openstudio-standards/space/space.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +65 -70
- data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +12 -14
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +16 -5
- data/lib/openstudio-standards/standards/Standards.Model.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +10 -2
- data/lib/openstudio-standards/{prototypes/common/objects/Prototype.Model.swh.rb → standards/Standards.ServiceWaterHeating.rb} +209 -139
- data/lib/openstudio-standards/standards/Standards.Surface.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +4 -8
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +22251 -12963
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_sets.json +91 -91
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +8981 -5228
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +8935 -5182
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +7281 -5391
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_sets.json +91 -91
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_properties.json +9005 -15215
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_sets.json +136 -136
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_properties.json +8717 -17168
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_sets.json +136 -136
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +1941 -651
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.construction_properties.json +135 -135
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.construction_properties.json +135 -135
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/data/nrel_zne_ready_2017.construction_properties.json +36 -36
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/data/ze_aedg_multifamily.construction_properties.json +36 -36
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +377 -99
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +3 -3
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +6889 -4044
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_constructions.json +108 -108
- data/lib/openstudio-standards/standards/cbes/cbes_pre_1978/data/cbes_pre_1978.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_1978/data/cbes_t24_1978.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_1992/data/cbes_t24_1992.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2001/data/cbes_t24_2001.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/data/cbes_t24_2005.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/data/cbes_t24_2008.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/data/cbes.constructions.json +142 -142
- data/lib/openstudio-standards/standards/deer/data/deer.constructions.json +5 -1551
- data/lib/openstudio-standards/standards/deer/data/deer.materials.json +40 -0
- data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.motors.json +88 -8
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +17 -0
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +2 -1
- data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +4 -4
- data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +61 -88
- data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +3 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/data/boiler_fuel_type_sets.json +54 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMidriseApartment.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMultiTower.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPPointTower.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPTownHouse.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +4 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +4 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +32 -24
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +89 -15
- data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +5 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +22 -65
- data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +19 -0
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +56 -2
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +3 -1
- data/lib/openstudio-standards/standards/necb/common/construction_defaults.osm +2 -2
- data/lib/openstudio-standards/standards/necb/docs/air_system_names_method.md +127 -0
- data/lib/openstudio-standards/thermal_zone/thermal_zone.rb +1 -1
- data/lib/openstudio-standards/utilities/template_measure/resources/BTAPMeasureHelper.rb +1 -1
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards/weather/information.rb +61 -5
- data/lib/openstudio-standards/weather/modify.rb +1 -1
- data/lib/openstudio-standards.rb +5 -3
- metadata +12 -63
- data/data/standards/OpenStudio_Standards-deer.xlsx +0 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +0 -1100
- data/lib/openstudio-standards/service_water_heating/component.rb +0 -189
@@ -92,22 +92,16 @@ class ASHRAE901PRM < Standard
|
|
92
92
|
end
|
93
93
|
|
94
94
|
# Splits the single chiller used for the initial sizing run
|
95
|
-
# into multiple separate chillers based on Appendix G.
|
96
|
-
#
|
95
|
+
# into multiple separate chillers based on Appendix G. Also applies
|
96
|
+
# EMS to stage chillers properly
|
97
97
|
# @param plant_loop [OpenStudio::Model::PlantLoop] chilled water loop
|
98
|
-
# @param sizing_run_dir [String] sizing run directory
|
99
98
|
# @return [Boolean] returns true if successful, false if not
|
100
|
-
def plant_loop_apply_prm_number_of_chillers(plant_loop
|
99
|
+
def plant_loop_apply_prm_number_of_chillers(plant_loop)
|
101
100
|
# Skip non-cooling plants & secondary cooling loop
|
102
101
|
return true unless plant_loop.sizingPlant.loopType == 'Cooling'
|
103
102
|
# If the loop is cooling but it is a secondary loop, then skip.
|
104
103
|
return true if plant_loop.additionalProperties.hasFeature('is_secondary_loop')
|
105
104
|
|
106
|
-
# Determine the number and type of chillers
|
107
|
-
num_chillers = nil
|
108
|
-
chiller_cooling_type = nil
|
109
|
-
chiller_compressor_type = nil
|
110
|
-
|
111
105
|
# Set the equipment to stage sequentially or uniformload if there is secondary loop
|
112
106
|
if plant_loop.additionalProperties.hasFeature('is_primary_loop')
|
113
107
|
plant_loop.setLoadDistributionScheme('UniformLoad')
|
@@ -115,9 +109,55 @@ class ASHRAE901PRM < Standard
|
|
115
109
|
plant_loop.setLoadDistributionScheme('SequentialLoad')
|
116
110
|
end
|
117
111
|
|
112
|
+
model = plant_loop.model
|
113
|
+
|
114
|
+
# Get all existing chillers and pumps. Copy chiller properties needed when duplicating existing settings
|
115
|
+
chillers = []
|
116
|
+
pumps = []
|
117
|
+
default_cop = nil
|
118
|
+
condenser_water_loop = nil
|
119
|
+
dsgn_sup_wtr_temp_c = nil
|
120
|
+
|
121
|
+
plant_loop.supplyComponents.each do |sc|
|
122
|
+
if sc.to_ChillerElectricEIR.is_initialized
|
123
|
+
chiller = sc.to_ChillerElectricEIR.get
|
124
|
+
|
125
|
+
# Copy the last chillers COP, leaving chilled water temperature, and reference cooling tower. These will be the
|
126
|
+
# default for any extra chillers.
|
127
|
+
default_cop = chiller.referenceCOP
|
128
|
+
dsgn_sup_wtr_temp_c = chiller.referenceLeavingChilledWaterTemperature
|
129
|
+
condenser_water_loop = chiller.condenserWaterLoop
|
130
|
+
chillers << chiller
|
131
|
+
|
132
|
+
elsif sc.to_PumpConstantSpeed.is_initialized
|
133
|
+
pumps << sc.to_PumpConstantSpeed.get
|
134
|
+
elsif sc.to_PumpVariableSpeed.is_initialized
|
135
|
+
pumps << sc.to_PumpVariableSpeed.get
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Get existing plant loop pump. We'll copy this pumps parameters before removing it. Throw exception for multiple pumps on supply side
|
140
|
+
if pumps.size.zero?
|
141
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps. A loop must have at least one pump.")
|
142
|
+
return false
|
143
|
+
elsif pumps.size > 1
|
144
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, found #{pumps.size} pumps, cannot split up per performance rating method baseline requirements.")
|
145
|
+
return false
|
146
|
+
else
|
147
|
+
original_pump = pumps[0]
|
148
|
+
end
|
149
|
+
|
150
|
+
return true if chillers.empty?
|
151
|
+
|
118
152
|
# Determine the capacity of the loop
|
119
153
|
cap_w = plant_loop_total_cooling_capacity(plant_loop)
|
120
154
|
cap_tons = OpenStudio.convert(cap_w, 'W', 'ton').get
|
155
|
+
|
156
|
+
# Throw exception for > 2,400 tons as this breaks our staging strategy cap of 3 chillers
|
157
|
+
if cap_tons > 2400
|
158
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, the total capacity (#{cap_w}) exceeded 2400 tons and would require more than 3 chillers. The existing code base cannot accommodate the staging required for this")
|
159
|
+
end
|
160
|
+
|
121
161
|
if cap_tons <= 300
|
122
162
|
num_chillers = 1
|
123
163
|
chiller_cooling_type = 'WaterCooled'
|
@@ -136,114 +176,352 @@ class ASHRAE901PRM < Standard
|
|
136
176
|
chiller_compressor_type = 'Centrifugal'
|
137
177
|
end
|
138
178
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
179
|
+
if chillers.length > num_chillers
|
180
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, the existing number of chillers exceeds the recommended amount. We have not accounted for this in the codebase yet.")
|
181
|
+
end
|
182
|
+
|
183
|
+
# Determine the per-chiller capacity and sizing factor
|
184
|
+
per_chiller_sizing_factor = (1.0 / num_chillers).round(2)
|
185
|
+
per_chiller_cap_w = cap_w / num_chillers
|
186
|
+
|
187
|
+
# Set the sizing factor and the chiller types
|
188
|
+
# chillers.each_with_index do |chiller, i|
|
189
|
+
for i in 0..num_chillers - 1
|
190
|
+
# if not enough chillers exist, create a new one. Else reference the i'th chiller
|
191
|
+
if i <= chillers.length - 1
|
192
|
+
chiller = chillers[i]
|
193
|
+
else
|
194
|
+
chiller = OpenStudio::Model::ChillerElectricEIR.new(model)
|
195
|
+
plant_loop.addSupplyBranchForComponent(chiller)
|
196
|
+
chiller.setReferenceLeavingChilledWaterTemperature(dsgn_sup_wtr_temp_c)
|
197
|
+
chiller.setLeavingChilledWaterLowerTemperatureLimit(OpenStudio.convert(36.0, 'F', 'C').get)
|
198
|
+
chiller.setReferenceEnteringCondenserFluidTemperature(OpenStudio.convert(95.0, 'F', 'C').get)
|
199
|
+
chiller.setMinimumPartLoadRatio(0.15)
|
200
|
+
chiller.setMaximumPartLoadRatio(1.0)
|
201
|
+
chiller.setOptimumPartLoadRatio(1.0)
|
202
|
+
chiller.setMinimumUnloadingRatio(0.25)
|
203
|
+
chiller.setChillerFlowMode('ConstantFlow')
|
204
|
+
chiller.setReferenceCOP(default_cop)
|
205
|
+
|
206
|
+
condenser_water_loop.get.addDemandBranchForComponent(chiller) if condenser_water_loop.is_initialized
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
chiller.setName("#{template} #{chiller_cooling_type} #{chiller_compressor_type} Chiller #{i + 1} of #{num_chillers}")
|
211
|
+
chiller.setSizingFactor(per_chiller_sizing_factor)
|
212
|
+
chiller.setReferenceCapacity(per_chiller_cap_w)
|
213
|
+
chiller.setCondenserType(chiller_cooling_type)
|
214
|
+
chiller.additionalProperties.setFeature('compressor_type', chiller_compressor_type)
|
215
|
+
|
216
|
+
# Add inlet pump
|
217
|
+
new_pump = OpenStudio::Model::PumpVariableSpeed.new(plant_loop.model)
|
218
|
+
new_pump.setName("#{chiller.name} Inlet Pump")
|
219
|
+
new_pump.setRatedPumpHead(original_pump.ratedPumpHead / num_chillers)
|
220
|
+
|
221
|
+
pump_variable_speed_set_control_type(new_pump, control_type = 'Riding Curve')
|
222
|
+
chiller_inlet_node = chiller.connectedObject(chiller.supplyInletPort).get.to_Node.get
|
223
|
+
new_pump.addToNode(chiller_inlet_node)
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
# Remove original pump, dedicated chiller pumps have all been added
|
228
|
+
original_pump.remove
|
229
|
+
|
230
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, there are #{chillers.size} #{chiller_cooling_type} #{chiller_compressor_type} chillers.")
|
231
|
+
|
232
|
+
# Check for a heat exchanger fluid to fluid-- that lets you know if this is a primary loop
|
233
|
+
has_secondary_plant_loop = !plant_loop.demandComponents(OpenStudio::Model::HeatExchangerFluidToFluid.iddObjectType).empty?
|
234
|
+
|
235
|
+
if has_secondary_plant_loop
|
236
|
+
# Add EMS to stage chillers if there's a primary/secondary configuration
|
237
|
+
if num_chillers > 3
|
238
|
+
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name} has more than 3 chillers. We do not have an EMS strategy for that yet.")
|
239
|
+
elsif num_chillers > 1
|
240
|
+
add_ems_for_multiple_chiller_pumps_w_secondary_plant(model, plant_loop)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
return true
|
245
|
+
end
|
246
|
+
|
247
|
+
# Adds EMS program for pumps serving 3 chillers on primary + secondary loop. This was due to an issue when modeling two
|
248
|
+
# dedicated loops. The headered pumps or dedicated constant speed pumps operate at full flow as long as there's a
|
249
|
+
# load on the loop unless this EMS is in place.
|
250
|
+
# @param model [OpenStudio::Model] OpenStudio model with plant loops
|
251
|
+
# @param primary_plant [OpenStudio::Model::PlantLoop] Primary chilled water loop with chillers
|
252
|
+
def add_ems_for_multiple_chiller_pumps_w_secondary_plant(model, primary_plant)
|
253
|
+
# Aggregate array of chillers on primary plant supply side
|
254
|
+
chiller_list = []
|
255
|
+
|
256
|
+
primary_plant.supplyComponents.each do |sc|
|
143
257
|
if sc.to_ChillerElectricEIR.is_initialized
|
144
|
-
|
145
|
-
elsif sc.to_PumpConstantSpeed.is_initialized
|
146
|
-
pumps << sc.to_PumpConstantSpeed.get
|
147
|
-
elsif sc.to_PumpVariableSpeed.is_initialized
|
148
|
-
pumps << sc.to_PumpVariableSpeed.get
|
258
|
+
chiller_list << sc.to_ChillerElectricEIR.get
|
149
259
|
end
|
150
260
|
end
|
151
261
|
|
152
|
-
|
153
|
-
first_chiller = nil
|
154
|
-
return true if chillers.empty?
|
262
|
+
num_of_chillers = chiller_list.length # Either 2 or 3
|
155
263
|
|
156
|
-
if
|
157
|
-
|
158
|
-
|
159
|
-
|
264
|
+
return if num_of_chillers <= 1
|
265
|
+
|
266
|
+
plant_name = primary_plant.name.to_s
|
267
|
+
|
268
|
+
# Make a variable to track the chilled water demand
|
269
|
+
chw_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, 'Plant Supply Side Cooling Demand Rate')
|
270
|
+
chw_sensor.setKeyName(plant_name)
|
271
|
+
chw_sensor.setName("#{plant_name.gsub(/[-\s]+/, '_')}_CHW_DEMAND")
|
272
|
+
|
273
|
+
# Sort chillers by their reference capacity
|
274
|
+
sorted_chiller_list = chiller_list.sort_by { |chiller| chiller.referenceCapacity.get.to_f}
|
275
|
+
|
276
|
+
# Make pump specific parameters for EMS. Use counter
|
277
|
+
sorted_chiller_list.each_with_index do |chiller, i|
|
278
|
+
# Get chiller pump
|
279
|
+
pump_name = "#{chiller.name} Inlet Pump"
|
280
|
+
pump = model.getPumpVariableSpeedByName(pump_name).get
|
281
|
+
|
282
|
+
# Set EMS names
|
283
|
+
ems_pump_flow_name = "CHILLER_PUMP_#{i + 1}_FLOW"
|
284
|
+
ems_pump_status_name = "CHILLER_PUMP_#{i + 1}_STATUS"
|
285
|
+
ems_pump_design_flow_name = "CHILLER_PUMP_#{i + 1}_DES_FLOW"
|
286
|
+
|
287
|
+
# ---- Actuators ----
|
288
|
+
|
289
|
+
# Pump Flow Actuator
|
290
|
+
actuator_pump_flow = OpenStudio::Model::EnergyManagementSystemActuator.new(pump, 'Pump', 'Pump Mass Flow Rate')
|
291
|
+
actuator_pump_flow.setName(ems_pump_flow_name)
|
292
|
+
|
293
|
+
# Pump Status Actuator
|
294
|
+
actuator_pump_status = OpenStudio::Model::EnergyManagementSystemActuator.new(pump,
|
295
|
+
'Plant Component Pump:VariableSpeed',
|
296
|
+
'On/Off Supervisory')
|
297
|
+
actuator_pump_status.setName(ems_pump_status_name)
|
298
|
+
|
299
|
+
# ---- Internal Variable ----
|
300
|
+
|
301
|
+
internal_variable = OpenStudio::Model::EnergyManagementSystemInternalVariable.new(model, 'Pump Maximum Mass Flow Rate')
|
302
|
+
internal_variable.setInternalDataIndexKeyName(pump_name)
|
303
|
+
internal_variable.setName(ems_pump_design_flow_name)
|
160
304
|
end
|
161
305
|
|
162
|
-
#
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
elsif
|
168
|
-
|
169
|
-
return false
|
170
|
-
else
|
171
|
-
orig_pump = pumps[0]
|
306
|
+
# Write EMS program
|
307
|
+
if num_of_chillers > 3
|
308
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.PlantLoop', "EMS Code for multiple chiller pump has not been written for greater than 2 chillers. This has #{num_of_chillers} chillers")
|
309
|
+
elsif num_of_chillers == 3
|
310
|
+
add_ems_program_for_3_pump_chiller_plant(model, sorted_chiller_list, primary_plant)
|
311
|
+
elsif num_of_chillers == 2
|
312
|
+
add_ems_program_for_2_pump_chiller_plant(model, sorted_chiller_list, primary_plant)
|
172
313
|
end
|
173
314
|
|
174
|
-
#
|
175
|
-
|
176
|
-
|
177
|
-
# This is unused
|
178
|
-
per_chiller_cap_tons = cap_tons / num_chillers
|
179
|
-
per_chiller_cap_w = cap_w / num_chillers
|
315
|
+
# Update chilled water loop operation scheme to work with updated EMS ranges
|
316
|
+
stage_chilled_water_loop_operation_schemes(model, primary_plant)
|
317
|
+
end
|
180
318
|
|
181
|
-
|
319
|
+
# Updates a chilled water plant's operation scheme to match the EMS written by either
|
320
|
+
# add_ems_program_for_3_pump_chiller_plant or add_ems_program_for_2_pump_chiller_plant
|
321
|
+
# @param model [OpenStudio::Model] OpenStudio model with plant loops
|
322
|
+
# @param chilled_water_loop [OpenStudio::Model::PlantLoop] chilled water loop
|
323
|
+
def stage_chilled_water_loop_operation_schemes(model, chilled_water_loop)
|
324
|
+
# Initialize array of cooling plant systems
|
325
|
+
chillers = []
|
182
326
|
|
183
|
-
#
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
if new_chiller.to_ChillerElectricEIR.is_initialized
|
188
|
-
new_chiller = new_chiller.to_ChillerElectricEIR.get
|
189
|
-
else
|
190
|
-
OpenStudio.logFree(OpenStudio::Error, 'prm.log', "For #{plant_loop.name}, could not clone chiller #{first_chiller.name}, cannot apply the performance rating method number of chillers.")
|
191
|
-
return false
|
192
|
-
end
|
193
|
-
# Connect the new chiller to the same CHW loop
|
194
|
-
# as the old chiller.
|
195
|
-
plant_loop.addSupplyBranchForComponent(new_chiller)
|
196
|
-
# Connect the new chiller to the same CW loop
|
197
|
-
# as the old chiller, if it was water-cooled.
|
198
|
-
cw_loop = first_chiller.secondaryPlantLoop
|
199
|
-
if cw_loop.is_initialized
|
200
|
-
cw_loop.get.addDemandBranchForComponent(new_chiller)
|
201
|
-
end
|
327
|
+
# Gets all associated chillers from the supply side and adds them to the chillers list
|
328
|
+
chilled_water_loop.supplyComponents(OpenStudio::Model::ChillerElectricEIR.iddObjectType).each do |chiller|
|
329
|
+
chillers << chiller.to_ChillerElectricEIR.get
|
330
|
+
end
|
202
331
|
|
203
|
-
|
332
|
+
# Skip those without chillers or only 1 (i.e., nothing to stage)
|
333
|
+
return if chillers.empty?
|
334
|
+
return if chillers.length == 1
|
335
|
+
|
336
|
+
# Sort chillers by capacity
|
337
|
+
sorted_chillers = chillers.sort_by { |chiller| chiller.referenceCapacity.get }
|
338
|
+
|
339
|
+
primary_chiller = sorted_chillers[0]
|
340
|
+
secondary_1_chiller = sorted_chillers[1]
|
341
|
+
secondary_2_chiller = sorted_chillers[2] if chillers.length == 3
|
342
|
+
|
343
|
+
equip_operation_cool_load = OpenStudio::Model::PlantEquipmentOperationCoolingLoad.new(model)
|
344
|
+
|
345
|
+
# Calculate load ranges into the PlantEquipmentOperation:CoolingLoad
|
346
|
+
loading_factor = 0.8
|
347
|
+
# # when the capacity of primary chiller is larger than the capacity of secondary chiller - the loading factor
|
348
|
+
# # will need to be adjusted to avoid load range intersect.
|
349
|
+
# if secondary_1_chiller.referenceCapacity.get <= primary_chiller.referenceCapacity.get * loading_factor
|
350
|
+
# # Adjustment_factor can creates a bandwidth for step 2 staging strategy.
|
351
|
+
# # set adjustment_factor = 1.0 means the step 2 staging strategy is skipped
|
352
|
+
# adjustment_factor = 1.0
|
353
|
+
# loading_factor = secondary_1_chiller.referenceCapacity.get / primary_chiller.referenceCapacity.get * adjustment_factor
|
354
|
+
# end
|
355
|
+
|
356
|
+
if chillers.length == 3
|
357
|
+
|
358
|
+
# Add four ranges for small, medium, and large chiller capacities
|
359
|
+
# 1: 0 W -> 80% of smallest chiller capacity
|
360
|
+
# 2: 80% of primary chiller -> medium size chiller capacity
|
361
|
+
# 3: medium chiller capacity -> medium + large chiller capacity
|
362
|
+
# 4: medium + large chiller capacity -> infinity
|
363
|
+
# Control strategy first stage
|
364
|
+
equipment_list = [primary_chiller]
|
365
|
+
range = primary_chiller.referenceCapacity.get * loading_factor
|
366
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
367
|
+
|
368
|
+
# Control strategy second stage
|
369
|
+
equipment_list = [secondary_1_chiller]
|
370
|
+
range = secondary_1_chiller.referenceCapacity.get
|
371
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
372
|
+
|
373
|
+
# Control strategy third stage
|
374
|
+
equipment_list = [secondary_1_chiller, secondary_2_chiller]
|
375
|
+
range = secondary_1_chiller.referenceCapacity.get + secondary_2_chiller.referenceCapacity.get
|
376
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
377
|
+
|
378
|
+
equipment_list = [primary_chiller, secondary_1_chiller, secondary_2_chiller]
|
379
|
+
range = 999999999
|
380
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
381
|
+
|
382
|
+
elsif chillers.length == 2
|
383
|
+
|
384
|
+
# Add three ranges for primary and secondary chiller capacities
|
385
|
+
# 1: 0 W -> 80% of smallest chiller capacity
|
386
|
+
# 2: 80% of primary chiller -> secondary chiller capacity
|
387
|
+
# 3: secondary chiller capacity -> infinity
|
388
|
+
# Control strategy first stage
|
389
|
+
equipment_list = [primary_chiller]
|
390
|
+
range = primary_chiller.referenceCapacity.get * loading_factor
|
391
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
392
|
+
|
393
|
+
# Control strategy second stage
|
394
|
+
equipment_list = [secondary_1_chiller]
|
395
|
+
range = secondary_1_chiller.referenceCapacity.get
|
396
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
397
|
+
|
398
|
+
# Control strategy third stage
|
399
|
+
equipment_list = [primary_chiller, secondary_1_chiller]
|
400
|
+
range = 999999999
|
401
|
+
equip_operation_cool_load.addLoadRange(range, equipment_list)
|
402
|
+
|
403
|
+
else
|
404
|
+
raise "Failed to stage chillers, #{chillers.length} chillers found in the loop.Logic for staging chillers has only been done for either 2 or 3 chillers"
|
204
405
|
end
|
205
406
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
407
|
+
chilled_water_loop.setPlantEquipmentOperationCoolingLoad(equip_operation_cool_load)
|
408
|
+
end
|
409
|
+
|
410
|
+
# Adds EMS program for pumps serving 2 chillers on primary + secondary loop. This was due to an issue when modeling two
|
411
|
+
# dedicated loops. The headered pumps or dedicated constant speed pumps operate at full flow as long as there's a
|
412
|
+
# load on the loop unless this EMS is in place.
|
413
|
+
# @param model [OpenStudio::Model] OpenStudio model with plant loops
|
414
|
+
# @param sorted_chiller_list [Array] Array of chillers in primary_plant sorted by capacity
|
415
|
+
# @param primary_plant [OpenStudio::Model::PlantLoop] Primary chilled water loop with chillers
|
416
|
+
def add_ems_program_for_2_pump_chiller_plant(model, sorted_chiller_list, primary_plant)
|
417
|
+
plant_name = primary_plant.name.to_s
|
418
|
+
|
419
|
+
# Break out sorted chillers and get their respective capacities
|
420
|
+
small_chiller = sorted_chiller_list[0]
|
421
|
+
large_chiller = sorted_chiller_list[1]
|
422
|
+
|
423
|
+
capacity_small_chiller = small_chiller.referenceCapacity.get
|
424
|
+
capacity_large_chiller = large_chiller.referenceCapacity.get
|
425
|
+
|
426
|
+
chw_demand = "#{primary_plant.name.to_s.gsub(/[-\s]+/, '_')}_CHW_DEMAND"
|
427
|
+
|
428
|
+
ems_pump_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
429
|
+
ems_pump_program.setName("#{plant_name.gsub(/[-\s]+/, '_')}_Pump_EMS")
|
430
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = NULL, !- Program Line 1')
|
431
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = NULL, !- Program Line 2')
|
432
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = NULL, !- A3')
|
433
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = NULL, !- A4')
|
434
|
+
ems_pump_program.addLine("IF #{chw_demand} <= #{0.8 * capacity_small_chiller}, !- A5")
|
435
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 0, !- A6')
|
436
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = 0, !- A7')
|
437
|
+
ems_pump_program.addLine("ELSEIF #{chw_demand} <= #{capacity_large_chiller}, !- A8")
|
438
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = 0, !- A9')
|
439
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 1, !- A10')
|
440
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = 0, !- A11')
|
441
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = CHILLER_PUMP_2_DES_FLOW, !- A12')
|
442
|
+
ems_pump_program.addLine("ELSEIF #{chw_demand} > #{capacity_large_chiller}, !- A13")
|
443
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = 1, !- A14')
|
444
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 1, !- A15')
|
445
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = CHILLER_PUMP_1_DES_FLOW, !- A16')
|
446
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = CHILLER_PUMP_2_DES_FLOW, !- A17')
|
447
|
+
ems_pump_program.addLine('ENDIF !- A18')
|
448
|
+
|
449
|
+
ems_pump_program_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
|
450
|
+
ems_pump_program_manager.setName("#{plant_name.gsub(/[-\s]+/, '_')}_Pump_Program_Manager")
|
451
|
+
ems_pump_program_manager.setCallingPoint('InsideHVACSystemIterationLoop')
|
452
|
+
ems_pump_program_manager.addProgram(ems_pump_program)
|
453
|
+
end
|
454
|
+
|
455
|
+
# Adds EMS program for pumps serving 3 chillers on primary + secondary loop. This was due to an issue when modeling two
|
456
|
+
# dedicated loops. The headered pumps or dedicated constant speed pumps operate at full flow as long as there's a
|
457
|
+
# load on the loop unless this EMS is in place.
|
458
|
+
# @param model [OpenStudio::Model] OpenStudio model with plant loops
|
459
|
+
# @param sorted_chiller_list [Array] Array of chillers in primary_plant sorted by capacity
|
460
|
+
# @param primary_plant [OpenStudio::Model::PlantLoop] Primary chilled water loop with chillers
|
461
|
+
def add_ems_program_for_3_pump_chiller_plant(model, sorted_chiller_list, primary_plant)
|
462
|
+
plant_name = primary_plant.name.to_s
|
463
|
+
|
464
|
+
# Break out sorted chillers and get their respective capacities
|
465
|
+
primary_chiller = sorted_chiller_list[0]
|
466
|
+
medium_chiller = sorted_chiller_list[1]
|
467
|
+
large_chiller = sorted_chiller_list[2]
|
468
|
+
|
469
|
+
capacity_80_pct_small = 0.8 * primary_chiller.referenceCapacity.get
|
470
|
+
capacity_medium_chiller = medium_chiller.referenceCapacity.get
|
471
|
+
capacity_large_chiller = large_chiller.referenceCapacity.get
|
472
|
+
|
473
|
+
if capacity_80_pct_small >= capacity_medium_chiller
|
474
|
+
first_stage_capacity = capacity_medium_chiller
|
475
|
+
else
|
476
|
+
first_stage_capacity = capacity_80_pct_small
|
234
477
|
end
|
235
478
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
479
|
+
chw_demand = "#{primary_plant.name.to_s.gsub(/[-\s]+/, '_')}_CHW_DEMAND"
|
480
|
+
|
481
|
+
ems_pump_program = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
|
482
|
+
ems_pump_program.setName("#{plant_name.gsub(/[-\s]+/, '_')}_Pump_EMS")
|
483
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = NULL, !- Program Line 1')
|
484
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = NULL, !- Program Line 2')
|
485
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_STATUS = NULL, !- A4')
|
486
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = NULL, !- A5')
|
487
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = NULL, !- A6')
|
488
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_FLOW = NULL, !- A7')
|
489
|
+
ems_pump_program.addLine("IF #{chw_demand} <= #{first_stage_capacity}, !- A8")
|
490
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 0, !- A9')
|
491
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_STATUS = 0, !- A10')
|
492
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = 0, !- A11')
|
493
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_FLOW = 0, !- A12')
|
494
|
+
|
495
|
+
if capacity_80_pct_small < capacity_medium_chiller
|
496
|
+
ems_pump_program.addLine("ELSEIF #{chw_demand} <= #{capacity_medium_chiller}, !- A13")
|
497
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = 0, !- A14')
|
498
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 1, !- A15')
|
499
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_STATUS = 0, !- A16')
|
500
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = 0, !- A17')
|
501
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = CHILLER_PUMP_2_DES_FLOW, !- A18')
|
502
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_FLOW = 0, !- A19')
|
243
503
|
end
|
244
|
-
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.PlantLoop', "For #{plant_loop.name}, there are #{final_chillers.size} #{chiller_cooling_type} #{chiller_compressor_type} chillers.")
|
245
504
|
|
246
|
-
|
505
|
+
ems_pump_program.addLine("ELSEIF #{chw_demand} <= #{capacity_medium_chiller + capacity_large_chiller}, !- A20")
|
506
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = 0, !- A21')
|
507
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 1, !- A22')
|
508
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_STATUS = 1, !- A23')
|
509
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = 0, !- A24')
|
510
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = CHILLER_PUMP_2_DES_FLOW, !- A25')
|
511
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_FLOW = CHILLER_PUMP_3_DES_FLOW, !- A26')
|
512
|
+
ems_pump_program.addLine("ELSEIF #{chw_demand} > #{capacity_medium_chiller + capacity_large_chiller}, !- A27")
|
513
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_STATUS = 1, !- A28')
|
514
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_STATUS = 1, !- A29')
|
515
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_STATUS = 1, !- A30')
|
516
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_1_FLOW = CHILLER_PUMP_1_DES_FLOW, !- A31')
|
517
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_2_FLOW = CHILLER_PUMP_2_DES_FLOW, !- A32')
|
518
|
+
ems_pump_program.addLine('SET CHILLER_PUMP_3_FLOW = CHILLER_PUMP_3_DES_FLOW, !- A33')
|
519
|
+
ems_pump_program.addLine('ENDIF !- A34')
|
520
|
+
|
521
|
+
ems_pump_program_manager = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
|
522
|
+
ems_pump_program_manager.setName("#{plant_name.gsub(/[-\s]+/, '_')}_Pump_Program_Manager")
|
523
|
+
ems_pump_program_manager.setCallingPoint('InsideHVACSystemIterationLoop')
|
524
|
+
ems_pump_program_manager.addProgram(ems_pump_program)
|
247
525
|
end
|
248
526
|
|
249
527
|
# Apply prm baseline pump power
|
@@ -552,7 +552,7 @@ class ASHRAE901PRM < Standard
|
|
552
552
|
space_area = space.floorArea
|
553
553
|
space_height = OpenStudio.convert(space_volume / space_area, 'm', 'ft').get
|
554
554
|
# calculate the new lpd values
|
555
|
-
space_lighting_per_area = (lighting_per_length * space_height) + lighting_per_area
|
555
|
+
space_lighting_per_area = ((lighting_per_length * space_height) / space_area) + lighting_per_area
|
556
556
|
|
557
557
|
# Adjust the occupancy control sensor reduction factor from dataset
|
558
558
|
if manon_or_partauto == 1
|
@@ -652,7 +652,7 @@ class ASHRAE901PRM < Standard
|
|
652
652
|
space_area = space.floorArea
|
653
653
|
space_height = OpenStudio.convert(space_volume / space_area, 'm', 'ft').get
|
654
654
|
# calculate and add new lpd values
|
655
|
-
user_space_type_lighting_per_area = ((lighting_per_length * space_height) + lighting_per_area) * sub_space_type_frac
|
655
|
+
user_space_type_lighting_per_area = (((lighting_per_length * space_height) / space_area) + lighting_per_area) * sub_space_type_frac
|
656
656
|
space_lighting_per_area += user_space_type_lighting_per_area
|
657
657
|
|
658
658
|
# Adjust the occupancy control sensor reduction factor from dataset
|
@@ -37,13 +37,13 @@ class ASHRAE901PRM2019 < ASHRAE901PRM
|
|
37
37
|
wwr_range['minimum_percent_of_surface'] = 0
|
38
38
|
wwr_range['maximum_percent_of_surface'] = 10
|
39
39
|
elsif wwr_info[wwr_building_type] <= 20
|
40
|
-
wwr_range['minimum_percent_of_surface'] = 10.
|
40
|
+
wwr_range['minimum_percent_of_surface'] = 10.001
|
41
41
|
wwr_range['maximum_percent_of_surface'] = 20
|
42
42
|
elsif wwr_info[wwr_building_type] <= 30
|
43
|
-
wwr_range['minimum_percent_of_surface'] = 20.
|
43
|
+
wwr_range['minimum_percent_of_surface'] = 20.001
|
44
44
|
wwr_range['maximum_percent_of_surface'] = 30
|
45
45
|
elsif wwr_info[wwr_building_type] <= 40
|
46
|
-
wwr_range['minimum_percent_of_surface'] = 30.
|
46
|
+
wwr_range['minimum_percent_of_surface'] = 30.001
|
47
47
|
wwr_range['maximum_percent_of_surface'] = 40
|
48
48
|
else
|
49
49
|
wwr_range['minimum_percent_of_surface'] = nil
|