urbanopt-reporting 0.3.3 → 0.3.4

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: e65d30b14cf3916be1251dd1092dd74f222e737a0c9d6e6278123f4c6101b503
4
- data.tar.gz: 4fa5c62490c7dcc883c5308f8f31547090f1eef01914b0e3e54093e218f09bf9
3
+ metadata.gz: 75187e938a1cbfabd1d74eba912af03fcd2aade54955a490d68ea1b97b229dd2
4
+ data.tar.gz: 25b56a46e4569a71a7c01964bf64f2a14d8c30fdc9f6f5167fd61b40f272eb52
5
5
  SHA512:
6
- metadata.gz: 0e0fdd09a89d58be74b9506fc9904253b0121f0d117041799baa500f3a0b1ab07f907609e0495486943751203c1f8683cc564ffcb038cb944721e1751e79c6f3
7
- data.tar.gz: 067ab1a1d6506c22933a1e4e9e09dac96ecc925e4d3d931bfc51bd6853faf99e658c4b578f6689d9e34cc5ff5533c77dab1d8533ccef1384963ad7a85ac627e1
6
+ metadata.gz: 5a5f20c29cc1eec6aafeece4479a52c4c5a6a0ecfb0374a0b8f243551f9a7d49ecfbcf25b233ce7e19441551adcd87c5eb668ad509d4c87b0681ea1a187da6b2
7
+ data.tar.gz: bccc2ad11e97d3330f2706cb9a7d32c5c0209130af88738854e6d56fb6d34b5ccfcc8b51b42633d3f359bf4c03c34d4888108528bd38c558c96ec06569c92e9d
@@ -1,5 +1,12 @@
1
1
  # URBANopt Reporting Gem
2
2
 
3
+ ## Version 0.3.4
4
+
5
+ Date Range: 01/14/21 - 01/15/21
6
+
7
+ - Fixed [#53]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/53 ), Make subfolders in feature saving if necessary
8
+ - Fixed [#55]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/55 ), Fix new measures
9
+
3
10
  ## Version 0.3.3
4
11
 
5
12
  Date Range: 12/09/20 - 01/13/21
@@ -505,18 +505,17 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
505
505
  feature_report.program.roof_area_sqft[:total_roof_area_sqft] = total_roof_area_sqft
506
506
 
507
507
  # available_roof_area_sqft
508
- # RK: a more robust method should be implemented to find the available_roof_area
508
+ # RK: a more robust method should be implemented to find the available_roof_area
509
509
  # assign available roof area to be a percentage of the total roof area
510
510
 
511
511
  if building_types[0][:building_type].include? 'Single-Family Detached'
512
512
  feature_report.program.roof_area_sqft[:available_roof_area_sqft] = 0.45 * total_roof_area_sqft
513
- else
513
+ else
514
514
  feature_report.program.roof_area_sqft[:available_roof_area_sqft] = 0.75 * total_roof_area_sqft
515
515
  end
516
516
 
517
517
  # RK: Temporary solution: assign available roof area to be equal to total roof area
518
- #feature_report.program.roof_area_sqft[:available_roof_area_sqft] = total_roof_area_sqft
519
-
518
+ # feature_report.program.roof_area_sqft[:available_roof_area_sqft] = total_roof_area_sqft
520
519
 
521
520
  # orientation
522
521
  # RK: a more robust method should be implemented to find orientation(finding main axis of the building using aspect ratio)
@@ -82,37 +82,38 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
82
82
  return false
83
83
  end
84
84
 
85
- result << OpenStudio::IdfObject.load('Output:Variable,,Site Mains Water Temperature,hourly;').get
86
- result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,hourly;').get
87
- result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,hourly;').get
88
- result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,hourly;').get
89
- result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,hourly;').get
90
- result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,hourly;').get
91
- result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,hourly;').get
92
- result << OpenStudio::IdfObject.load('Output:Meter,Fans:Electricity,hourly;').get
93
- result << OpenStudio::IdfObject.load('Output:Meter,InteriorEquipment:Electricity,hourly;').get # Joules
94
- result << OpenStudio::IdfObject.load('Output:Meter,ExteriorLighting:Electricity,hourly;').get # Joules
95
- result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,hourly;').get # Joules
96
- result << OpenStudio::IdfObject.load('Output:Meter,Gas:Facility,hourly;').get # Joules
97
- result << OpenStudio::IdfObject.load('Output:Meter,Heating:EnergyTransfer,hourly;').get # Joules
98
- result << OpenStudio::IdfObject.load('Output:Meter,WaterSystems:EnergyTransfer,hourly;').get # Joules
85
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Mains Water Temperature,timestep;').get
86
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,timestep;').get
87
+ result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,timestep;').get
88
+ result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,timestep;').get
89
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,timestep;').get
90
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,timestep;').get
91
+ result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,timestep;').get
92
+ result << OpenStudio::IdfObject.load('Output:Meter,Fans:Electricity,timestep;').get
93
+ result << OpenStudio::IdfObject.load('Output:Meter,InteriorEquipment:Electricity,timestep;').get # Joules
94
+ result << OpenStudio::IdfObject.load('Output:Meter,ExteriorLighting:Electricity,timestep;').get # Joules
95
+ result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get # Joules
96
+ result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get ##Using this for data at timestep interval
97
+ result << OpenStudio::IdfObject.load('Output:Meter,Gas:Facility,timestep;').get # Joules
98
+ result << OpenStudio::IdfObject.load('Output:Meter,Heating:EnergyTransfer,timestep;').get # Joules
99
+ result << OpenStudio::IdfObject.load('Output:Meter,WaterSystems:EnergyTransfer,timestep;').get # Joules
99
100
  # these variables are used for the modelica export.
100
- result << OpenStudio::IdfObject.load('Output:Variable,*,Zone Predicted Sensible Load to Setpoint Heat Transfer Rate,hourly;').get # watts according to e+
101
- result << OpenStudio::IdfObject.load('Output:Variable,*,Water Heater Total Demand Heat Transfer Rate,hourly;').get # Watts
101
+ result << OpenStudio::IdfObject.load('Output:Variable,*,Zone Predicted Sensible Load to Setpoint Heat Transfer Rate,timestep;').get # watts according to e+
102
+ result << OpenStudio::IdfObject.load('Output:Variable,*,Water Heater Total Demand Heat Transfer Rate,timestep;').get # Watts
102
103
 
103
104
  return result
104
105
  end
105
106
 
106
- def extract_timeseries_into_matrix(sqlfile, data, variable_name, key_value = nil, default_if_empty=0)
107
+ def extract_timeseries_into_matrix(sqlfile, data, variable_name, key_value = nil, default_if_empty = 0, timestep)
107
108
  log "Executing query for #{variable_name}"
108
109
  column_name = variable_name
109
110
  if key_value
110
- ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name, key_value)
111
- # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
111
+ # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name, key_value)
112
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
112
113
  column_name += "_#{key_value}"
113
114
  else
114
- ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
115
- # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
115
+ # ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
116
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
116
117
  end
117
118
  log 'Iterating over timeseries'
118
119
  column = [column_name.delete(':').delete(' ')] # Set the header of the data to the variable name, removing : and spaces
@@ -120,7 +121,7 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
120
121
  if ts.empty?
121
122
  log "No time series for #{variable_name}:#{key_value}... defaulting to #{default_if_empty}"
122
123
  # needs to be data.size-1 since the column name is already stored above (+=)
123
- column += [default_if_empty] * (data.size-1)
124
+ column += [default_if_empty] * (data.size - 1)
124
125
  else
125
126
  ts = ts.get if ts.respond_to?(:get)
126
127
  ts = ts.first if ts.respond_to?(:first)
@@ -154,10 +155,10 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
154
155
  log "Finished extracting #{variable_name}"
155
156
  end
156
157
 
157
- def create_new_variable_sum(data, new_var_name, include_str, options=nil)
158
+ def create_new_variable_sum(data, new_var_name, include_str, options = nil)
158
159
  var_info = {
159
- name: new_var_name,
160
- var_indexes: []
160
+ name: new_var_name,
161
+ var_indexes: []
161
162
  }
162
163
  data.each_with_index do |row, index|
163
164
  if index.zero?
@@ -212,6 +213,9 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
212
213
  end
213
214
  model = model.get
214
215
 
216
+ timesteps_per_hour=model.getTimestep.numberOfTimestepsPerHour.to_i
217
+ timestep=60/timesteps_per_hour #timestep in minutes
218
+
215
219
  sqlFile = runner.lastEnergyPlusSqlFile
216
220
  if sqlFile.empty?
217
221
  runner.registerError('Cannot find last sql file.')
@@ -233,45 +237,47 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
233
237
  ]
