openstudio-load-flexibility-measures 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []