openstudio-load-flexibility-measures 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 537d8d5a9f2f9e508453d1e45d23cb5c7ee10b149a6df8b4df9e835b077a6bbf
4
- data.tar.gz: bb9151db95b85b535e02fbf76383d4edb7e9a902de644afa0e1bf95e9cbf989b
3
+ metadata.gz: 678b5aacbeb51baa27c912b8691b2eaa2279ba92dbc96ebe0a9dd3f111a29c42
4
+ data.tar.gz: 12768b48601c478e3e6119d7aff9c1456c21ca4ded142561a061303839458aad
5
5
  SHA512:
6
- metadata.gz: ac277da97b3f779204ebf87737c3e2fdd3f2eadc5943eb785c221d63e585ce5fe3cc3b49799d7612220bfd1337aa2f4b048167ee3c75f5917a152eae163fdddc
7
- data.tar.gz: 8e89c3dbccfba007051aee78e7ca84071b522087b7956b423f9b188e3254b8d5c62da13ffcfd1929cdc4ef65c2cb885255044c14e77499a4c8c33779b8088137
6
+ metadata.gz: ef15d6c3b4900eda9ca4d128668a06e1dbf77335902a61732bd920cff9748f061bb907810c2a497ea0127e450d5d5f8b2a217d526d9fe85938b3743b36db20d6
7
+ data.tar.gz: 93e4dedd2bd79ef2d9b1254e3e78eebbf3bd949f18682b224219c468c04c22365d3a958cc917a8ec38157107aab0bd8c2c0bd811cf19e7816b734c21fa86f5b3
data/CHANGELOG.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # OpenStudio Load Flexibility Measures Gem
2
2
 
3
+ ## Version 0.3.2
4
+ * Modify HPWH measure "simplified" option to automatically identify water heater objects without explicit user naming
5
+ * Modify HPWH measure to improve integration with URBANopt workflow
6
+ * Update HPWH measure documentation
7
+
3
8
  ## Version 0.3.1
4
9
  * Updated OS Extension dependency to 0.4.2
5
10
  * Updated OS Standards dependency to 0.2.13
11
+ * Added Jenkins file for CI testing
6
12
 
7
13
  ## Version 0.3.0
8
14
  * Merged [#20](https://github.com/NREL/openstudio-load-flexibility-measures-gem/pull/20), 030 upgrade
@@ -2,14 +2,12 @@
2
2
 
3
3
  ###### (Automatically generated documentation)
4
4
 
5
- # Add HPWH for Domestic Hot Water
5
+ #
6
6
 
7
7
  ## Description
8
- This measure adds or replaces existing domestic hot water heater with air source heat pump system and allows for the addition of multiple daily flexible control time windows. The heater/tank system may charge at maximum capacity up to an elevated temperature, or float without any heat addition for a specified timeframe down to a minimum tank temperature.
8
+
9
9
 
10
10
  ## Modeler Description
11
- This measure allows selection between three heat pump water heater modeling approaches in EnergyPlus.The user may select between the pumped-condenser or wrapped-condenser objects. They may also elect to use a simplified calculation which does not use the heat pump objects, but instead used an electric resistance heater and approximates the equivalent electrical input that would be required from a heat pump. This expedites simulation at the expense of accuracy.
12
- The flexibility of the system is based on user-defined temperatures and times, which are converted into schedule objects. There are four flexibility options. (1) None: normal operation of the DHW system at a fixed tank temperature setpoint. (2) Charge - Heat Pump: the tank is charged to a maximum temperature using only the heat pump. (3) Charge - Electric: the tank is charged using internal electric resistance heaters to a maximum temperature. (4) Float: all heating elements are turned-off for a user-defined time period unless the tank temperature falls below a minimum value. The heat pump will be prioritized in a low tank temperature event, with the electric resistance heaters serving as back-up.
13
11
 
14
12
 
15
13
  ## Measure Type
@@ -21,166 +19,8 @@ ModelMeasure
21
19
  ## Arguments
22
20
 
23
21
 
24
- ### Remove existing water heater on selected loop
25
-
26
- **Name:** remove_wh,
27
- **Type:** Boolean,
28
- **Units:** ,
29
- **Required:** true,
30
- **Model Dependent:** false
31
-
32
- ### Select hot water loop
33
- The water tank will be placed on the supply side of this loop.
34
- **Name:** loop,
35
- **Type:** Choice,
36
- **Units:** ,
37
- **Required:** true,
38
- **Model Dependent:** false
39
-
40
- ### Select thermal zone
41
- This is where the water heater tank will be placed
42
- **Name:** zone,
43
- **Type:** Choice,
44
- **Units:** ,
45
- **Required:** true,
46
- **Model Dependent:** false
47
-
48
- ### Select heat pump water heater type
49
-
50
- **Name:** type,
51
- **Type:** Choice,
52
- **Units:** ,
53
- **Required:** true,
54
- **Model Dependent:** false
55
-
56
- ### Set hot water tank volume
57
- [gal]
58
- **Name:** vol,
59
- **Type:** Double,
60
- **Units:** ,
61
- **Required:** true,
62
- **Model Dependent:** false
63
-
64
- ### Set heat pump heating capacity
65
- [kW]
66
- **Name:** cap,
67
- **Type:** Double,
68
- **Units:** ,
69
- **Required:** true,
70
- **Model Dependent:** false
71
-
72
- ### Set heat pump rated COP (heating)
73
-
74
- **Name:** cop,
75
- **Type:** Double,
76
- **Units:** ,
77
- **Required:** true,
78
- **Model Dependent:** false
79
-
80
- ### Set electric backup heating capacity
81
- [kW]
82
- **Name:** bu_cap,
83
- **Type:** Double,
84
- **Units:** ,
85
- **Required:** true,
86
- **Model Dependent:** false
87
-
88
- ### Set maximum tank temperature
89
- [F]
90
- **Name:** max_temp,
91
- **Type:** Double,
92
- **Units:** ,
93
- **Required:** true,
94
- **Model Dependent:** false
95
-
96
- ### Set minimum tank temperature during float
97
- [F]
98
- **Name:** min_temp,
99
- **Type:** Double,
100
- **Units:** ,
101
- **Required:** true,
102
- **Model Dependent:** false
103
-
104
- ### Set deadband temperature difference between heat pump and electric backup
105
- [F]
106
- **Name:** db_temp,
107
- **Type:** Double,
108
- **Units:** ,
109
- **Required:** true,
110
- **Model Dependent:** false
111
-
112
- ### Select reference tank setpoint temperature schedule
113
-
114
- **Name:** sched,
115
- **Type:** Choice,
116
- **Units:** ,
117
- **Required:** true,
118
- **Model Dependent:** false
119
-
120
- ### Daily Flex Period 1:
121
- Applies every day in the full run period.
122
- **Name:** flex0,
123
- **Type:** Choice,
124
- **Units:** ,
125
- **Required:** true,
126
- **Model Dependent:** false
127
-
128
- ### Use 24-Hour Format
129
-
130
- **Name:** flex_hrs0,
131
- **Type:** String,
132
- **Units:** ,
133
- **Required:** false,
134
- **Model Dependent:** false
135
-
136
- ### Daily Flex Period 2:
137
- Applies every day in the full run period.
138
- **Name:** flex1,
139
- **Type:** Choice,
140
- **Units:** ,
141
- **Required:** true,
142
- **Model Dependent:** false
143
-
144
- ### Use 24-Hour Format
145
-
146
- **Name:** flex_hrs1,
147
- **Type:** String,
148
- **Units:** ,
149
- **Required:** false,
150
- **Model Dependent:** false
151
-
152
- ### Daily Flex Period 3:
153
- Applies every day in the full run period.
154
- **Name:** flex2,
155
- **Type:** Choice,
156
- **Units:** ,
157
- **Required:** true,
158
- **Model Dependent:** false
159
-
160
- ### Use 24-Hour Format
161
-
162
- **Name:** flex_hrs2,
163
- **Type:** String,
164
- **Units:** ,
165
- **Required:** false,
166
- **Model Dependent:** false
167
-
168
- ### Daily Flex Period 4:
169
- Applies every day in the full run period.
170
- **Name:** flex3,
171
- **Type:** Choice,
172
- **Units:** ,
173
- **Required:** true,
174
- **Model Dependent:** false
175
-
176
- ### Use 24-Hour Format
177
-
178
- **Name:** flex_hrs3,
179
- **Type:** String,
180
- **Units:** ,
181
- **Required:** false,
182
- **Model Dependent:** false
183
22
 
184
23
 
24
+ This measure does not have any user arguments
185
25
 
186
26
 
@@ -87,36 +87,49 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
87
87
 
88
88
  # create argument for removal of existing water heater tanks on selected loop
89
89
  remove_wh = OpenStudio::Measure::OSArgument.makeBoolArgument('remove_wh', true)
90
- remove_wh.setDisplayName('Remove existing water heater on selected loop')
90
+ remove_wh.setDisplayName('Remove existing water heater?')
91
91
  remove_wh.setDescription('')
92
92
  remove_wh.setDefaultValue(true)
93
93
  args << remove_wh
94
94
 
95
- # find available plant loops (heating)
96
- loop_names = []
95
+ # find available water heaters and get default volume
96
+ if !model.getWaterHeaterMixeds.empty?
97
+ wheaters = model.getWaterHeaterMixeds
98
+ end
97
99
 
98
- unless model.getPlantLoops.empty?
99
- loops = model.getPlantLoops
100
- loops.each do |lp|
101
- unless lp.sizingPlant.loopType.empty?
102
- next unless lp.sizingPlant.loopType.to_s == 'Heating'
103
- loop_names << lp.name.to_s
104
- end
100
+ default_vol = 80.0 # gallons
101
+ wh_names = ['All Water Heaters (Simplified Only)']
102
+ wheaters.each do |w|
103
+ if w.tankVolume.to_f > OpenStudio.convert(39, 'gal', 'm^3').to_f
104
+ wh_names << w.name.to_s
105
+ default_vol = [default_vol, (w.tankVolume.to_f / 0.0037854118).round(1)].max
105
106
  end
106
107
  end
107
108
 
108
- loop_names << 'Error: No Service Water Loop Found' if loop_names.empty?
109
+ wh = OpenStudio::Measure::OSArgument.makeChoiceArgument('wh', wh_names, true)
110
+ wh.setDisplayName('Select 40+ gallon water heater to replace or augment')
111
+ wh.setDescription("All can only be used with the 'Simplified' model")
112
+ wh.setDefaultValue(wh_names[0])
113
+ args << wh
109
114
 
110
- # create argument for loop selection
111
- loop = OpenStudio::Measure::OSArgument.makeChoiceArgument('loop', loop_names.sort, true)
112
- loop.setDisplayName('Select hot water loop')
113
- loop.setDescription('The water tank will be placed on the supply side of this loop.')
114
- loop.setDefaultValue(loop_names.sort[0])
115
- args << loop
115
+ # create argument for hot water tank volume
116
+ vol = OpenStudio::Measure::OSArgument.makeDoubleArgument('vol', false)
117
+ vol.setDisplayName('Set hot water tank volume [gal]')
118
+ vol.setDescription('Enter 0 to use existing tank volume(s). Values less than 5 are treated as sizing multipliers.')
119
+ vol.setUnits('gal')
120
+ vol.setDefaultValue(0)
121
+ args << vol
122
+
123
+ # create argument for water heater type
124
+ type = OpenStudio::Measure::OSArgument.makeChoiceArgument('type',
125
+ ['Simplified', 'PumpedCondenser', 'WrappedCondenser'], true)
126
+ type.setDisplayName('Select heat pump water heater type')
127
+ type.setDescription('')
128
+ type.setDefaultValue('Simplified')
129
+ args << type
116
130
 
117
131
  # find available spaces for heater location
118
132
  zone_names = []
119
-
120
133
  unless model.getThermalZones.empty?
121
134
  zones = model.getThermalZones
122
135
  zones.each do |zn|
@@ -126,46 +139,15 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
126
139
  end
127
140
 
128
141
  zone_names << 'Error: No Thermal Zones Found' if zone_names.empty?
142
+ zone_names = ['N/A - Simplified'] + zone_names
129
143
 
130
144
  # create argument for thermal zone selection (location of water heater)
131
145
  zone = OpenStudio::Measure::OSArgument.makeChoiceArgument('zone', zone_names, true)
132
- zone.setDisplayName('Select thermal zone')
133
- zone.setDescription('This is where the water heater tank will be placed')
146
+ zone.setDisplayName('Select thermal zone for HP evaporator')
147
+ zone.setDescription("Does not apply to 'Simplified' cases")
134
148
  zone.setDefaultValue(zone_names[0])
135
149
  args << zone
136
150
 
137
- # create argument for water heater type
138
- type = OpenStudio::Measure::OSArgument.makeChoiceArgument('type',
139
- ['PumpedCondenser', 'WrappedCondenser', 'Simplified'], true)
140
- type.setDisplayName('Select heat pump water heater type')
141
- type.setDescription('')
142
- type.setDefaultValue('PumpedCondenser')
143
- args << type
144
-
145
- # find largest current water heater volume - if any mixed tanks are already present. Default is 80 gal.
146
- default_vol = 80.0 # gal
147
-
148
- wheaters = if !model.getWaterHeaterMixeds.empty?
149
- model.getWaterHeaterMixeds
150
- else
151
- []
152
- end
153
-
154
- unless wheaters.empty?
155
- wheaters.each do |wh|
156
- unless wh.tankVolume.empty?
157
- default_vol = [default_vol, (wh.tankVolume.to_f / 0.0037854118).round(1)].max # convert m^3 to gal
158
- end
159
- end
160
- end
161
-
162
- # create argument for hot water tank volume
163
- vol = OpenStudio::Measure::OSArgument.makeDoubleArgument('vol', true)
164
- vol.setDisplayName('Set hot water tank volume')
165
- vol.setDescription('[gal]')
166
- vol.setDefaultValue(default_vol)
167
- args << vol
168
-
169
151
  # create argument for heat pump capacity
170
152
  cap = OpenStudio::Measure::OSArgument.makeDoubleArgument('cap', true)
171
153
  cap.setDisplayName('Set heat pump heating capacity')
@@ -176,7 +158,7 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
176
158
  # create argument for heat pump rated cop
177
159
  cop = OpenStudio::Measure::OSArgument.makeDoubleArgument('cop', true)
178
160
  cop.setDisplayName('Set heat pump rated COP (heating)')
179
- cop.setDefaultValue(2.8)
161
+ cop.setDefaultValue(3.2)
180
162
  args << cop
181
163
 
182
164
  # create argument for electric backup capacity
@@ -289,13 +271,13 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
289
271
 
290
272
  # assign the user inputs to variables
291
273
  remove_wh = runner.getBoolArgumentValue('remove_wh', user_arguments)
292
- loop = runner.getStringArgumentValue('loop', user_arguments)
293
- zone = runner.getStringArgumentValue('zone', user_arguments)
274
+ wh = runner.getStringArgumentValue('wh', user_arguments)
275
+ vol = runner.getDoubleArgumentValue('vol', user_arguments)
294
276
  type = runner.getStringArgumentValue('type', user_arguments)
277
+ zone = runner.getStringArgumentValue('zone', user_arguments)
295
278
  cap = runner.getDoubleArgumentValue('cap', user_arguments)
296
279
  cop = runner.getDoubleArgumentValue('cop', user_arguments)
297
280
  bu_cap = runner.getDoubleArgumentValue('bu_cap', user_arguments)
298
- vol = runner.getDoubleArgumentValue('vol', user_arguments)
299
281
  max_temp = runner.getDoubleArgumentValue('max_temp', user_arguments)
300
282
  min_temp = runner.getDoubleArgumentValue('min_temp', user_arguments)
301
283
  db_temp = runner.getDoubleArgumentValue('db_temp', user_arguments)
@@ -306,15 +288,6 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
306
288
  flex_hrs << runner.getStringArgumentValue('flex_hrs' + n.to_s, user_arguments)
307
289
  end
308
290
 
309
- # check for error inputs
310
- if loop.include?('Error')
311
- runner.registerError('No service hot water loop was found. Measure did not run.')
312
- end
313
-
314
- if zone.include?('Error')
315
- runner.registerError('No thermal zone was found. Measure did not run.')
316
- end
317
-
318
291
  # check capacity, volume, and temps for reasonableness
319
292
  if cap < 5
320
293
  runner.registerWarning('HPWH heating capacity is less than 5kW ( 17kBtu/hr)')
@@ -324,7 +297,9 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
324
297
  runner.registerWarning('Backup heating capaicty is less than 5kW ( 17kBtu/hr).')
325
298
  end
326
299
 
327
- if vol < 40
300
+ if vol == 0
301
+ runner.registerInfo('Tank volume was not specified, using existing tank capacity.')
302
+ elsif vol < 40
328
303
  runner.registerWarning('Tank has less than 40 gallon capacity; check heat pump sizing if model fails.')
329
304
  end
330
305
 
@@ -334,15 +309,15 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
334
309
  'conditions facilitate the growth of Legionella.')
335
310
  end
336
311
 
337
- if max_temp > 180
338
- runner.registerWarning('Maximum charging temperature exceeded practical limits; reset to 180F.')
339
- max_temp = 180.0
312
+ if max_temp > 185
313
+ runner.registerWarning('Maximum charging temperature exceeded practical limits; reset to 185F.')
314
+ max_temp = 185.0
340
315
  end
341
316
 
342
- if max_temp > 160
317
+ if max_temp > 170
343
318
  runner.registerWarning("#{max_temp}F is above or near the limit of the HP performance curves. If the " \
344
319
  'simulation fails with cooling capacity less than 0, you have exceeded performance ' \
345
- 'limits. Consider setting max temp to less than 160F.')
320
+ 'limits. Consider setting max temp to less than 170F.')
346
321
  end
347
322
 
348
323
  # check selected schedule and set flag for later use
@@ -483,7 +458,7 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
483
458
  idx += 1
484
459
  end
485
460
 
486
- ## CONTROLS: TANK TEMPERATURE SETPOINT SCHEDULE (ELECTRIC BACKUP) --------------------------------------------------
461
+ ## END CONTROLS: TANK TEMPERATURE SETPOINT SCHEDULE (ELECTRIC BACKUP) ----------------------------------------------
487
462
 
488
463
  ## HARDWARE --------------------------------------------------------------------------------------------------------