234
238
 
235
239
  # just grab one of the variables to get the date/time stamps
236
- # ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', 'Cooling:Electricity')
237
- ts = sqlFile.timeSeries('RUN PERIOD 1', 'Hourly', 'Cooling:Electricity')
238
- unless ts.empty?
240
+ attribute_name = 'Electricity:Facility'
241
+ ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', attribute_name)
242
+ if ts.empty?
243
+ runner.registerError("This feature does not have the attribute '#{attribute_name}' to enable this measure to work." \
244
+ "To resolve, simulate a building with electricity or remove this measure from your workflow.")
245
+ else
239
246
  ts = ts.first
240
247
  dt_base = nil
241
248
  # Save off the date time values
242
249
  ts.dateTimes.each_with_index do |dt, index|
243
- runner.registerInfo("My index is #{index}")
244
250
  dt_base = DateTime.parse(dt.to_s) if dt_base.nil?
245
251
  dt_current = DateTime.parse(dt.to_s)
246
252
  rows << [
247
253
  DateTime.parse(dt.to_s).strftime('%m/%d/%Y %H:%M'),
248
- dt.date.monthOfYear.value,
249
- dt.date.dayOfMonth,
250
- dt.date.dayOfWeek.value,
251
- dt.time.hours,
252
- dt.time.minutes,
253
- dt_current.to_time.to_i - dt_base.to_time.to_i
254
+ dt.date.monthOfYear.value,
255
+ dt.date.dayOfMonth,
256
+ dt.date.dayOfWeek.value,
257
+ dt.time.hours,
258
+ dt.time.minutes,
259
+ dt_current.to_time.to_i - dt_base.to_time.to_i + timestep*60
254
260
  ]
255
261
  end
256
262
  end
257
263
 
258
264
  # add in the other variables by columns -- should really pull this from the report variables defined above
259
- extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Drybulb Temperature', 'Environment', 0)
260
- extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Relative Humidity', 'Environment', 0)
261
- extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Electricity', nil, 0)
262
- extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Gas', nil, 0)
263
- extract_timeseries_into_matrix(sqlFile, rows, 'Cooling:Electricity', nil, 0)
264
- extract_timeseries_into_matrix(sqlFile, rows, 'Electricity:Facility', nil, 0)
265
- extract_timeseries_into_matrix(sqlFile, rows, 'Gas:Facility', nil, 0)
266
- extract_timeseries_into_matrix(sqlFile, rows, 'Heating:EnergyTransfer', nil, 0)
267
- extract_timeseries_into_matrix(sqlFile, rows, 'WaterSystems:EnergyTransfer', nil, 0)
265
+ extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Drybulb Temperature', 'Environment', 0, timestep)
266
+ extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Relative Humidity', 'Environment', 0, timestep)
267
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Electricity', nil, 0, timestep)
268
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Gas', nil, 0, timestep)
269
+ extract_timeseries_into_matrix(sqlFile, rows, 'Cooling:Electricity', nil, 0, timestep)
270
+ extract_timeseries_into_matrix(sqlFile, rows, 'Electricity:Facility', nil, 0, timestep)
271
+ extract_timeseries_into_matrix(sqlFile, rows, 'Gas:Facility', nil, 0, timestep)
272
+ extract_timeseries_into_matrix(sqlFile, rows, 'Heating:EnergyTransfer', nil, 0, timestep)
273
+ extract_timeseries_into_matrix(sqlFile, rows, 'WaterSystems:EnergyTransfer', nil, 0, timestep)
268
274
 
269
275
  # get all zones and save the names for later use in aggregation.
270
276
  tz_names = []
271
277
  model.getThermalZones.each do |tz|
272
278
  tz_names << tz.name.get if tz.name.is_initialized
