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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/measures/default_feature_reports/measure.rb +3 -4
- data/lib/measures/export_modelica_loads/measure.rb +53 -47
- data/lib/measures/export_time_series_modelica/measure.rb +124 -128
- data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +3 -1
- data/lib/urbanopt/reporting/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75187e938a1cbfabd1d74eba912af03fcd2aade54955a490d68ea1b97b229dd2
|
4
|
+
data.tar.gz: 25b56a46e4569a71a7c01964bf64f2a14d8c30fdc9f6f5167fd61b40f272eb52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a5f20c29cc1eec6aafeece4479a52c4c5a6a0ecfb0374a0b8f243551f9a7d49ecfbcf25b233ce7e19441551adcd87c5eb668ad509d4c87b0681ea1a187da6b2
|
7
|
+
data.tar.gz: bccc2ad11e97d3330f2706cb9a7d32c5c0209130af88738854e6d56fb6d34b5ccfcc8b51b42633d3f359bf4c03c34d4888108528bd38c558c96ec06569c92e9d
|
data/CHANGELOG.md
CHANGED
@@ -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,
|
86
|
-
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,
|
87
|
-
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,
|
88
|
-
result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,
|
89
|
-
result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,
|
90
|
-
result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,
|
91
|
-
result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,
|
92
|
-
result << OpenStudio::IdfObject.load('Output:Meter,Fans:Electricity,
|
93
|
-
result << OpenStudio::IdfObject.load('Output:Meter,InteriorEquipment:Electricity,
|
94
|
-
result << OpenStudio::IdfObject.load('Output:Meter,ExteriorLighting:Electricity,
|
95
|
-
result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,
|
96
|
-
result << OpenStudio::IdfObject.load('Output:Meter,
|
97
|
-
result << OpenStudio::IdfObject.load('Output:Meter,
|
98
|
-
result << OpenStudio::IdfObject.load('Output:Meter,
|
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,
|
101
|
-
result << OpenStudio::IdfObject.load('Output:Variable,*,Water Heater Total Demand Heat Transfer Rate,
|
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
|
-
|
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
|
-
|
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
|
-
|
160
|
-
|
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
|
-
|
237
|
-
ts = sqlFile.timeSeries('RUN PERIOD 1', '
|
238
|
-
|
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
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
117
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
204
|
-
|
205
|
-
|
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
|
-
|
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
|
-
|
212
|
-
|
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
|
-
|
284
|
-
|
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
|
-
#
|
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
|
-
|
307
|
-
|
308
|
-
|
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
|
-
|
319
|
-
|
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
|
-
|
343
|
-
|
344
|
-
|
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
|
-
|
363
|
+
|
364
|
+
key_var={}
|
369
365
|
|
370
366
|
plantloops.each do |plantLoop|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
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
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
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
|
-
|
423
|
-
end
|
419
|
+
end
|
424
420
|
|
425
421
|
true
|
426
422
|
ensure
|
427
423
|
sqlFile&.close
|
428
424
|
end
|
429
|
-
|
425
|
+
end
|
430
426
|
|
431
427
|
|
432
428
|
# register the measure to be used by the application
|
@@ -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
|
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.
|
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-
|
12
|
+
date: 2021-01-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|