489
464
  # This section adds the selected type of heat pump water heater to the supply side of the selected loop. If
@@ -493,99 +468,122 @@ class AddHphw < OpenStudio::Measure::ModelMeasure
493
468
  # use OS standards build - arbitrary selection, but NZE Ready seems appropriate
494
469
  std = Standard.build('NREL ZNE Ready 2017')
495
470
 
496
- # create empty arrays and initialize variables for later use
497
- old_heater = []
498
- count = 0
499
-
500
- # convert loop and zone names from STRINGS into OS model OBJECTS
501
- zone = model.getThermalZoneByName(zone).get
502
- loop = model.getPlantLoopByName(loop).get
503
-
504
- # find and locate old water heater on selected loop, if applicable
505
- loop_equip = loop.supplyComponents
506
- loop_equip.each do |le|
507
- if le.iddObject.name.include?('WaterHeater:Mixed')
508
- old_heater << model.getWaterHeaterMixedByName(le.name.to_s).get
509
- count += 1
510
- elsif le.iddObject.name.include?('WaterHeater:Stratified')
511
- old_heater << model.getWaterHeaterStratifiedByName(le.name.to_s).get
512
- count += 1
471
+ #####
472
+ # get the selected water heaters
473
+ whtrs = []
474
+ model.getWaterHeaterMixeds.each do |w|
475
+ if wh == 'All Water Heaters (Simplified Only)'
476
+ # exclude booster tanks (<10gal):
477
+ if w.tankVolume.to_f < 0.037854
478
+ next
479
+ else
480
+ whtrs << w
481
+ end
482
+ elsif w.name.to_s == wh
483
+ whtrs << w
513
484
  end
514
485
  end
515
486
 
516
- unless old_heater.empty?
517
- inlet = old_heater[0].supplyInletModelObject.get.to_Node.get
518
- outlet = old_heater[0].supplyOutletModelObject.get.to_Node.get
519
- end
487
+ whtrs.each do |wh|
488
+ # create empty arrays and initialize variables for later use
489
+ old_heater = []
490
+ count = 0
520
491
 
521
- # Add heat pump water heater and attach to selected loop
522
- # Reference: https://github.com/NREL/openstudio-standards/blob/master/lib/
523
- # => openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb
524
- if type != 'Simplified'
525
- hpwh = std.model_add_heatpump_water_heater(model, # model
526
- type: type, # type
527
- water_heater_capacity: (cap * 1000 / cop), # water_heater_capacity
528
- electric_backup_capacity: (bu_cap * 1000), # electric_backup_capacity
529
- water_heater_volume: OpenStudio.convert(vol, 'gal', 'm^3').get, # water_heater_volume
530
- service_water_temperature: OpenStudio.convert(140.0, 'F', 'C').get, # service_water_temperature
531
- parasitic_fuel_consumption_rate: 3.0, # parasitic_fuel_consumption_rate
532
- swh_temp_sch: sched, # swh_temp_sch
533
- cop: cop, # cop
534
- shr: 0.88, # shr
535
- tank_ua: 3.9, # tank_ua
536
- set_peak_use_flowrate: false, # set_peak_use_flowrate
537
- peak_flowrate: 0.0, # peak_flowrate
538
- flowrate_schedule: nil, # flowrate_schedule
539
- water_heater_thermal_zone: zone) # water_heater_thermal_zone
540
- else
541
- hpwh = std.model_add_water_heater(model, # model
542
- (cap * 1000), # water_heater_capacity
543
- OpenStudio.convert(vol, 'gal', 'm^3').get, # water_heater_volume
544
- 'HeatPump', # water_heater_fuel
545
- OpenStudio.convert(140.0, 'F', 'C').get, # service_water_temperature
546
- 3.0, # parasitic_fuel_consumption_rate
547
- sched, # swh_temp_sch
548
- false, # set_peak_use_flowrate
549
- 0.0, # peak_flowrate
550
- nil, # flowrate_schedule
551
- zone, # water_heater_thermal_zone
552
- 1) # number_water_heaters
553
- end
492
+ # get the appropriate plant loop
493
+ loop = ''
494
+ loops = model.getPlantLoops
495
+ loops.each do |l|
496
+ l.supplyComponents.each do |c|
497
+ if c.name.to_s == wh.name.to_s
498
+ loop = l
499
+ end
500
+ end
501
+ end
554
502
 