273
- extract_timeseries_into_matrix(sqlFile, rows, 'Zone Predicted Sensible Load to Setpoint Heat Transfer Rate', tz_names.last, 0)
274
- extract_timeseries_into_matrix(sqlFile, rows, 'Water Heater Heating Rate', tz_names.last, 0)
279
+ extract_timeseries_into_matrix(sqlFile, rows, 'Zone Predicted Sensible Load to Setpoint Heat Transfer Rate', tz_names.last, 0, timestep)
280
+ extract_timeseries_into_matrix(sqlFile, rows, 'Water Heater Heating Rate', tz_names.last, 0, timestep)
275
281
  end
276
282
 
277
283
  # sum up a couple of the columns and create a new columns
@@ -346,7 +352,7 @@ class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
346
352
  # Find the total runtime for energyplus and save it into a registerValue
347
353
  total_time = -999
348
354
  location_of_file = ['../eplusout.end', './run/eplusout.end']
349
- first_index = location_of_file.map {|f| File.exist?(f)}.index(true)
355
+ first_index = location_of_file.map { |f| File.exist?(f) }.index(true)
350
356
  if first_index
351
357
  match = File.read(location_of_file[first_index]).to_s.match(/Elapsed.Time=(.*)hr(.*)min(.*)sec/)
352
358
  total_time = match[1].to_i * 3600 + match[2].to_i * 60 + match[3].to_f
@@ -61,25 +61,25 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
61
61
  puts "#{Time.now}: #{str}"
62
62
  end
63
63
 
64
- def arguments(_model)
64
+ def arguments(_model)
65
65
  args = OpenStudio::Measure::OSArgumentVector.new
66
-
66
+
67
67
  hhw_loop_name = OpenStudio::Measure::OSArgument.makeStringArgument('hhw_loop_name', true)
68
68
  hhw_loop_name.setDisplayName('Name or Partial Name of Heating Hot Water Loop, non-case-sensitive')
69
69
  hhw_loop_name.setDefaultValue('hot')
70
70
  args << hhw_loop_name
71
-
72
- chw_loop_name = OpenStudio::Measure::OSArgument.makeStringArgument('chw_loop_name', true)
71
+
72
+ chw_loop_name = OpenStudio::Measure::OSArgument.makeStringArgument('chw_loop_name', true)
73
73
  chw_loop_name.setDisplayName('Name or Partial Name of Chilled Water Loop, non-case-sensitive')
74
74
  chw_loop_name.setDefaultValue('chilled')
75
75
  args << chw_loop_name
76
-
77
- dec_places_mass_flow = OpenStudio::Measure::OSArgument.makeIntegerArgument('dec_places_mass_flow', true)
76
+
77
+ dec_places_mass_flow = OpenStudio::Measure::OSArgument.makeIntegerArgument('dec_places_mass_flow', true)
78
78
  dec_places_mass_flow.setDisplayName('Number of Decimal Places to Round Mass Flow Rate')
79
79
  dec_places_mass_flow.setDescription('Number of decimal places to which mass flow rate will be rounded')
80
80
  dec_places_mass_flow.setDefaultValue(3)
81
81
  args << dec_places_mass_flow
82
-
82
+
83
83
  dec_places_temp = OpenStudio::Measure::OSArgument.makeIntegerArgument('dec_places_temp', true)
84
84
  dec_places_temp.setDisplayName('Number of Decimal Places to Round Temperature')
85
85
  dec_places_temp.setDescription('Number of decimal places to which temperature will be rounded')
@@ -94,7 +94,6 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
94
94
  super(runner, user_arguments)
95
95
 
96
96
  result = OpenStudio::IdfObjectVector.new
97
-
98
97
 
99
98
  # To use the built-in error checking we need the model...
100
99
  # get the last model and sql file
@@ -107,51 +106,48 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
107
106
 
108
107
  # use the built-in error checking
109
108
  return false unless runner.validateUserArguments(arguments(model), user_arguments)
110
-
111
- ##Read in argumetns related to variables for output requests
112
- hhw_loop_name = runner.getStringArgumentValue('hhw_loop_name', user_arguments)
113
- chw_loop_name = runner.getStringArgumentValue('chw_loop_name', user_arguments)
114
-
115
109
 
