urbanopt-reporting 0.3.3 → 0.3.4

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: 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