555
- # add tank to appropriate branch and node (will be placed first in series if old tanks not removed)
556
- # modify objects as ncessary
557
- if old_heater.empty?
558
- loop.addSupplyBranchForComponent(hpwh.tank)
559
- elsif type != 'Simplified'
560
- hpwh.tank.addToNode(inlet)
561
- hpwh.setDeadBandTemperatureDifference(db_temp / 1.8)
562
- runner.registerInfo("#{hpwh.tank.name} was added to the model on #{loop.name}")
563
- else
564
- hpwh.addToNode(inlet)
565
- hpwh.setMaximumTemperatureLimit(OpenStudio.convert(max_temp, 'F', 'C').get)
566
- runner.registerInfo("#{hpwh.name} was added to the model on #{loop.name}")
567
- end
503
+ # use existing tank volume unless otherwise specified
504
+ # values between 0.0 and 5.0 are considered tank sizing multipliers
505
+ if vol == 0
506
+ v = wh.tankVolume
507
+ elsif (vol > 0.0) && (vol < 5.0)
508
+ v = wh.tankVolume.to_f * vol
509
+ else
510
+ v = OpenStudio.convert(vol, 'gal', 'm^3').get
511
+ end
568
512
 
569
- # remove old tank objects if necessary
570
- if remove_wh
571
- old_heater.each do |oh|
572
- runner.registerInfo("#{oh.name} was removed from the model.")
573
- oh.remove
513
+ inlet = wh.supplyInletModelObject.get.to_Node.get
514
+ outlet = wh.supplyOutletModelObject.get.to_Node.get
515
+
516
+ # Add heat pump water heater and attach to selected loop
517
+ # Reference: https://github.com/NREL/openstudio-standards/blob/master/lib/
518
+ # => openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb
519
+ if type != 'Simplified'
520
+ # convert zone name from STRING into OS model OBJECT
521
+ zone = model.getThermalZoneByName(zone).get
522
+ hpwh = std.model_add_heatpump_water_heater(model, # model
523
+ type: type, # type
524
+ water_heater_capacity: (cap * 1000 / cop), # water_heater_capacity
525
+ electric_backup_capacity: (bu_cap * 1000), # electric_backup_capacity
526
+ water_heater_volume: v, # water_heater_volume
527
+ service_water_temperature: OpenStudio.convert(140.0, 'F', 'C').get, # service_water_temperature
528
+ parasitic_fuel_consumption_rate: 3.0, # parasitic_fuel_consumption_rate
529
+ swh_temp_sch: sched, # swh_temp_sch
530
+ cop: cop, # cop
531
+ shr: 0.88, # shr
532
+ tank_ua: 3.9, # tank_ua
533
+ set_peak_use_flowrate: false, # set_peak_use_flowrate
534
+ peak_flowrate: 0.0, # peak_flowrate
535
+ flowrate_schedule: nil, # flowrate_schedule
536
+ water_heater_thermal_zone: zone) # water_heater_thermal_zone
537
+ else
538
+ # zone = wh.ambientTemperatureThermalZone.get
539
+ runner.registerWarning(wh.to_s)
540
+ hpwh = std.model_add_water_heater(model, # model
541
+ (cap * 1000), # water_heater_capacity
542
+ v.to_f, # water_heater_volume
543
+ 'HeatPump', # water_heater_fuel
544
+ OpenStudio.convert(140.0, 'F', 'C').to_f, # service_water_temperature
545
+ 3.0, # parasitic_fuel_consumption_rate
546
+ sched, # swh_temp_sch
547
+ false, # set_peak_use_flowrate
548
+ 0.0, # peak_flowrate
549
+ nil, # flowrate_schedule
550
+ model.getThermalZones[0], # water_heater_thermal_zone
551
+ 1) # number_water_heaters
552
+ # set COP in PLF curve
553
+ cop_curve = hpwh.partLoadFactorCurve.get
554
+ cop_curve.setName(cop_curve.name.get.gsub('2.8', cop.to_s))
555
+ cop_curve.setCoefficient1Constant(cop)
556
+ end
557
+
558
+ # add tank to appropriate branch and node (will be placed first in series if old tanks not removed)
559
+ # modify objects as ncessary
560
+ if type != 'Simplified'
561
+ hpwh.tank.addToNode(inlet)
562
+ hpwh.setDeadBandTemperatureDifference(db_temp / 1.8)
563
+ runner.registerInfo("#{hpwh.tank.name} was added to the model on #{loop.name}")
564
+ else
565
+ hpwh.addToNode(inlet)
566
+ hpwh.setMaximumTemperatureLimit(OpenStudio.convert(max_temp, 'F', 'C').get)
567
+ runner.registerInfo("#{hpwh.name} was added to the model on #{loop.name}")
574
568
  end
575
- end
576
- ## END HARDWARE ----------------------------------------------------------------------------------------------------
577
569
 
578
- ## CONTROLS MODIFICATIONS FOR TANK ---------------------------------------------------------------------------------
579
- # apply schedule to tank
580
- if type == 'PumpedCondenser'
581
- hpwh.tank.to_WaterHeaterMixed.get.setSetpointTemperatureSchedule(tank_sched)
582
- elsif type == 'WrappedCondenser'
583
- hpwh.tank.to_WaterHeaterStratified.get.setHeater1SetpointTemperatureSchedule(tank_sched)
584
- hpwh.tank.to_WaterHeaterStratified.get.setHeater2SetpointTemperatureSchedule(tank_sched)
585
- elsif type == 'Simplified'
586
- runner.registerInfo('Line 492 was used. Nothing done here yet... Check tank temperature schedules...')
570
+ # remove old tank objects if necessary
571
+ if remove_wh
572
+ runner.registerInfo("#{wh.name} was removed from the model.")
573
+ wh.remove
574
+ end
575
+
576
+ # CONTROLS MODIFICATIONS FOR TANK ---------------------------------------------------------------------------------
577
+ # apply schedule to tank
578
+ if type == 'PumpedCondenser'
579
+ hpwh.tank.to_WaterHeaterMixed.get.setSetpointTemperatureSchedule(tank_sched)
580
+ elsif type == 'WrappedCondenser'
581
+ hpwh.tank.to_WaterHeaterStratified.get.setHeater1SetpointTemperatureSchedule(tank_sched)
582
+ hpwh.tank.to_WaterHeaterStratified.get.setHeater2SetpointTemperatureSchedule(tank_sched)
583
+ end
584
+ # END CONTROLS MODIFICATIONS FOR TANK -----------------------------------------------------------------------------
587
585
  end
588
- ## END CONTROLS MODIFICATIONS FOR TANK -----------------------------------------------------------------------------
586
+ ## END HARDWARE ----------------------------------------------------------------------------------------------------
589
587
 
590
588
  ## ADD REPORTED VARIABLES ------------------------------------------------------------------------------------------
591
589
 
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.0</schema_version>
4
4
  <name>add_hphw</name>
5
5
  <uid>518cde6f-1806-4b9a-bee9-ccaac49c7a53</uid>
6
- <version_id>0a64fe16-eef8-4026-a3a6-45fa8dcad162</version_id>
7
- <version_modified>20210317T134945Z</version_modified>
6
+ <version_id>1ddd139f-d267-4817-95c1-339d78c6594e</version_id>
7
+ <version_modified>20210512T163832Z</version_modified>
8
8
  <xml_checksum>A374667A</xml_checksum>
9
9
  <class_name>AddHphw</class_name>
10
10
  <display_name>Add HPWH for Domestic Hot Water</display_name>
@@ -18,6 +18,7 @@ The flexibility of the system is based on user-defined temperatures and times, w
18
18
  <display_name>Remove existing water heater on selected loop</display_name>
19
19
  <description></description>
20
20
  <type>Boolean</type>
21
+ <units></units>
21
22
  <required>true</required>
22
23
  <model_dependent>false</model_dependent>
23
24
  <default_value>true</default_value>
@@ -31,12 +32,15 @@ The flexibility of the system is based on user-defined temperatures and times, w
31
32
  <display_name>false</display_name>
32
33
  </choice>
33
34
  </choices>
35
+ <min_value></min_value>
36
+ <max_value></max_value>
34
37
  </argument>
35
38
  <argument>
36
39
  <name>loop</name>
37
40
  <display_name>Select hot water loop</display_name>
38
41
  <description>The water tank will be placed on the supply side of this loop.</description>
39
42
  <type>Choice</type>
43
+ <units></units>
40
44
  <required>true</required>
41
45
  <model_dependent>false</model_dependent>
42
46
  <default_value>Error: No Service Water Loop Found</default_value>
@@ -46,12 +50,15 @@ The flexibility of the system is based on user-defined temperatures and times, w
46
50
  <display_name>Error: No Service Water Loop Found</display_name>
47
51
  </choice>
48
52
  </choices>
53
+ <min_value></min_value>
54
+ <max_value></max_value>
49
55
  </argument>
50
56
  <argument>
51
57
  <name>zone</name>
52
58
  <display_name>Select thermal zone</display_name>
53
59
  <description>This is where the water heater tank will be placed</description>
54
60
  <type>Choice</type>
61
+ <units></units>
55
62
  <required>true</required>
56
63
  <model_dependent>false</model_dependent>
57
64
  <default_value>Error: No Thermal Zones Found</default_value>
@@ -61,15 +68,18 @@ The flexibility of the system is based on user-defined temperatures and times, w
61
68
  <display_name>Error: No Thermal Zones Found</display_name>
62
69
  </choice>
63
70
  </choices>
71
+ <min_value></min_value>
72
+ <max_value></max_value>
64
73
  </argument>
65
74
  <argument>
66
75
  <name>type</name>
67
76
  <display_name>Select heat pump water heater type</display_name>
68
77
  <description></description>
69
78
  <type>Choice</type>
79
+ <units></units>
70
80
  <required>true</required>
71
81
  <model_dependent>false</model_dependent>
72
- <default_value>PumpedCondenser</default_value>
82
+ <default_value>Simplified</default_value>
73
83
  <choices>
74
84
  <choice>
75
85
  <value>PumpedCondenser</value>
@@ -84,74 +94,99 @@ The flexibility of the system is based on user-defined temperatures and times, w
84
94
  <display_name>Simplified</display_name>
85
95
  </choice>
86
96
  </choices>
97
+ <min_value></min_value>
98
+ <max_value></max_value>
87
99
  </argument>
88
100
  <argument>
89
101
  <name>vol</name>
90
102
  <display_name>Set hot water tank volume</display_name>
91
103
  <description>[gal]</description>
92
104
  <type>Double</type>
105
+ <units></units>
93
106
  <required>true</required>
94
107
  <model_dependent>false</model_dependent>
95
108
  <default_value>80</default_value>
109
+ <min_value></min_value>
110
+ <max_value></max_value>
96
111
  </argument>
97
112
  <argument>
98
113
  <name>cap</name>
99
114
  <display_name>Set heat pump heating capacity</display_name>
100
115
  <description>[kW]</description>
101
116
  <type>Double</type>
117
+ <units></units>
102
118
  <required>true</required>
103
119
  <model_dependent>false</model_dependent>
104
120
  <default_value>23.4</default_value>
121
+ <min_value></min_value>
122
+ <max_value></max_value>
105
123
  </argument>
106
124
  <argument>
107
125
  <name>cop</name>
108
126
  <display_name>Set heat pump rated COP (heating)</display_name>
127
+ <description></description>
109
128
  <type>Double</type>
129
+ <units></units>
110
130
  <required>true</required>
111
131
  <model_dependent>false</model_dependent>
112
132
  <default_value>2.8</default_value>
133
+ <min_value></min_value>
134
+ <max_value></max_value>
113
135
  </argument>
114
136
  <argument>
115
137
  <name>bu_cap</name>
116
138
  <display_name>Set electric backup heating capacity</display_name>
117
139
  <description>[kW]</description>
118
140
  <type>Double</type>
141
+ <units></units>
119
142
  <required>true</required>
120
143
  <model_dependent>false</model_dependent>
121
144
  <default_value>23.4</default_value>
145
+ <min_value></min_value>
146
+ <max_value></max_value>
122
147
  </argument>
123
148
  <argument>
124
149
  <name>max_temp</name>
125
150
  <display_name>Set maximum tank temperature</display_name>
126
151
  <description>[F]</description>
127
152
  <type>Double</type>
153
+ <units></units>
128
154
  <required>true</required>
129
155
  <model_dependent>false</model_dependent>
130
156
  <default_value>160</default_value>
157
+ <min_value></min_value>
158
+ <max_value></max_value>
131
159
  </argument>
132
160
  <argument>
133
161
  <name>min_temp</name>
134
162
  <display_name>Set minimum tank temperature during float</display_name>
135
163
  <description>[F]</description>
136
164
  <type>Double</type>
165
+ <units></units>
137
166
  <required>true</required>
138
167
  <model_dependent>false</model_dependent>
139
168
  <default_value>120</default_value>
169
+ <min_value></min_value>
170
+ <max_value></max_value>
140
171
  </argument>
141
172
  <argument>
142
173
  <name>db_temp</name>
143
174
  <display_name>Set deadband temperature difference between heat pump and electric backup</display_name>
144
175
  <description>[F]</description>
145
176
  <type>Double</type>
177
+ <units></units>
146
178
  <required>true</required>
147
179
  <model_dependent>false</model_dependent>
148
180
  <default_value>5</default_value>
181
+ <min_value></min_value>
182
+ <max_value></max_value>
149
183
  </argument>
150
184
  <argument>
151
185
  <name>sched</name>
152
186
  <display_name>Select reference tank setpoint temperature schedule</display_name>
153
187
  <description></description>
154
188
  <type>Choice</type>
189
+ <units></units>
155
190
  <required>true</required>
156
191
  <model_dependent>false</model_dependent>
157
192
  <default_value>--Create New @ 140F--</default_value>
@@ -161,12 +196,15 @@ The flexibility of the system is based on user-defined temperatures and times, w
161
196
  <display_name>--Create New @ 140F--</display_name>
162
197
  </choice>
163
198
  </choices>
199
+ <min_value></min_value>
200
+ <max_value></max_value>
164
201
  </argument>
165
202
  <argument>
166
203
  <name>flex0</name>
167
204
  <display_name>Daily Flex Period 1:</display_name>
168
205
  <description>Applies every day in the full run period.</description>
169
206
  <type>Choice</type>
207
+ <units></units>
170
208
  <required>true</required>
171
209
  <model_dependent>false</model_dependent>
172
210
  <default_value>None</default_value>
@@ -188,20 +226,27 @@ The flexibility of the system is based on user-defined temperatures and times, w
188
226
  <display_name>Float</display_name>
189
227
  </choice>
190
228
  </choices>
229
+ <min_value></min_value>
230
+ <max_value></max_value>
191
231
  </argument>
192
232
  <argument>
193
233
  <name>flex_hrs0</name>
194
234
  <display_name>Use 24-Hour Format</display_name>
235
+ <description></description>
195
236
  <type>String</type>
237
+ <units></units>
196
238
  <required>false</required>
197
239
  <model_dependent>false</model_dependent>
198
240
  <default_value>HH:MM - HH:MM</default_value>
241
+ <min_value></min_value>
242
+ <max_value></max_value>
199
243
  </argument>
200
244
  <argument>
201
245
  <name>flex1</name>
202
246
  <display_name>Daily Flex Period 2:</display_name>
203
247
  <description>Applies every day in the full run period.</description>
204
248
  <type>Choice</type>
249
+ <units></units>
205
250
  <required>true</required>
206
251
  <model_dependent>false</model_dependent>
207
252
  <default_value>None</default_value>
@@ -223,20 +268,27 @@ The flexibility of the system is based on user-defined temperatures and times, w
223
268
  <display_name>Float</display_name>
224
269
  </choice>
225
270
  </choices>
271
+ <min_value></min_value>
272
+ <max_value></max_value>
226
273
  </argument>
227
274
  <argument>
228
275
  <name>flex_hrs1</name>
229
276
  <display_name>Use 24-Hour Format</display_name>
277
+ <description></description>
230
278
  <type>String</type>
279
+ <units></units>
231
280
  <required>false</required>
232
281
  <model_dependent>false</model_dependent>
233
282
  <default_value>HH:MM - HH:MM</default_value>
283
+ <min_value></min_value>
284
+ <max_value></max_value>
234
285
  </argument>
235
286
  <argument>
236
287
  <name>flex2</name>
237
288
  <display_name>Daily Flex Period 3:</display_name>
238
289
  <description>Applies every day in the full run period.</description>
239
290
  <type>Choice</type>
291
+ <units></units>
240
292
  <required>true</required>
241
293
  <model_dependent>false</model_dependent>
242
294
  <default_value>None</default_value>
@@ -258,20 +310,27 @@ The flexibility of the system is based on user-defined temperatures and times, w
258
310
  <display_name>Float</display_name>
259
311
  </choice>
260
312
  </choices>
313
+ <min_value></min_value>
314
+ <max_value></max_value>
261
315
  </argument>
262
316
  <argument>
263
317
  <name>flex_hrs2</name>
264
318
  <display_name>Use 24-Hour Format</display_name>
319
+ <description></description>
265
320
  <type>String</type>
321
+ <units></units>
266
322
  <required>false</required>
267
323
  <model_dependent>false</model_dependent>
268
324
  <default_value>HH:MM - HH:MM</default_value>
325
+ <min_value></min_value>
326
+ <max_value></max_value>
269
327
  </argument>
270
328
  <argument>
271
329
  <name>flex3</name>
272
330
  <display_name>Daily Flex Period 4:</display_name>
273
331
  <description>Applies every day in the full run period.</description>
274
332
  <type>Choice</type>
333
+ <units></units>
275
334
  <required>true</required>
276
335
  <model_dependent>false</model_dependent>
277
336
  <default_value>None</default_value>
@@ -293,14 +352,20 @@ The flexibility of the system is based on user-defined temperatures and times, w
293
352
  <display_name>Float</display_name>
294
353
  </choice>
295
354
  </choices>
355
+ <min_value></min_value>
356
+ <max_value></max_value>
296
357
  </argument>
297
358
  <argument>
298
359
  <name>flex_hrs3</name>
299
360
  <display_name>Use 24-Hour Format</display_name>
361
+ <description></description>
300
362
  <type>String</type>
363
+ <units></units>
301
364
  <required>false</required>
302
365
  <model_dependent>false</model_dependent>
303
366
  <default_value>HH:MM - HH:MM</default_value>
367
+ <min_value></min_value>
368
+ <max_value></max_value>
304
369
  </argument>
305
370
  </arguments>
306
371
  <outputs />
@@ -376,12 +441,6 @@ The flexibility of the system is based on user-defined temperatures and times, w
376
441
  <usage_type>test</usage_type>
377
442
  <checksum>15E27276</checksum>
378
443
  </file>
379
- <file>
380
- <filename>README.md</filename>
381
- <filetype>md</filetype>
382
- <usage_type>readme</usage_type>
383
- <checksum>1FE9503E</checksum>
384
- </file>
385
444
  <file>
386
445
  <version>
387
446
  <software_program>OpenStudio</software_program>
@@ -391,7 +450,14 @@ The flexibility of the system is based on user-defined temperatures and times, w
391
450
  <filename>measure.rb</filename>
392
451
  <filetype>rb</filetype>
393
452
  <usage_type>script</usage_type>
394
- <checksum>F8FEB798</checksum>
453
+ <checksum>44E0C02B</checksum>
454
+ </file>
455
+ <file>
456
+ <filename>README.md</filename>
457
+ <filetype>md</filetype>
458
+ <usage_type>readme</usage_type>
459
+ <checksum>0B68E96D</checksum>
395
460
  </file>
396
461
  </files>
397
462
  </measure>
463
+ <error>undefined method `each' for nil:NilClass</error>
@@ -3,8 +3,8 @@
3
3
  <schema_version>3.0</schema_version>
4
4
  <name>add_packaged_ice_storage</name>
5
5
  <uid>2aa8c128-53b9-49fd-9aaf-9253a1f05936</uid>
6
- <version_id>1a0ab79e-1825-4418-a4ad-aec2194d4707</version_id>
7
- <version_modified>20201208T224029Z</version_modified>
6
+ <version_id>c0df7e6f-d86f-4f80-875d-420a727dbf8a</version_id>
7
+ <version_modified>20210421T154438Z</version_modified>
8
8
  <xml_checksum>2617824F</xml_checksum>
9
9
  <class_name>AddPackagedIceStorage</class_name>
10
10
  <display_name>Add Packaged Ice Storage</display_name>
@@ -224,12 +224,6 @@ If 'AutoSize' is selected for ice capacity, these inputs set an ice capacity siz
224
224
  <usage_type>test</usage_type>
225
225
  <checksum>2D918464</checksum>
226
226
  </file>
227
- <file>
228
- <filename>README.md</filename>
229
- <filetype>md</filetype>
230
- <usage_type>readme</usage_type>
231
- <checksum>A67F3738</checksum>
232
- </file>
233
227
  <file>
234
228
  <version>
235
229
  <software_program>OpenStudio</software_program>
@@ -241,5 +235,11 @@ If 'AutoSize' is selected for ice capacity, these inputs set an ice capacity siz
241
235
  <usage_type>script</usage_type>
242
236
  <checksum>749A70A0</checksum>
243
237
  </file>
238
+ <file>
239
+ <filename>README.md</filename>
240
+ <filetype>md</filetype>
241
+ <usage_type>readme</usage_type>
242
+ <checksum>E6FBC489</checksum>
243
+ </file>
244
244
  </files>
245
245
  </measure>
@@ -35,6 +35,6 @@
35
35
 
36
36
  module OpenStudio
37
37
  module LoadFlexibilityMeasures
38
- VERSION = '0.3.1'.freeze
38
+ VERSION = '0.3.2'.freeze
39
39
  end
40
40
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstudio-load-flexibility-measures
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karl Heine
8
8
  - Ryan Meyer
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-04-22 00:00:00.000000000 Z
12
+ date: 2021-06-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -147,7 +147,7 @@ files:
147
147
  homepage: https://openstudio.net
148
148
  licenses: []
149
149
  metadata: {}
150
- post_install_message:
150
+ post_install_message:
151
151
  rdoc_options: []
152
152
  require_paths:
153
153
  - lib
@@ -162,8 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
162
  - !ruby/object:Gem::Version
163
163
  version: '0'
164
164
  requirements: []
165
- rubygems_version: 3.1.2
166
- signing_key:
165
+ rubygems_version: 3.1.4
166
+ signing_key:
167
167
  specification_version: 4
168
168
  summary: library and measures for OpenStudio for load flexibility applications.
169
169
  test_files: []