116
- #Identify key names for output variables.
117
- plantloops = model.getPlantLoops
110
+ ##Read in argumetns related to variables for output requests
111
+ hhw_loop_name = runner.getStringArgumentValue('hhw_loop_name', user_arguments)
112
+ chw_loop_name = runner.getStringArgumentValue('chw_loop_name', user_arguments)
113
+
114
+ #Identify key names for output variables.
115
+ plantloops = model.getPlantLoops
118
116
 
119
117
  selected_plant_loops = []
120
118
  i = 0
121
-
122
- variable_name1 = 'System Node Mass Flow Rate'
123
- variable_name2 = 'System Node Temperature'
124
- reporting_frequency = 'timestep'
125
119
 
126
-
120
+ variable_name1 = 'System Node Mass Flow Rate'
121
+ variable_name2 = 'System Node Temperature'
122
+ reporting_frequency = 'timestep'
123
+
127
124
  plantloops.each do |plantLoop|
128
- log "plant loop name #{plantLoop.name.get.to_s}"
129
- if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_s
130
- #Extract plant loop information
131
- selected_plant_loops[0]=plantLoop
132
- key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
133
- key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
134
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name2},timestep;").get
135
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_inlet},#{variable_name2},timestep;").get
136
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name1},timestep;").get
137
- end
138
- if plantLoop.name.get.to_s.downcase.include? hhw_loop_name.to_s and !plantLoop.name.get.to_s.downcase.include? "service" and !plantLoop.name.get.to_s.downcase.include? "domestic"
139
- #Extract plant loop information
140
- selected_plant_loops[1]=plantLoop
141
- key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
142
- key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
143
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_outlet},#{variable_name2},timestep;").get
144
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_inlet},#{variable_name2},timestep;").get
145
- result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_outlet},#{variable_name1},timestep;").get
146
- end
147
- end
148
-
125
+ log "plant loop name #{plantLoop.name.get.to_s}"
126
+ if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_s
127
+ #Extract plant loop information
128
+ selected_plant_loops[0]=plantLoop
129
+ key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
130
+ key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
131
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name2},timestep;").get
132
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_inlet},#{variable_name2},timestep;").get
133
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name1},timestep;").get
134
+ end
135
+ if plantLoop.name.get.to_s.downcase.include? hhw_loop_name.to_s and !plantLoop.name.get.to_s.downcase.include? "service" and !plantLoop.name.get.to_s.downcase.include? "domestic"
136
+ #Extract plant loop information
137
+ selected_plant_loops[1]=plantLoop
138
+ key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
139
+ key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
140
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_outlet},#{variable_name2},timestep;").get
141
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_inlet},#{variable_name2},timestep;").get
142
+ result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_outlet},#{variable_name1},timestep;").get
143
+ end
144
+ end
149
145
 
150
146
  result << OpenStudio::IdfObject.load('Output:Variable,,Site Mains Water Temperature,hourly;').get
151
147
  result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,hourly;').get
152
148
  result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,hourly;').get
153
149
  result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,hourly;').get
154
- result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,timestep;').get ##Using this for data at timestep interval
150
+ result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get ##Using this for data at timestep interval
155
151
  result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,hourly;').get
156
152
  result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,hourly;').get
157
153
  result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,hourly;').get
@@ -169,17 +165,16 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
169
165
  result
170
166
  end
171
167
 
172
- def extract_timeseries_into_matrix(sqlfile, data, variable_name, str, key_value = nil, default_if_empty = 0,dec_places, timestep)
168
+ def extract_timeseries_into_matrix(sqlfile, data, variable_name, str, key_value = nil, default_if_empty = 0,dec_places, timestep)
173
169
  log "Executing query for #{variable_name}"
174
170
  #column_name = variable_name
175
171
  if key_value
176
- #ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name, key_value)
177
- ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
172
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
178
173
  #column_name += "_#{key_value}"
179
- column_name=str
174
+ column_name=str
180
175
  else
181
176
  #ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
182
- ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
177
+ ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
183
178
  end
184
179
  log 'Iterating over timeseries'
185
180
  column = [column_name.delete(':').delete(' ')] # Set the header of the data to the variable name, removing : and spaces
@@ -191,7 +186,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
191
186
  else
192
187
  ts = ts.get if ts.respond_to?(:get)
193
188
  ts = ts.first if ts.respond_to?(:first)
194
-
189
+
195
190
  start = Time.now
196
191
  # Iterating in OpenStudio can take up to 60 seconds with 10min data. The quick_proc takes 0.03 seconds.
