openstudio-geb 0.0.2 → 0.0.3r
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/lib/measures/AdjustThermostatSetpointsByDegreesForPeakHours/measure.rb +1 -1
- data/lib/measures/add_chilled_water_storage_tank/measure.rb +167 -36
- data/lib/measures/add_chilled_water_storage_tank/tests/restaurant.osm +12189 -0
- data/lib/measures/average_ventilation_for_peak_hours/measure.rb +22 -11
- data/lib/measures/average_ventilation_for_peak_hours/tests/LargeOffice-90.1-2013-ASHRAE 169-2013-5A.osm +21863 -0
- data/lib/measures/reduce_epd_by_percentage_for_peak_hours/measure.rb +94 -95
- data/lib/openstudio/geb/version.rb +1 -1
- metadata +7 -5
- data/lib/measures/average_ventilation_for_peak_hours/tests/example_model.osm +0 -8077
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95736fe58727e0f60da222a3f643c02dc5e5465dc77b5e6513012a59949d9d85
|
4
|
+
data.tar.gz: 55105af8ce0bf75e1005123a36f77e61268136554663d6b476091e1995396bae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63d3ff9b2cc8415a52ba1906a61146ed28ba6a977da91393e84fa0ed7e6845240beea11c03d20483b86f92b56b4f779fff42a08f093544bc59e43dcce0453605
|
7
|
+
data.tar.gz: 02f4cfd1f7b5e87d3c14c142a15cf370aa19793a3f280fd772b39a972c844680d817fb40123caf7c8f914a4686c85a14de4375078de197c77196b79a619ef390
|
data/.gitignore
CHANGED
@@ -673,7 +673,7 @@ class AdjustThermostatSetpointsByDegreesForPeakHours < OpenStudio::Measure::Mode
|
|
673
673
|
elsif vec_time[i]>time_begin && vec_time[i]<=time_end && count==1
|
674
674
|
sch_day.addValue(vec_time[i], vec_value[i])
|
675
675
|
elsif vec_time[i]>time_end && count == 1
|
676
|
-
sch_day.addValue(time_end, target_temp_si)
|
676
|
+
sch_day.addValue(time_end, target_temp_si.value)
|
677
677
|
sch_day.addValue(vec_time[i], vec_value[i])
|
678
678
|
count = 2
|
679
679
|
else
|
@@ -49,9 +49,9 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
49
49
|
loop_choices << loop.name.to_s
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
52
|
+
loop_choices << ""
|
53
53
|
# Make choice argument for primary loop selection
|
54
|
-
selected_primary_loop_name = OpenStudio::Measure::OSArgument.makeChoiceArgument('selected_primary_loop_name', loop_choices,
|
54
|
+
selected_primary_loop_name = OpenStudio::Measure::OSArgument.makeChoiceArgument('selected_primary_loop_name', loop_choices, false)
|
55
55
|
selected_primary_loop_name.setDisplayName('Select Primary Loop:')
|
56
56
|
selected_primary_loop_name.setDescription('This is the primary cooling loop on which the chilled water tank will be added.')
|
57
57
|
pri_loop_name = nil
|
@@ -62,6 +62,7 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
62
62
|
selected_primary_loop_name.setDefaultValue(pri_loop_name)
|
63
63
|
else
|
64
64
|
selected_primary_loop_name.setDescription('Error: No Cooling Loop Found')
|
65
|
+
selected_primary_loop_name.setDefaultValue("")
|
65
66
|
end
|
66
67
|
args << selected_primary_loop_name
|
67
68
|
|
@@ -156,12 +157,13 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
156
157
|
args << wknds
|
157
158
|
|
158
159
|
# Output path, for sizing run
|
159
|
-
run_output_path = OpenStudio::Measure::OSArgument.makePathArgument('run_output_path', true, "")
|
160
|
+
run_output_path = OpenStudio::Measure::OSArgument.makePathArgument('run_output_path', true, "", false)
|
160
161
|
run_output_path.setDisplayName('Output path for tank sizing run (if tank volume is not provided)')
|
162
|
+
run_output_path.setDefaultValue(".")
|
161
163
|
args << run_output_path
|
162
164
|
|
163
165
|
# epw file path, for sizing run
|
164
|
-
epw_path = OpenStudio::Measure::OSArgument.makePathArgument('epw_path', true, "")
|
166
|
+
epw_path = OpenStudio::Measure::OSArgument.makePathArgument('epw_path', true, "", false)
|
165
167
|
epw_path.setDisplayName('epw file path for tank sizing run (if tank volume is not provided)')
|
166
168
|
args << epw_path
|
167
169
|
|
@@ -187,6 +189,36 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
187
189
|
# assign the user inputs to variables
|
188
190
|
objective = runner.getStringArgumentValue('objective', user_arguments)
|
189
191
|
selected_primary_loop_name = runner.getStringArgumentValue('selected_primary_loop_name', user_arguments)
|
192
|
+
# if user_arguments['selected_primary_loop_name'].hasValue
|
193
|
+
# selected_primary_loop_name = runner.getStringArgumentValue('selected_primary_loop_name', user_arguments)
|
194
|
+
if !selected_primary_loop_name.empty?
|
195
|
+
# get the primary cooling loop
|
196
|
+
selected_primary_loop = model.getModelObjectByName(selected_primary_loop_name)
|
197
|
+
if selected_primary_loop.is_initialized
|
198
|
+
selected_primary_loop = selected_primary_loop.get.to_PlantLoop.get
|
199
|
+
else
|
200
|
+
# The provided value is not a plant loop in the model
|
201
|
+
runner.registerError("The provided primary loop name doesn't exist in the model.")
|
202
|
+
return false
|
203
|
+
end
|
204
|
+
else
|
205
|
+
loop_choices = []
|
206
|
+
model.getPlantLoops.each do |loop|
|
207
|
+
if loop.sizingPlant.loopType.to_s == 'Cooling'
|
208
|
+
loop_choices << loop.name.to_s
|
209
|
+
end
|
210
|
+
end
|
211
|
+
if loop_choices.empty?
|
212
|
+
# No cooling loop; the measure is not applicable
|
213
|
+
runner.registerAsNotApplicable("No cooling loop in the model. The measure is not applicable.")
|
214
|
+
return true
|
215
|
+
else
|
216
|
+
# There is cooling loop in the model but user didn't specify one,
|
217
|
+
# and the cooling loop name does not include 'chilled water loop'
|
218
|
+
runner.registerError("Please select a primary loop name to run the measure. The available cooling loop(s) in the model is #{loop_choices.join(', ')}")
|
219
|
+
return false
|
220
|
+
end
|
221
|
+
end
|
190
222
|
primary_loop_sp = runner.getDoubleArgumentValue('primary_loop_sp', user_arguments)
|
191
223
|
secondary_loop_sp = runner.getDoubleArgumentValue('secondary_loop_sp', user_arguments)
|
192
224
|
tank_charge_sp = runner.getDoubleArgumentValue('tank_charge_sp', user_arguments)
|
@@ -199,6 +231,7 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
199
231
|
charge_end = runner.getStringArgumentValue('charge_end', user_arguments)
|
200
232
|
wknds = runner.getBoolArgumentValue('wknds', user_arguments)
|
201
233
|
|
234
|
+
|
202
235
|
# check time format
|
203
236
|
begin
|
204
237
|
discharge_start = Time.strptime(discharge_start, '%H:%M')
|
@@ -293,14 +326,7 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
293
326
|
return false
|
294
327
|
end
|
295
328
|
|
296
|
-
|
297
|
-
selected_primary_loop = model.getModelObjectByName(selected_primary_loop_name)
|
298
|
-
if selected_primary_loop.is_initialized
|
299
|
-
selected_primary_loop = selected_primary_loop.get.to_PlantLoop.get
|
300
|
-
else
|
301
|
-
runner.registerError("Error: No Primary Cooling Loop Found. ")
|
302
|
-
return false
|
303
|
-
end
|
329
|
+
|
304
330
|
# report initial condition of model
|
305
331
|
runner.registerInitialCondition("Original primary chilled water loop: #{selected_primary_loop.name}.")
|
306
332
|
|
@@ -312,17 +338,112 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
312
338
|
primary_delta_t = selected_primary_loop.sizingPlant.loopDesignTemperatureDifference
|
313
339
|
end
|
314
340
|
|
341
|
+
# get the condenser water loop
|
342
|
+
cw_loop = nil
|
343
|
+
model.getPlantLoops.each do |loop|
|
344
|
+
if loop.sizingPlant.loopType.to_s.downcase == 'condenser'
|
345
|
+
cw_loop = loop if cw_loop.nil?
|
346
|
+
# confirm if this condenser loop contains demand component of chiller that is in the selected_primary_loop
|
347
|
+
common_comps = cw_loop.demandComponents & selected_primary_loop.supplyComponents
|
348
|
+
chiller_in_both_loops = false
|
349
|
+
common_comps.each do |comp|
|
350
|
+
chiller_in_both_loops = true if comp.to_ChillerElectricEIR.is_initialized || comp.to_ChillerAbsorption.is_initialized || comp.to_ChillerAbsorptionIndirect.is_initialized
|
351
|
+
end
|
352
|
+
cw_loop = nil unless chiller_in_both_loops
|
353
|
+
end
|
354
|
+
end
|
355
|
+
# not necessarily can find a cw_loop as the existing primary chiller might be air cooled.
|
356
|
+
|
357
|
+
def hardsize_cooling_tower_two_speed(tower)
|
358
|
+
# implement the applySizingValues function for CoolingTowerTwoSpeed here since it's not yet implemented in OS standards
|
359
|
+
rated_water_flow_rate = tower.autosizedDesignWaterFlowRate
|
360
|
+
if rated_water_flow_rate.is_initialized
|
361
|
+
tower.setDesignWaterFlowRate(rated_water_flow_rate.get)
|
362
|
+
end
|
363
|
+
|
364
|
+
high_fan_speed_fan_power = tower.autosizedHighFanSpeedFanPower
|
365
|
+
if high_fan_speed_fan_power.is_initialized
|
366
|
+
tower.setHighFanSpeedFanPower(high_fan_speed_fan_power.get)
|
367
|
+
end
|
368
|
+
|
369
|
+
high_fan_speed_air_flow_rate = tower.autosizedHighFanSpeedAirFlowRate
|
370
|
+
if high_fan_speed_air_flow_rate.is_initialized
|
371
|
+
tower.setHighFanSpeedAirFlowRate(high_fan_speed_air_flow_rate.get)
|
372
|
+
end
|
373
|
+
|
374
|
+
high_fan_speed_u_factor_times_area_value = tower.autosizedHighFanSpeedUFactorTimesAreaValue
|
375
|
+
if high_fan_speed_u_factor_times_area_value.is_initialized
|
376
|
+
tower.setHighFanSpeedUFactorTimesAreaValue(high_fan_speed_u_factor_times_area_value.get)
|
377
|
+
end
|
378
|
+
|
379
|
+
low_fan_speed_air_flow_rate = tower.autosizedLowFanSpeedAirFlowRate
|
380
|
+
if low_fan_speed_air_flow_rate.is_initialized
|
381
|
+
tower.setLowFanSpeedAirFlowRate(low_fan_speed_air_flow_rate.get)
|
382
|
+
end
|
383
|
+
|
384
|
+
low_fan_speed_fan_power = tower.autosizedLowFanSpeedFanPower
|
385
|
+
if low_fan_speed_fan_power.is_initialized
|
386
|
+
tower.setLowFanSpeedFanPower(low_fan_speed_fan_power.get)
|
387
|
+
end
|
388
|
+
|
389
|
+
low_fan_speed_u_factor_times_area_value = tower.autosizedLowFanSpeedUFactorTimesAreaValue
|
390
|
+
if low_fan_speed_u_factor_times_area_value.is_initialized
|
391
|
+
tower.setLowFanSpeedUFactorTimesAreaValue(low_fan_speed_u_factor_times_area_value.get)
|
392
|
+
end
|
393
|
+
|
394
|
+
free_convection_regime_air_flow_rate = tower.autosizedFreeConvectionRegimeAirFlowRate
|
395
|
+
if free_convection_regime_air_flow_rate.is_initialized
|
396
|
+
tower.setFreeConvectionRegimeAirFlowRate(free_convection_regime_air_flow_rate.get)
|
397
|
+
end
|
398
|
+
|
399
|
+
free_convection_regime_u_factor_times_area_value = tower.autosizedFreeConvectionRegimeUFactorTimesAreaValue
|
400
|
+
if free_convection_regime_u_factor_times_area_value.is_initialized
|
401
|
+
tower.setFreeConvectionRegimeUFactorTimesAreaValue(free_convection_regime_u_factor_times_area_value.get)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
315
405
|
# if user provides this input, if not, do autosizing
|
316
406
|
if user_arguments['tank_vol'].hasValue
|
317
407
|
tank_vol = runner.getDoubleArgumentValue('tank_vol', user_arguments)
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
408
|
+
if cw_loop
|
409
|
+
# autosize cooling tower in the condenser loop to avoid invalid hard-sized parameters
|
410
|
+
cw_loop.supplyComponents.each do |comp|
|
411
|
+
if comp.to_CoolingTowerSingleSpeed.is_initialized
|
412
|
+
cooling_tower = comp.to_CoolingTowerSingleSpeed.get
|
413
|
+
cooling_tower.autosizeDesignWaterFlowRate
|
414
|
+
cooling_tower.autosizeFanPoweratDesignAirFlowRate
|
415
|
+
cooling_tower.autosizeDesignAirFlowRate
|
416
|
+
cooling_tower.autosizeUFactorTimesAreaValueatDesignAirFlowRate
|
417
|
+
cooling_tower.autosizeAirFlowRateinFreeConvectionRegime
|
418
|
+
cooling_tower.autosizeUFactorTimesAreaValueatFreeConvectionAirFlowRate
|
419
|
+
runner.registerInfo("CoolingTowerSingleSpeed #{cooling_tower.name} has been set to autosize.")
|
420
|
+
elsif comp.to_CoolingTowerTwoSpeed.is_initialized
|
421
|
+
cooling_tower = comp.to_CoolingTowerTwoSpeed.get
|
422
|
+
cooling_tower.autosizeDesignWaterFlowRate
|
423
|
+
cooling_tower.autosizeHighFanSpeedFanPower
|
424
|
+
cooling_tower.autosizeHighFanSpeedAirFlowRate
|
425
|
+
cooling_tower.autosizeHighFanSpeedUFactorTimesAreaValue
|
426
|
+
cooling_tower.autosizeLowFanSpeedAirFlowRate
|
427
|
+
cooling_tower.autosizeLowFanSpeedFanPower
|
428
|
+
cooling_tower.autosizeLowFanSpeedUFactorTimesAreaValue
|
429
|
+
cooling_tower.autosizeFreeConvectionRegimeAirFlowRate
|
430
|
+
cooling_tower.autosizeFreeConvectionRegimeUFactorTimesAreaValue
|
431
|
+
runner.registerInfo("CoolingTowerTwoSpeed #{cooling_tower.name} has been set to autosize.")
|
432
|
+
elsif comp.to_CoolingTowerVariableSpeed.is_initialized
|
433
|
+
cooling_tower = comp.to_CoolingTowerVariableSpeed.get
|
434
|
+
cooling_tower.autosize
|
435
|
+
runner.registerInfo("CoolingTowerVariableSpeed #{cooling_tower.name} has been set to autosize.")
|
436
|
+
end
|
437
|
+
end
|
322
438
|
end
|
439
|
+
else
|
440
|
+
# unless user_arguments['run_output_path'].hasValue
|
441
|
+
# runner.registerError("Need to provide run output path for sizing run of tank volume. ")
|
442
|
+
# return false
|
443
|
+
# end
|
323
444
|
run_output_path = runner.getPathArgumentValue('run_output_path', user_arguments)
|
324
445
|
Dir.mkdir(run_output_path.to_s) unless File.exists?(run_output_path.to_s)
|
325
|
-
sizing_output_path = File.join(run_output_path.to_s, 'sizing_run')
|
446
|
+
sizing_output_path = File.expand_path(File.join(run_output_path.to_s, 'sizing_run'))
|
326
447
|
Dir.mkdir(sizing_output_path.to_s) unless File.exists?(sizing_output_path.to_s)
|
327
448
|
|
328
449
|
# Change the simulation to only run the sizing days
|
@@ -351,11 +472,18 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
351
472
|
File.open(osw_path, 'w') do |f|
|
352
473
|
f << JSON.pretty_generate(osw)
|
353
474
|
end
|
475
|
+
model.resetSqlFile
|
354
476
|
run_osw(osw_path)
|
355
477
|
sleep(1)
|
356
|
-
|
357
|
-
|
358
|
-
|
478
|
+
sql_path = OpenStudio::Path.new(File.join(sizing_output_path.to_s, "run", "eplusout.sql"))
|
479
|
+
if OpenStudio.exists(sql_path)
|
480
|
+
sql = OpenStudio::SqlFile.new(sql_path)
|
481
|
+
unless sql.connectionOpen
|
482
|
+
runner.registerError("The sizing run failed without valid a sql file. Look at the eplusout.err file in #{File.dirname(sql_path.to_s)} to see the cause.")
|
483
|
+
return false
|
484
|
+
end
|
485
|
+
# Attach the sql file from the run to the model
|
486
|
+
model.setSqlFile(sql)
|
359
487
|
end
|
360
488
|
|
361
489
|
total_cooling_cap = 0 # initial
|
@@ -368,6 +496,24 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
368
496
|
total_cooling_cap += comp.to_ChillerAbsorptionIndirect.get.autosizedNominalCapacity.get
|
369
497
|
end
|
370
498
|
end
|
499
|
+
if cw_loop
|
500
|
+
# hard size cooling tower in the condenser loop
|
501
|
+
cw_loop.supplyComponents.each do |comp|
|
502
|
+
if comp.to_CoolingTowerSingleSpeed.is_initialized
|
503
|
+
cooling_tower = comp.to_CoolingTowerSingleSpeed.get
|
504
|
+
cooling_tower.applySizingValues
|
505
|
+
runner.registerInfo("Autosized parameters from the sizing run have been set to CoolingTowerSingleSpeed #{cooling_tower.name}")
|
506
|
+
elsif comp.to_CoolingTowerTwoSpeed.is_initialized
|
507
|
+
cooling_tower = comp.to_CoolingTowerTwoSpeed.get
|
508
|
+
hardsize_cooling_tower_two_speed(cooling_tower)
|
509
|
+
runner.registerInfo("Autosized parameters from the sizing run have been set to CoolingTowerTwoSpeed #{cooling_tower.name}")
|
510
|
+
elsif comp.to_CoolingTowerVariableSpeed.is_initialized
|
511
|
+
cooling_tower = comp.to_CoolingTowerVariableSpeed.get
|
512
|
+
cooling_tower.applySizingValues
|
513
|
+
runner.registerInfo("Autosized parameters from the sizing run have been set to CoolingTowerVariableSpeed #{cooling_tower.name}")
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|
371
517
|
|
372
518
|
# assuming average load ratio of chiller is 1/3 throughout the day
|
373
519
|
tank_vol = total_cooling_cap/3.0 * 3600 * lasting_hrs / (4182 * 1000 * secondary_delta_t) # heat capacity of water 4182J/kg.K, water density 1000g/m3, lasting 8 hours
|
@@ -380,7 +526,6 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
380
526
|
|
381
527
|
sec_loop = OpenStudio::Model::PlantLoop.new(model)
|
382
528
|
sec_loop.setName("Chilled Water Secondary Loop")
|
383
|
-
selected_primary_loop = model.getPlantLoopByName("Chilled Water Loop").get
|
384
529
|
selected_primary_loop.setName("Chilled Water Primary Loop")
|
385
530
|
sizing_sec_plant = sec_loop.sizingPlant
|
386
531
|
sizing_sec_plant.setLoopType('Cooling')
|
@@ -391,21 +536,7 @@ class AddChilledWaterStorageTank < OpenStudio::Measure::ModelMeasure
|
|
391
536
|
sizing_pri_plant.setDesignLoopExitTemperature(primary_loop_sp)
|
392
537
|
sizing_pri_plant.setLoopDesignTemperatureDifference(primary_delta_t)
|
393
538
|
|
394
|
-
|
395
|
-
cw_loop = nil
|
396
|
-
model.getPlantLoops.each do |loop|
|
397
|
-
if loop.sizingPlant.loopType.to_s.downcase == 'condenser'
|
398
|
-
cw_loop = loop if cw_loop.nil?
|
399
|
-
# confirm if this condenser loop contains demand component of chiller that is in the selected_primary_loop
|
400
|
-
common_comps = cw_loop.demandComponents & selected_primary_loop.supplyComponents
|
401
|
-
chiller_in_both_loops = false
|
402
|
-
common_comps.each do |comp|
|
403
|
-
chiller_in_both_loops = true if comp.to_ChillerElectricEIR.is_initialized || comp.to_ChillerAbsorption.is_initialized || comp.to_ChillerAbsorptionIndirect.is_initialized
|
404
|
-
end
|
405
|
-
cw_loop = nil unless chiller_in_both_loops
|
406
|
-
end
|
407
|
-
end
|
408
|
-
# not necessarily can find a cw_loop as the existing primary chiller might be air cooled.
|
539
|
+
|
409
540
|
|
410
541
|
# add chilled water tank to the primary loop as demand and secondary loop as supply
|
411
542
|
chw_storage_tank = OpenStudio::Model::ThermalStorageChilledWaterStratified.new(model)
|