197
192
  # for i in 0..ts.values.size - 1
@@ -200,24 +195,21 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
200
195
  # end
201
196
 
202
197
  quick_proc = ts.values.to_s.split(',')
203
- quick_proc[0]=quick_proc[0].split('(', 2).last #cleanup necessary to remove opening paren
204
- quick_proc=quick_proc.map(&:to_f)
205
- x = 0
198
+ quick_proc[0]=quick_proc[0].split('(', 2).last #cleanup necessary to remove opening paren
199
+ quick_proc=quick_proc.map(&:to_f)
200
+ x = 0
206
201
  len = quick_proc.length
207
- log "quick proc #{quick_proc}"
208
- while(x < len) #Round to the # of decimal places specified
202
+ log "quick proc #{quick_proc}"
203
+ while(x < len) #Round to the # of decimal places specified
209
204
  quick_proc[x]=(quick_proc[x]).round(dec_places)
210
205
  x=x+1
211
- end
212
- quick_proc=quick_proc.map(&:to_s)
206
+ end
207
+ quick_proc=quick_proc.map(&:to_s)
213
208
 
214
-
215
209
  # the first and last have some cleanup items because of the Vector method
216
- quick_proc[0] = quick_proc[0].gsub(/^.*\(/, '')
217
- quick_proc[-1] = quick_proc[-1].delete(')')
210
+ quick_proc[0] = quick_proc[0].gsub(/^.*\(/, '')
211
+ quick_proc[-1] = quick_proc[-1].delete(')')
218
212
  column += quick_proc
219
-
220
-
221
213
 
222
214
  log "Took #{Time.now - start} to iterate"
223
215
  end
@@ -279,9 +271,11 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
279
271
 
280
272
  # use the built-in error checking
281
273
  return false unless runner.validateUserArguments(arguments(model), user_arguments)
282
-
283
- args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
284
- if !args then return false end
274
+
275
+ args = OsLib_HelperMethods.createRunVariables(runner, model, user_arguments, arguments(model))
276
+ if !args
277
+ return false
278
+ end
285
279
 
286
280
  # lookup and replace argument values from upstream measures
287
281
  if args['use_upstream_args'] == true
@@ -291,7 +285,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
291
285
  if !value_from_osw.empty?
292
286
  runner.registerInfo("Replacing argument named #{arg} from current measure with a value of #{value_from_osw[:value]} from #{value_from_osw[:measure_name]}.")
293
287
  new_val = value_from_osw[:value]
294
- # todo - make code to handle non strings more robust. check_upstream_measure_for_arg could pass bakc the argument type
288
+ # TODO: make code to handle non strings more robust. check_upstream_measure_for_arg could pass back the argument type
295
289
  if arg == 'hhw_loop_name'
296
290
  args[arg] = new_val.to_s
297
291
  elsif arg == 'chw_loop_name'
@@ -303,9 +297,9 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
303
297
  end
304
298
  end
305
299
  hhw_loop_name = args['hhw_loop_name']
306
- chw_loop_name = args['chw_loop_name']
307
- dec_places_temp = args['dec_places_temp']
308
- dec_places_mass_flow = args['dec_places_mass_flow']
300
+ chw_loop_name = args['chw_loop_name']
301
+ dec_places_temp = args['dec_places_temp']
302
+ dec_places_mass_flow = args['dec_places_mass_flow']
309
303
  # get the last model and sql file
310
304
  model = runner.lastOpenStudioModel
311
305
  if model.empty?
@@ -313,10 +307,9 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
313
307
  return false
314
308
  end
315
309
  model = model.get
316
-
317
310
 
318
- timesteps_per_hour=model.getTimestep.numberOfTimestepsPerHour.to_i
319
- timestep=60/timesteps_per_hour #timestep in minutes
311
+ timesteps_per_hour=model.getTimestep.numberOfTimestepsPerHour.to_i
312
+ timestep=60/timesteps_per_hour #timestep in minutes
320
313
 
321
314
  sqlFile = runner.lastEnergyPlusSqlFile
322
315
  if sqlFile.empty?
@@ -339,9 +332,12 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
339
332
  ]
340
333
 
341
334
  # just grab one of the variables to get the date/time stamps
342
- ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', 'Cooling:Electricity')
343
- #ts = sqlFile.timeSeries('RUN PERIOD 1', 'Hourly', 'Cooling:Electricity')
344
- unless ts.empty?
335
+ attribute_name = 'Electricity:Facility'
336
+ ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', attribute_name)
337
+ if ts.empty?
338
+ runner.registerError("This feature does not have the attribute '#{attribute_name}' to enable this measure to work." \
339
+ "To resolve, simulate a building with electricity or remove this measure from your workflow.")
340
+ else
345
341
  ts = ts.first
346
342
  dt_base = nil
347
343
  # Save off the date time values
@@ -355,7 +351,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
355
351
  dt.date.dayOfWeek.value,
356
352
  dt.time.hours,
357
353
  dt.time.minutes,
358
- dt_current.to_time.to_i - dt_base.to_time.to_i + timestep*60
354
+ dt_current.to_time.to_i - dt_base.to_time.to_i + timestep*60
359
355
  ]
360
356
  end
361
357
  end
@@ -364,69 +360,69 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
364
360
 
365
361
  selected_plant_loops = []
366
362
  i = 0
367
-
368
- key_var={}
363
+
364
+ key_var={}
369
365
 
370
366
  plantloops.each do |plantLoop|
371
- if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_str
372
- #Extract plant loop information
373
- selected_plant_loops[0]=plantLoop
374
- end
375
- if plantLoop.name.get.to_s.downcase.include? hhw_loop_name.to_str
376
- #Get plant loop information
377
- selected_plant_loops[1]=plantLoop
378
- end
367
+ if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_str
368
+ #Extract plant loop information
369
+ selected_plant_loops[0]=plantLoop
370
+ end
371
+ if plantLoop.name.get.to_s.downcase.include? hhw_loop_name.to_str
372
+ #Get plant loop information
373
+ selected_plant_loops[1]=plantLoop
374
+ end
375
+ end
376
+
377
+ if !selected_plant_loops[1].nil?
378
+ #Set up variables for output
379
+ key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
380
+ key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
381
+ key_var['hhw_outlet_massflow']='massFlowRateHeating'
382
+ key_var['hhw_outlet_temp']='heatingReturnTemperature[C]'
383
+ key_var['hhw_inlet_temp']='heatingSupplyTemperature[C]'
384
+ #Extract time series
385
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_outlet_temp'], key_value_hhw_outlet, 0, dec_places_temp, timestep)
386
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_inlet_temp'], key_value_hhw_inlet, 0, dec_places_temp, timestep)
387
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['hhw_outlet_massflow'], key_value_hhw_outlet, 0, dec_places_mass_flow, timestep)
388
+ else
389
+ runner.registerWarning("No hot water loop found. If one is expected, make sure the hot water loop name argument provides a string present in its name.")
379
390
  end
380
-
381
- if !selected_plant_loops[1].nil?
382
- #Set up variables for output
383
- key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
384
- key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
385
- key_var['hhw_outlet_massflow']='massFlowRateHeating'
386
- key_var['hhw_outlet_temp']='heatingReturnTemperature[C]'
387
- key_var['hhw_inlet_temp']='heatingSupplyTemperature[C]'
388
- #Extract time series
389
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_outlet_temp'], key_value_hhw_outlet, 0, dec_places_temp, timestep)
390
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_inlet_temp'], key_value_hhw_inlet, 0, dec_places_temp, timestep)
391
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['hhw_outlet_massflow'], key_value_hhw_outlet, 0, dec_places_mass_flow, timestep)
392
- else
393
- runner.registerWarning("No hot water loop found. If one is expected, make sure the hot water loop name argument provides a string present in its name.")
394
- end
395
-
396
- if !selected_plant_loops[0].nil?
397
- #Set up variables for outputs
398
- key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
399
- key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
400
- key_var['chw_outlet_massflow']='massFlowRateCooling'
401
- key_var['chw_outlet_temp']='ChilledWaterReturnTemperature[C]'
402
- key_var['chw_inlet_temp']='ChilledWaterSupplyTemperature[C]'
403
- #Extract time series
404
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_outlet_temp'], key_value_chw_outlet, 0, dec_places_temp,timestep)
405
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_inlet_temp'], key_value_chw_inlet, 0, dec_places_temp,timestep)
406
- extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['chw_outlet_massflow'], key_value_chw_outlet, 0, dec_places_mass_flow,timestep)
407
- else
408
- runner.registerWarning("No chilled water loop found. If one is expected, make sure the chilled water loop name argument provides a string present in its name.")
409
- end
410
-
411
-
412
- if selected_plant_loops[0].nil? and selected_plant_loops[1].nil?
413
- runner.registerWarning("No HVAC plant loops found. If one or more plant loops are expected, make sure they follow the naming conventions mentioned in the previous warnings.")
414
- end
415
-
416
- if !selected_plant_loops.nil?
417
- # convert this to CSV object
418
- File.open('./building_loads.csv', 'w') do |f|
419
- rows.each do |row|
420
- f << row.join(',') << "\n"
391
+
392
+ if !selected_plant_loops[0].nil?
393
+ #Set up variables for outputs
394
+ key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
395
+ key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
396
+ key_var['chw_outlet_massflow']='massFlowRateCooling'
397
+ key_var['chw_outlet_temp']='ChilledWaterReturnTemperature[C]'
398
+ key_var['chw_inlet_temp']='ChilledWaterSupplyTemperature[C]'
399
+ #Extract time series
400
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_outlet_temp'], key_value_chw_outlet, 0, dec_places_temp,timestep)
401
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_inlet_temp'], key_value_chw_inlet, 0, dec_places_temp,timestep)
402
+ extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['chw_outlet_massflow'], key_value_chw_outlet, 0, dec_places_mass_flow,timestep)
403
+ else
404
+ runner.registerWarning("No chilled water loop found. If one is expected, make sure the chilled water loop name argument provides a string present in its name.")
405
+ end
406
+
407
+
408
+ if selected_plant_loops[0].nil? and selected_plant_loops[1].nil?
409
+ runner.registerWarning("No HVAC plant loops found. If one or more plant loops are expected, make sure they follow the naming conventions mentioned in the previous warnings.")
410
+ end
411
+
412
+ if !selected_plant_loops.nil?
413
+ # convert this to CSV object
414
+ File.open('./building_loads.csv', 'w') do |f|
415
+ rows.each do |row|
416
+ f << row.join(',') << "\n"
417
+ end
421
418
  end
422
- end
423
- end
419
+ end
424
420
 
425
421
  true
426
422
  ensure
427
423
  sqlFile&.close
428
424
  end
429
- end
425
+ end
430
426
 
431
427
 
432
428
  # register the measure to be used by the application
@@ -396,4 +396,4 @@ module OsLib_HelperMethods
396
396
 
397
397
  # OpenStudio has built in helper for unit conversion. That can be done using OpenStudio::convert() as shown below.
398
398
  # OpenStudio::convert(double,"from unit string","to unit string").get
399
- end
399
+ end
@@ -40,6 +40,7 @@ require_relative 'thermal_storage'
40
40
 
41
41
  require 'json-schema'
42
42
  require 'json'
43
+ require 'fileutils'
43
44
 
44
45
  module URBANopt
45
46
  module Reporting
@@ -244,6 +245,7 @@ module URBANopt
244
245
  Dir.mkdir(results_dir_path) unless Dir.exist?(File.join(@directory_name, 'feature_reports'))
245
246
 
246
247
  @timeseries_csv.path = File.join(@directory_name, 'feature_reports', file_name + '.csv')
248
+ FileUtils.mkdir_p File.dirname(@timeseries_csv.path)
247
249
  @timeseries_csv.save_data
248
250
 
249
251
  ## save json rport
@@ -270,7 +272,7 @@ module URBANopt
270
272
 
271
273
  return true
272
274
  end
273
-
275
+
274
276
  ##
275
277
  # Calls the individual functions to save 'default_feature_report.json' and 'default_feature_report.csv'
276
278
  # For backward compatibility and ease of use
@@ -30,6 +30,6 @@
30
30
 
31
31
  module URBANopt
32
32
  module Reporting
33
- VERSION = '0.3.3'.freeze
33
+ VERSION = '0.3.4'.freeze
34
34
  end
35
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-reporting
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rawad El Kontar
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-01-13 00:00:00.000000000 Z
12
+ date: 2021-01-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler