openstudio-workflow 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +39 -2
- data/Rakefile +12 -1
- data/lib/openstudio-workflow.rb +31 -4
- data/lib/openstudio/workflow/adapter.rb +8 -9
- data/lib/openstudio/workflow/adapters/local.rb +35 -22
- data/lib/openstudio/workflow/adapters/mongo.rb +82 -92
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +229 -0
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +7 -10
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +37 -159
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +53 -492
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +1 -5
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/README.md +0 -0
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.rb +81 -87
- data/lib/openstudio/workflow/jobs/{run_postprocess → run_reporting_measures}/packaged_measures/StandardReports/measure.xml +1 -1
- data/lib/openstudio/workflow/jobs/{run_postprocess/packaged_measures/StandardReports/resources/report.html.in → run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb} +0 -0
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +548 -0
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +226 -0
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +39 -41
- data/lib/openstudio/workflow/multi_delegator.rb +6 -6
- data/lib/openstudio/workflow/run.rb +95 -39
- data/lib/openstudio/workflow/version.rb +1 -1
- metadata +9 -6
@@ -17,10 +17,8 @@
|
|
17
17
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
######################################################################
|
19
19
|
|
20
|
-
|
21
20
|
# Run Prelight job to prepare the directory for simulations.
|
22
21
|
class RunPreflight
|
23
|
-
|
24
22
|
def initialize(directory, logger, adapter, options = {})
|
25
23
|
defaults = {}
|
26
24
|
@options = defaults.merge(options)
|
@@ -28,13 +26,11 @@ class RunPreflight
|
|
28
26
|
@adapter = adapter
|
29
27
|
@results = {}
|
30
28
|
@logger = logger
|
31
|
-
|
32
29
|
end
|
33
30
|
|
34
31
|
def perform
|
35
32
|
@logger.info "Calling #{__method__} in the #{self.class} class"
|
36
33
|
|
37
|
-
|
38
34
|
@adapter.communicate_started @directory, @options
|
39
35
|
|
40
36
|
# Add the moment this does nothing.
|
@@ -42,4 +38,4 @@ class RunPreflight
|
|
42
38
|
# return the results back to the caller--always
|
43
39
|
@results
|
44
40
|
end
|
45
|
-
end
|
41
|
+
end
|
File without changes
|
@@ -1,91 +1,90 @@
|
|
1
1
|
require 'erb'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
|
-
#start the measure
|
4
|
+
# start the measure
|
4
5
|
class StandardReports < OpenStudio::Ruleset::ReportingUserScript
|
5
|
-
|
6
|
-
#
|
7
|
-
#the display name in PAT comes from the name field in measure.xml
|
6
|
+
# define the name that a user will see, this method may be deprecated as
|
7
|
+
# the display name in PAT comes from the name field in measure.xml
|
8
8
|
def name
|
9
|
-
|
9
|
+
'Standard Reports'
|
10
10
|
end
|
11
11
|
|
12
|
-
#define the arguments that the user will input
|
13
|
-
def arguments
|
12
|
+
# define the arguments that the user will input
|
13
|
+
def arguments
|
14
14
|
args = OpenStudio::Ruleset::OSArgumentVector.new
|
15
15
|
|
16
|
-
|
17
|
-
end #end the arguments method
|
16
|
+
args
|
17
|
+
end # end the arguments method
|
18
18
|
|
19
|
-
#sql_query method
|
19
|
+
# sql_query method
|
20
20
|
def sql_query(sql, report_name, query)
|
21
21
|
val = 10e9
|
22
22
|
result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
|
23
|
-
|
23
|
+
unless result.empty?
|
24
24
|
val = result.get
|
25
25
|
end
|
26
|
-
|
26
|
+
val
|
27
27
|
end
|
28
28
|
|
29
|
-
#define what happens when the measure is run
|
29
|
+
# define what happens when the measure is run
|
30
30
|
def run(runner, user_arguments)
|
31
31
|
super(runner, user_arguments)
|
32
32
|
|
33
|
-
#use the built-in error checking
|
34
|
-
|
33
|
+
# use the built-in error checking
|
34
|
+
unless runner.validateUserArguments(arguments, user_arguments)
|
35
35
|
return false
|
36
36
|
end
|
37
|
-
|
38
|
-
os_version = OpenStudio::VersionString.new(OpenStudio::openStudioVersion())
|
39
|
-
min_version_feature1 = OpenStudio::VersionString.new("1.2.3")
|
40
37
|
|
41
|
-
|
38
|
+
os_version = OpenStudio::VersionString.new(OpenStudio.openStudioVersion)
|
39
|
+
min_version_feature1 = OpenStudio::VersionString.new('1.2.3')
|
42
40
|
|
41
|
+
# get the last model and sql file
|
43
42
|
model = runner.lastOpenStudioModel
|
44
43
|
if model.empty?
|
45
|
-
runner.registerError(
|
44
|
+
runner.registerError('Cannot find last model.')
|
46
45
|
return false
|
47
46
|
end
|
48
47
|
model = model.get
|
49
48
|
|
50
49
|
sqlFile = runner.lastEnergyPlusSqlFile
|
51
50
|
if sqlFile.empty?
|
52
|
-
runner.registerError(
|
51
|
+
runner.registerError('Cannot find last sql file.')
|
53
52
|
return false
|
54
53
|
end
|
55
54
|
sqlFile = sqlFile.get
|
56
55
|
model.setSqlFile(sqlFile)
|
57
56
|
|
58
57
|
# put data into variables, these are available in the local scope binding
|
59
|
-
#building_name = model.getBuilding.name.get
|
58
|
+
# building_name = model.getBuilding.name.get
|
60
59
|
|
61
|
-
web_asset_path = OpenStudio
|
60
|
+
web_asset_path = OpenStudio.getSharedResourcesPath / OpenStudio::Path.new('web_assets')
|
62
61
|
|
63
62
|
energy = "var consumption = {\n"
|
64
|
-
fuel_type =
|
65
|
-
units =
|
63
|
+
fuel_type = ''
|
64
|
+
units = ''
|
66
65
|
|
67
66
|
site_energy_use = 0.0
|
68
|
-
OpenStudio::EndUseFuelType
|
67
|
+
OpenStudio::EndUseFuelType.getValues.each do |fuel_type|
|
69
68
|
energy << "\t\""
|
70
69
|
fuel_type = OpenStudio::EndUseFuelType.new(fuel_type).valueDescription
|
71
70
|
energy << OpenStudio::EndUseFuelType.new(fuel_type).valueDescription # append this to remove whitespace between words ".delete(' ')"
|
72
71
|
energy << " Consumption\":{\n\t\t\"units\":"
|
73
|
-
if fuel_type ==
|
72
|
+
if fuel_type == 'Electricity'
|
74
73
|
units = "\"kWh\""
|
75
|
-
unit_str =
|
74
|
+
unit_str = 'kWh'
|
76
75
|
else
|
77
76
|
units = "\"Million Btu\""
|
78
|
-
unit_str =
|
77
|
+
unit_str = 'MBtu'
|
79
78
|
end
|
80
79
|
fuel_type_aggregation = 0.0
|
81
80
|
energy << units
|
82
81
|
energy << ",\n\t\t\"data\":{\n\t\t\t\""
|
83
|
-
OpenStudio::EndUseCategoryType
|
82
|
+
OpenStudio::EndUseCategoryType.getValues.each do |category_type|
|
84
83
|
fuel_and_category_aggregation = 0.0
|
85
84
|
category_str = OpenStudio::EndUseCategoryType.new(category_type).valueDescription
|
86
85
|
energy << category_str # append this to remove whitespace between words ".delete(' ')"
|
87
86
|
energy << "\":["
|
88
|
-
OpenStudio::MonthOfYear
|
87
|
+
OpenStudio::MonthOfYear.getValues.each do |month|
|
89
88
|
if month >= 1 and month <= 12
|
90
89
|
if not sqlFile.energyConsumptionByMonth(OpenStudio::EndUseFuelType.new(fuel_type),
|
91
90
|
OpenStudio::EndUseCategoryType.new(category_type),
|
@@ -94,36 +93,36 @@ class StandardReports < OpenStudio::Ruleset::ReportingUserScript
|
|
94
93
|
OpenStudio::EndUseCategoryType.new(category_type),
|
95
94
|
OpenStudio::MonthOfYear.new(month)).get
|
96
95
|
fuel_and_category_aggregation += valInJ
|
97
|
-
valInUnits = OpenStudio
|
98
|
-
temp = sprintf
|
96
|
+
valInUnits = OpenStudio.convert(valInJ, 'J', unit_str).get
|
97
|
+
temp = sprintf '%.3f', valInUnits
|
99
98
|
energy << temp.to_s
|
100
|
-
energy <<
|
99
|
+
energy << ','
|
101
100
|
if os_version >= min_version_feature1
|
102
101
|
month_str = OpenStudio::MonthOfYear.new(month).valueDescription
|
103
|
-
prefix_str = OpenStudio
|
104
|
-
runner.registerValue("#{prefix_str}_si",valInJ,
|
105
|
-
runner.registerValue("#{prefix_str}_ip",valInUnits,unit_str)
|
102
|
+
prefix_str = OpenStudio.toUnderscoreCase("#{fuel_type}_#{category_str}_#{month_str}")
|
103
|
+
runner.registerValue("#{prefix_str}_si", valInJ, 'J')
|
104
|
+
runner.registerValue("#{prefix_str}_ip", valInUnits, unit_str)
|
106
105
|
end
|
107
106
|
else
|
108
|
-
energy <<
|
107
|
+
energy << '0,'
|
109
108
|
end
|
110
109
|
end
|
111
110
|
end
|
112
111
|
energy = energy[0..-2]
|
113
112
|
energy << "],\n\t\t\t\""
|
114
|
-
if (os_version >= min_version_feature1)
|
115
|
-
prefix_str = OpenStudio
|
116
|
-
runner.registerValue("#{prefix_str}_si",fuel_and_category_aggregation,
|
117
|
-
runner.registerValue("#{prefix_str}_ip",OpenStudio
|
113
|
+
if (os_version >= min_version_feature1)
|
114
|
+
prefix_str = OpenStudio.toUnderscoreCase("#{fuel_type}_#{category_str}")
|
115
|
+
runner.registerValue("#{prefix_str}_si", fuel_and_category_aggregation, 'J')
|
116
|
+
runner.registerValue("#{prefix_str}_ip", OpenStudio.convert(fuel_and_category_aggregation, 'J', unit_str).get, unit_str)
|
118
117
|
end
|
119
118
|
fuel_type_aggregation += fuel_and_category_aggregation
|
120
119
|
end
|
121
120
|
energy = energy[0..-7]
|
122
121
|
energy << "\n\t\t}\n\t},\n"
|
123
122
|
if (os_version >= min_version_feature1)
|
124
|
-
runner.registerValue(OpenStudio
|
125
|
-
runner.registerValue(OpenStudio
|
126
|
-
OpenStudio
|
123
|
+
runner.registerValue(OpenStudio.toUnderscoreCase("#{fuel_type}_si"), fuel_type_aggregation, 'J')
|
124
|
+
runner.registerValue(OpenStudio.toUnderscoreCase("#{fuel_type}_ip"),
|
125
|
+
OpenStudio.convert(fuel_type_aggregation, 'J', unit_str).get,
|
127
126
|
unit_str)
|
128
127
|
end
|
129
128
|
site_energy_use += fuel_type_aggregation
|
@@ -131,64 +130,61 @@ class StandardReports < OpenStudio::Ruleset::ReportingUserScript
|
|
131
130
|
energy = energy[0..-3]
|
132
131
|
energy << "\n};\n"
|
133
132
|
if (os_version >= min_version_feature1)
|
134
|
-
runner.registerValue(
|
135
|
-
runner.registerValue(
|
136
|
-
|
137
|
-
# queries that don't have API methods yet
|
133
|
+
runner.registerValue('site_energy_use_si', OpenStudio.convert(site_energy_use, 'J', 'GJ').get, 'GJ')
|
134
|
+
runner.registerValue('site_energy_use_ip', OpenStudio.convert(site_energy_use, 'J', 'MBtu').get, 'MBtu')
|
135
|
+
|
136
|
+
# queries that don't have API methods yet
|
138
137
|
total_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Total Building Area' AND ColumnName='Area'")
|
139
|
-
runner.registerValue(
|
140
|
-
|
138
|
+
runner.registerValue('total_building_area', total_building_area, 'm2')
|
139
|
+
|
141
140
|
net_conditioned_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
|
142
|
-
runner.registerValue(
|
143
|
-
|
141
|
+
runner.registerValue('net_conditioned_building_area', net_conditioned_building_area, 'm2')
|
142
|
+
|
144
143
|
unconditioned_building_area = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Unconditioned Building Area' AND ColumnName='Area'")
|
145
|
-
runner.registerValue(
|
146
|
-
|
144
|
+
runner.registerValue('unconditioned_building_area', unconditioned_building_area, 'm2')
|
145
|
+
|
147
146
|
total_site_energy_eui = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'")
|
148
|
-
runner.registerValue(
|
147
|
+
runner.registerValue('total_site_energy_eui', total_site_energy_eui, 'MJ/m2')
|
149
148
|
|
150
149
|
total_source_energy_eui = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'")
|
151
|
-
runner.registerValue(
|
152
|
-
|
150
|
+
runner.registerValue('total_source_energy_eui', total_source_energy_eui, 'MJ/m2')
|
151
|
+
|
153
152
|
time_setpoint_not_met_during_occupied_heating = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
|
154
|
-
runner.registerValue(
|
153
|
+
runner.registerValue('time_setpoint_not_met_during_occupied_heating', time_setpoint_not_met_during_occupied_heating, 'hr')
|
155
154
|
|
156
155
|
time_setpoint_not_met_during_occupied_cooling = sql_query(sqlFile, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
|
157
|
-
runner.registerValue(
|
158
|
-
|
156
|
+
runner.registerValue('time_setpoint_not_met_during_occupied_cooling', time_setpoint_not_met_during_occupied_cooling, 'hr')
|
157
|
+
|
159
158
|
time_setpoint_not_met_during_occupied_hours = time_setpoint_not_met_during_occupied_heating + time_setpoint_not_met_during_occupied_cooling
|
160
|
-
runner.registerValue(
|
161
|
-
|
159
|
+
runner.registerValue('time_setpoint_not_met_during_occupied_hours', time_setpoint_not_met_during_occupied_hours, 'hr')
|
160
|
+
|
162
161
|
total_life_cycle_cost = sql_query(sqlFile, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
|
163
|
-
runner.registerValue(
|
164
|
-
|
162
|
+
runner.registerValue('total_life_cycle_cost', total_life_cycle_cost, '$')
|
163
|
+
|
165
164
|
end
|
166
165
|
|
167
166
|
# echo out our values
|
168
|
-
#runner.registerInfo("This building is named #{building_name}.")
|
167
|
+
# runner.registerInfo("This building is named #{building_name}.")
|
169
168
|
|
170
169
|
# read in template
|
171
|
-
html_in_path = "#{File.dirname(__FILE__)}/resources/report.html.
|
170
|
+
html_in_path = "#{File.dirname(__FILE__)}/resources/report.html.erb"
|
172
171
|
if File.exist?(html_in_path)
|
173
|
-
|
172
|
+
html_in_path = html_in_path
|
174
173
|
else
|
175
|
-
html_in_path = "#{File.dirname(__FILE__)}/report.html.
|
176
|
-
end
|
177
|
-
html_in = ""
|
178
|
-
File.open(html_in_path, 'r') do |file|
|
179
|
-
html_in = file.read
|
174
|
+
html_in_path = "#{File.dirname(__FILE__)}/report.html.erb"
|
180
175
|
end
|
181
176
|
|
182
177
|
# configure template with variable values
|
183
|
-
renderer = ERB.new(
|
178
|
+
renderer = ERB.new(File.read(html_in_path))
|
184
179
|
html_out = renderer.result(binding)
|
185
180
|
|
186
181
|
# write html file
|
187
|
-
html_out_path = 'report.html'
|
182
|
+
html_out_path = './report.html'
|
183
|
+
|
188
184
|
File.open(html_out_path, 'w') do |file|
|
189
185
|
file << html_out
|
190
|
-
|
191
|
-
# make sure data is written to the disk one way or the other
|
186
|
+
|
187
|
+
# make sure data is written to the disk one way or the other
|
192
188
|
begin
|
193
189
|
file.fsync
|
194
190
|
rescue
|
@@ -196,17 +192,15 @@ class StandardReports < OpenStudio::Ruleset::ReportingUserScript
|
|
196
192
|
end
|
197
193
|
end
|
198
194
|
|
199
|
-
#closing the sql file
|
195
|
+
# closing the sql file
|
200
196
|
sqlFile.close
|
201
197
|
|
202
|
-
#reporting final condition
|
203
|
-
runner.registerFinalCondition(
|
204
|
-
|
205
|
-
return true
|
206
|
-
|
207
|
-
end #end the run method
|
198
|
+
# reporting final condition
|
199
|
+
runner.registerFinalCondition('Standard Report generated successfully.')
|
208
200
|
|
209
|
-
|
201
|
+
true
|
202
|
+
end # end the run method
|
203
|
+
end # end the measure
|
210
204
|
|
211
|
-
#this allows the measure to be use by the application
|
212
|
-
StandardReports.new.registerWithApplication
|
205
|
+
# this allows the measure to be use by the application
|
206
|
+
StandardReports.new.registerWithApplication
|
File without changes
|
@@ -0,0 +1,548 @@
|
|
1
|
+
######################################################################
|
2
|
+
# Copyright (c) 2008-2014, Alliance for Sustainable Energy.
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
######################################################################
|
19
|
+
|
20
|
+
# Run precanned post processing to extract object functions
|
21
|
+
# TODO: I hear that measures can step on each other if not run in their own directory
|
22
|
+
|
23
|
+
require 'csv'
|
24
|
+
require 'ostruct'
|
25
|
+
|
26
|
+
class RunReportingMeasures
|
27
|
+
# Mixin the MeasureApplication module to apply measures
|
28
|
+
include OpenStudio::Workflow::ApplyMeasures
|
29
|
+
|
30
|
+
def initialize(directory, logger, adapter, options = {})
|
31
|
+
defaults = {}
|
32
|
+
@options = defaults.merge(options)
|
33
|
+
@directory = directory
|
34
|
+
@run_directory = "#{@directory}/run"
|
35
|
+
@adapter = adapter
|
36
|
+
@logger = logger
|
37
|
+
@results = {}
|
38
|
+
@output_attributes = {}
|
39
|
+
|
40
|
+
# TODO: we shouldn't have to keep loading this file if we need it. It should be availabe for any job.
|
41
|
+
# TODO: passing in the options everytime is ridiculuous
|
42
|
+
@analysis_json = @adapter.get_problem(@directory, @options)
|
43
|
+
|
44
|
+
@logger.info "#{self.class} passed the following options #{@options}"
|
45
|
+
|
46
|
+
@model = load_model @options[:run_openstudio][:osm]
|
47
|
+
|
48
|
+
# TODO: should read the name of the sql output file via the :run_openstudio options hash
|
49
|
+
# I want to reiterate that this is cheezy!
|
50
|
+
@sql_filename = "#{@run_directory}/eplusout.sql"
|
51
|
+
fail "EnergyPlus SQL file did not exist #{@sql_filename}" unless File.exist? @sql_filename
|
52
|
+
|
53
|
+
@objective_functions = {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def perform
|
57
|
+
@logger.info "Calling #{__method__} in the #{self.class} class"
|
58
|
+
@logger.info 'RunPostProcess Retrieving datapoint and problem'
|
59
|
+
|
60
|
+
begin
|
61
|
+
@datapoint_json = @adapter.get_datapoint(@directory, @options)
|
62
|
+
@analysis_json = @adapter.get_problem(@directory, @options)
|
63
|
+
|
64
|
+
if @options[:use_monthly_reports]
|
65
|
+
run_monthly_postprocess
|
66
|
+
else
|
67
|
+
run_standard_postprocess
|
68
|
+
end
|
69
|
+
|
70
|
+
translate_csv_to_json
|
71
|
+
|
72
|
+
run_packaged_measures
|
73
|
+
|
74
|
+
if @analysis_json && @analysis_json[:analysis]
|
75
|
+
apply_measures(:reporting_measure)
|
76
|
+
end
|
77
|
+
|
78
|
+
@logger.info 'Saving reporting measures output attributes JSON'
|
79
|
+
File.open("#{@run_directory}/reporting_measure_attributes.json", 'w') do
|
80
|
+
|f| f << JSON.pretty_generate(@output_attributes)
|
81
|
+
end
|
82
|
+
|
83
|
+
run_extract_inputs_and_outputs
|
84
|
+
|
85
|
+
@logger.info "Objective Function JSON is #{@objective_functions}"
|
86
|
+
obj_fun_file = "#{@directory}/objectives.json"
|
87
|
+
FileUtils.rm_f(obj_fun_file) if File.exist?(obj_fun_file)
|
88
|
+
File.open(obj_fun_file, 'w') { |f| f << JSON.pretty_generate(@objective_functions) }
|
89
|
+
|
90
|
+
rescue => e
|
91
|
+
log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
92
|
+
raise log_message
|
93
|
+
end
|
94
|
+
|
95
|
+
@results
|
96
|
+
end
|
97
|
+
|
98
|
+
def run_extract_inputs_and_outputs
|
99
|
+
# For xml, the measure attributes are in the measure_attributes_xml.json file
|
100
|
+
# TODO: somehow pass the metadata around on which JSONs to suck into the database
|
101
|
+
if File.exist? "#{@run_directory}/measure_attributes_xml.json"
|
102
|
+
temp_json = JSON.parse(File.read("#{@run_directory}/measure_attributes_xml.json"), symbolize_names: true)
|
103
|
+
@results.merge! temp_json
|
104
|
+
end
|
105
|
+
|
106
|
+
# Inputs are in the measure_attributes.json file
|
107
|
+
if File.exist? "#{@run_directory}/measure_attributes.json"
|
108
|
+
temp_json = JSON.parse(File.read("#{@run_directory}/measure_attributes.json"), symbolize_names: true)
|
109
|
+
@results.merge! temp_json
|
110
|
+
end
|
111
|
+
|
112
|
+
# Inputs are in the reporting_measure_attributes.jsonfile
|
113
|
+
if File.exist? "#{@run_directory}/reporting_measure_attributes.json"
|
114
|
+
temp_json = JSON.parse(File.read("#{@run_directory}/reporting_measure_attributes.json"), symbolize_names: true)
|
115
|
+
@results.merge! temp_json
|
116
|
+
end
|
117
|
+
|
118
|
+
# Initialize the objective function variable
|
119
|
+
@objective_functions = {}
|
120
|
+
if File.exist? "#{@run_directory}/standard_report_legacy.json"
|
121
|
+
@results[:standard_report_legacy] = JSON.parse(File.read("#{@run_directory}/standard_report_legacy.json"), symbolize_names: true)
|
122
|
+
|
123
|
+
@logger.info 'Iterating over Analysis JSON Output Variables'
|
124
|
+
# Save the objective functions to the object for sending back to the simulation executive
|
125
|
+
|
126
|
+
@analysis_json[:analysis][:output_variables].each do |variable|
|
127
|
+
# determine which ones are the objective functions (code smell: todo: use enumerator)
|
128
|
+
if variable[:objective_function]
|
129
|
+
@logger.info "Looking for objective function #{variable[:name]}"
|
130
|
+
# TODO: move this to cleaner logic. Use ostruct?
|
131
|
+
if variable[:name].include? '.'
|
132
|
+
k, v = variable[:name].split('.')
|
133
|
+
if @results.key?(k.to_sym) && @results[k.to_sym][v.to_sym]
|
134
|
+
@objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = @results[k.to_sym][v.to_sym]
|
135
|
+
if variable[:objective_function_target]
|
136
|
+
@logger.info "Found objective function target for #{variable[:name]}"
|
137
|
+
@objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_target].to_f
|
138
|
+
end
|
139
|
+
if variable[:scaling_factor]
|
140
|
+
@logger.info "Found scaling factor for #{variable[:name]}"
|
141
|
+
@objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = variable[:scaling_factor].to_f
|
142
|
+
end
|
143
|
+
if variable[:objective_function_group]
|
144
|
+
@logger.info "Found objective function group for #{variable[:name]}"
|
145
|
+
@objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_group].to_f
|
146
|
+
end
|
147
|
+
else
|
148
|
+
@logger.warn "No results for objective function #{variable[:name]}"
|
149
|
+
@objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = Float::MAX
|
150
|
+
@objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = nil
|
151
|
+
@objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = nil
|
152
|
+
@objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = nil
|
153
|
+
end
|
154
|
+
else
|
155
|
+
# variable name is not nested with the '.' -- this is for legacy purposes and should be deleted on 9/30/2014
|
156
|
+
if @results[variable[:name]]
|
157
|
+
@objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = @results[k.to_sym][v.to_sym]
|
158
|
+
if variable[:objective_function_target]
|
159
|
+
@logger.info "Found objective function target for #{variable[:name]}"
|
160
|
+
@objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_target].to_f
|
161
|
+
end
|
162
|
+
if variable[:scaling_factor]
|
163
|
+
@logger.info "Found scaling factor for #{variable[:name]}"
|
164
|
+
@objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = variable[:scaling_factor].to_f
|
165
|
+
end
|
166
|
+
if variable[:objective_function_group]
|
167
|
+
@logger.info "Found objective function group for #{variable[:name]}"
|
168
|
+
@objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_group].to_f
|
169
|
+
end
|
170
|
+
else
|
171
|
+
@logger.warn "No results for objective function #{variable[:name]}"
|
172
|
+
@objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = Float::MAX
|
173
|
+
@objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = nil
|
174
|
+
@objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = nil
|
175
|
+
@objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = nil
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
# Load in the OpenStudio model. It is required for postprocessing
|
186
|
+
def load_model(filename)
|
187
|
+
model = nil
|
188
|
+
@logger.info 'Loading model'
|
189
|
+
|
190
|
+
# TODO: wrap this in an exception block and fail as appropriate
|
191
|
+
# assume that the seed model has been placed in the directory
|
192
|
+
if File.exist? filename
|
193
|
+
@logger.info "Reading in model #{filename}"
|
194
|
+
translator = OpenStudio::OSVersion::VersionTranslator.new
|
195
|
+
model = translator.loadModel(filename)
|
196
|
+
fail 'OpenStudio model is empty or could not be loaded' if model.empty?
|
197
|
+
model = model.get
|
198
|
+
else
|
199
|
+
fail "Model '#{filename}' did not exist"
|
200
|
+
end
|
201
|
+
|
202
|
+
model
|
203
|
+
end
|
204
|
+
|
205
|
+
# Run the prepackaged measures in the Gem.
|
206
|
+
def run_packaged_measures
|
207
|
+
# configure the workflow item json to pass
|
208
|
+
workflow_item = {
|
209
|
+
display_name: 'Standard Reports',
|
210
|
+
measure_definition_directory: File.expand_path(File.join(File.dirname(__FILE__), 'packaged_measures', 'StandardReports', 'measure.rb')),
|
211
|
+
measure_definition_class_name: 'StandardReports',
|
212
|
+
measure_type: 'ReportingMeasure',
|
213
|
+
name: 'standard_reports'
|
214
|
+
}
|
215
|
+
@logger.info 'Running packaged reporting measures'
|
216
|
+
|
217
|
+
apply_measure(workflow_item)
|
218
|
+
|
219
|
+
@logger.info 'Finished Running Packaged Measures'
|
220
|
+
end
|
221
|
+
|
222
|
+
def translate_csv_to_json
|
223
|
+
if File.exist?("#{@run_directory}/eplustbl.csv")
|
224
|
+
@logger.info 'Translating EnergyPlus table CSV to JSON file'
|
225
|
+
results = {}
|
226
|
+
csv = CSV.read("#{@run_directory}/eplustbl.csv")
|
227
|
+
csv.transpose.each do |k, v|
|
228
|
+
longname = k.gsub(/\(.*\)/, '').strip
|
229
|
+
short_name = longname.downcase.gsub(' ', '_')
|
230
|
+
units = k.match(/\(.*\)/)[0].gsub('(', '').gsub(')', '')
|
231
|
+
results[short_name.to_sym] = v.nil? ? nil : v.to_f
|
232
|
+
results["#{short_name}_units".to_sym] = units
|
233
|
+
results["#{short_name}_display_name".to_sym] = longname
|
234
|
+
end
|
235
|
+
|
236
|
+
@logger.info 'Saving results to json'
|
237
|
+
|
238
|
+
# save out results
|
239
|
+
File.open("#{@run_directory}/standard_report_legacy.json", 'w') { |f| f << JSON.pretty_generate(results) }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
# TODO: THis is uglier than the one below! sorry.
|
244
|
+
def run_monthly_postprocess
|
245
|
+
def sql_query(sql, report_name, query)
|
246
|
+
val = nil
|
247
|
+
result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
|
248
|
+
if result.empty?
|
249
|
+
@logger.warn "Query for run_monthly_postprocess failed for #{query}"
|
250
|
+
else
|
251
|
+
begin
|
252
|
+
val = result.get
|
253
|
+
rescue => e
|
254
|
+
@logger.info "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
255
|
+
val = nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
val
|
260
|
+
end
|
261
|
+
|
262
|
+
def add_element(hash, var_name, value, xpath = nil)
|
263
|
+
values_hash = {}
|
264
|
+
values_hash['name'] = var_name
|
265
|
+
|
266
|
+
# store correct datatype
|
267
|
+
store_val = nil
|
268
|
+
if value.nil?
|
269
|
+
store_val = nil
|
270
|
+
elsif value == 'true'
|
271
|
+
store_val = true
|
272
|
+
elsif value == 'false'
|
273
|
+
store_val = false
|
274
|
+
else
|
275
|
+
test = value.to_s
|
276
|
+
value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
|
277
|
+
if value.is_a?(Fixnum) || value.is_a?(Float)
|
278
|
+
store_val = value.to_f
|
279
|
+
else
|
280
|
+
store_val = value.to_s
|
281
|
+
end
|
282
|
+
end
|
283
|
+
values_hash['value'] = store_val
|
284
|
+
values_hash['xpath'] = xpath unless xpath.nil?
|
285
|
+
|
286
|
+
hash['data']['variables'] << values_hash
|
287
|
+
end
|
288
|
+
|
289
|
+
# add results from sql method
|
290
|
+
def add_data(sql, query, hdr, area, val)
|
291
|
+
row = []
|
292
|
+
val = sql_query(sql, 'AnnualBuildingUtilityPerformanceSummary', query) if val.nil?
|
293
|
+
row << hdr
|
294
|
+
if area.nil?
|
295
|
+
row << val
|
296
|
+
else
|
297
|
+
row << (val * 1000) / area
|
298
|
+
end
|
299
|
+
row
|
300
|
+
end
|
301
|
+
|
302
|
+
# add results from sql method
|
303
|
+
def add_data2(sql, query, hdr, area, val)
|
304
|
+
row = []
|
305
|
+
val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - ELECTRICITY', query) if val.nil?
|
306
|
+
row << hdr
|
307
|
+
if area.nil?
|
308
|
+
row << val
|
309
|
+
else
|
310
|
+
row << (val * 1000) / area
|
311
|
+
end
|
312
|
+
row
|
313
|
+
end
|
314
|
+
|
315
|
+
# add results from sql method
|
316
|
+
def add_data3(sql, query, hdr, area, val)
|
317
|
+
row = []
|
318
|
+
val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - NATURAL GAS', query) if val.nil?
|
319
|
+
row << hdr
|
320
|
+
if area.nil?
|
321
|
+
row << val
|
322
|
+
else
|
323
|
+
row << (val * 1000) / area
|
324
|
+
end
|
325
|
+
row
|
326
|
+
end
|
327
|
+
|
328
|
+
# add results from sql method
|
329
|
+
def add_data4(sql, query, hdr, area, val)
|
330
|
+
row = []
|
331
|
+
|
332
|
+
if val.nil?
|
333
|
+
val = 0
|
334
|
+
|
335
|
+
['INTERIORLIGHTS:ELECTRICITY', 'EXTERIORLIGHTS:ELECTRICITY', 'INTERIOREQUIPMENT:ELECTRICITY', 'EXTERIOREQUIPMENT:ELECTRICITY',
|
336
|
+
'FANS:ELECTRICITY', 'PUMPS:ELECTRICITY', 'HEATING:ELECTRICITY', 'COOLING:ELECTRICITY', 'HEATREJECTION:ELECTRICITY',
|
337
|
+
'HUMIDIFIER:ELECTRICITY', 'HEATRECOVERY:ELECTRICITY', 'WATERSYSTEMS:ELECTRICITY', 'COGENERATION:ELECTRICITY', 'REFRIGERATION:ELECTRICITY'].each do |end_use|
|
338
|
+
|
339
|
+
tmp_query = query + " AND ColumnName='#{end_use}'"
|
340
|
+
tmp_val = sql_query(sql, 'BUILDING ENERGY PERFORMANCE - ELECTRICITY', tmp_query)
|
341
|
+
val += tmp_val unless tmp_val.nil?
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
row << hdr
|
346
|
+
if area.nil?
|
347
|
+
row << val
|
348
|
+
else
|
349
|
+
row << (val * 1000) / area
|
350
|
+
end
|
351
|
+
row
|
352
|
+
end
|
353
|
+
|
354
|
+
# open sql file
|
355
|
+
sql_file = OpenStudio::SqlFile.new(@sql_filename)
|
356
|
+
|
357
|
+
# get building area
|
358
|
+
bldg_area = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
|
359
|
+
# populate data array
|
360
|
+
|
361
|
+
tbl_data = []
|
362
|
+
tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Energy (MJ/m2)', nil, nil)
|
363
|
+
tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Source Energy (MJ/m2)', nil, nil)
|
364
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'", 'Total Electricity (MJ/m2)', bldg_area, nil)
|
365
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Natural Gas'", 'Total Natural Gas (MJ/m2)', bldg_area, nil)
|
366
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Electricity'", 'Heating Electricity (MJ/m2)', bldg_area, nil)
|
367
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Natural Gas'", 'Heating Natural Gas (MJ/m2)', bldg_area, nil)
|
368
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Cooling' AND ColumnName='Electricity'", 'Cooling Electricity (MJ/m2)', bldg_area, nil)
|
369
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Lighting' AND ColumnName='Electricity'", 'Interior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
370
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Lighting' AND ColumnName='Electricity'", 'Exterior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
371
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Electricity'", 'Interior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
372
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Natural Gas'", 'Interior Equipment Natural Gas (MJ/m2)', bldg_area, nil)
|
373
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Equipment' AND ColumnName='Electricity'", 'Exterior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
374
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Fans' AND ColumnName='Electricity'", 'Fans Electricity (MJ/m2)', bldg_area, nil)
|
375
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Pumps' AND ColumnName='Electricity'", 'Pumps Electricity (MJ/m2)', bldg_area, nil)
|
376
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heat Rejection' AND ColumnName='Electricity'", 'Heat Rejection Electricity (MJ/m2)', bldg_area, nil)
|
377
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Humidification' AND ColumnName='Electricity'", 'Humidification Electricity (MJ/m2)', bldg_area, nil)
|
378
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Electricity'", 'Water Systems Electricity (MJ/m2)', bldg_area, nil)
|
379
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Natural Gas'", 'Water Systems Natural Gas (MJ/m2)', bldg_area, nil)
|
380
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Refrigeration' AND ColumnName='Electricity'", 'Refrigeration Electricity (MJ/m2)', bldg_area, nil)
|
381
|
+
htg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
|
382
|
+
clg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
|
383
|
+
tot_hrs = clg_hrs && htg_hrs ? htg_hrs + clg_hrs : nil
|
384
|
+
tbl_data << add_data(sql_file, nil, 'Heating Hours Unmet (hr)', nil, htg_hrs)
|
385
|
+
tbl_data << add_data(sql_file, nil, 'Cooling Hours Unmet (hr)', nil, clg_hrs)
|
386
|
+
tbl_data << add_data(sql_file, nil, 'Total Hours Unmet (hr)', nil, tot_hrs)
|
387
|
+
total_cost = sql_query(sql_file, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
|
388
|
+
tbl_data << add_data(sql_file, nil, 'Total Life Cycle Cost ($)', nil, total_cost)
|
389
|
+
# cooling:electricity
|
390
|
+
tbl_data << add_data2(sql_file, "RowName='January' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jan (J)', nil, nil)
|
391
|
+
tbl_data << add_data2(sql_file, "RowName='February' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Feb (J)', nil, nil)
|
392
|
+
tbl_data << add_data2(sql_file, "RowName='March' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Mar (J)', nil, nil)
|
393
|
+
tbl_data << add_data2(sql_file, "RowName='April' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Apr (J)', nil, nil)
|
394
|
+
tbl_data << add_data2(sql_file, "RowName='May' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity May (J)', nil, nil)
|
395
|
+
tbl_data << add_data2(sql_file, "RowName='June' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jun (J)', nil, nil)
|
396
|
+
tbl_data << add_data2(sql_file, "RowName='July' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Jul (J)', nil, nil)
|
397
|
+
tbl_data << add_data2(sql_file, "RowName='August' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Aug (J)', nil, nil)
|
398
|
+
tbl_data << add_data2(sql_file, "RowName='September' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Sep (J)', nil, nil)
|
399
|
+
tbl_data << add_data2(sql_file, "RowName='October' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Oct (J)', nil, nil)
|
400
|
+
tbl_data << add_data2(sql_file, "RowName='November' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Nov (J)', nil, nil)
|
401
|
+
tbl_data << add_data2(sql_file, "RowName='December' AND ColumnName='COOLING:ELECTRICITY'", 'Cooling Electricity Dec (J)', nil, nil)
|
402
|
+
# heating:gas
|
403
|
+
tbl_data << add_data3(sql_file, "RowName='January' AND ColumnName='HEATING:GAS'", 'Heating Gas Jan (J)', nil, nil)
|
404
|
+
tbl_data << add_data3(sql_file, "RowName='February' AND ColumnName='HEATING:GAS'", 'Heating Gas Feb (J)', nil, nil)
|
405
|
+
tbl_data << add_data3(sql_file, "RowName='March' AND ColumnName='HEATING:GAS'", 'Heating Gas Mar (J)', nil, nil)
|
406
|
+
tbl_data << add_data3(sql_file, "RowName='April' AND ColumnName='HEATING:GAS'", 'Heating Gas Apr (J)', nil, nil)
|
407
|
+
tbl_data << add_data3(sql_file, "RowName='May' AND ColumnName='HEATING:GAS'", 'Heating Gas May (J)', nil, nil)
|
408
|
+
tbl_data << add_data3(sql_file, "RowName='June' AND ColumnName='HEATING:GAS'", 'Heating Gas Jun (J)', nil, nil)
|
409
|
+
tbl_data << add_data3(sql_file, "RowName='July' AND ColumnName='HEATING:GAS'", 'Heating Gas Jul (J)', nil, nil)
|
410
|
+
tbl_data << add_data3(sql_file, "RowName='August' AND ColumnName='HEATING:GAS'", 'Heating Gas Aug (J)', nil, nil)
|
411
|
+
tbl_data << add_data3(sql_file, "RowName='September' AND ColumnName='HEATING:GAS'", 'Heating Gas Sep (J)', nil, nil)
|
412
|
+
tbl_data << add_data3(sql_file, "RowName='October' AND ColumnName='HEATING:GAS'", 'Heating Gas Oct (J)', nil, nil)
|
413
|
+
tbl_data << add_data3(sql_file, "RowName='November' AND ColumnName='HEATING:GAS'", 'Heating Gas Nov (J)', nil, nil)
|
414
|
+
tbl_data << add_data3(sql_file, "RowName='December' AND ColumnName='HEATING:GAS'", 'Heating Gas Dec (J)', nil, nil)
|
415
|
+
# total Electricity
|
416
|
+
tbl_data << add_data4(sql_file, "RowName='January'", 'Total Electricity Jan (J)', nil, nil)
|
417
|
+
tbl_data << add_data4(sql_file, "RowName='February'", 'Total Electricity Feb (J)', nil, nil)
|
418
|
+
tbl_data << add_data4(sql_file, "RowName='March'", 'Total Electricity Mar (J)', nil, nil)
|
419
|
+
tbl_data << add_data4(sql_file, "RowName='April'", 'Total Electricity Apr (J)', nil, nil)
|
420
|
+
tbl_data << add_data4(sql_file, "RowName='May'", 'Total Electricity May (J)', nil, nil)
|
421
|
+
tbl_data << add_data4(sql_file, "RowName='June'", 'Total Electricity Jun (J)', nil, nil)
|
422
|
+
tbl_data << add_data4(sql_file, "RowName='July'", 'Total Electricity Jul (J)', nil, nil)
|
423
|
+
tbl_data << add_data4(sql_file, "RowName='August'", 'Total Electricity Aug (J)', nil, nil)
|
424
|
+
tbl_data << add_data4(sql_file, "RowName='September'", 'Total Electricity Sep (J)', nil, nil)
|
425
|
+
tbl_data << add_data4(sql_file, "RowName='October'", 'Total Electricity Oct (J)', nil, nil)
|
426
|
+
tbl_data << add_data4(sql_file, "RowName='November'", 'Total Electricity Nov (J)', nil, nil)
|
427
|
+
tbl_data << add_data4(sql_file, "RowName='December'", 'Total Electricity Dec (J)', nil, nil) # close SQL file
|
428
|
+
sql_file.close
|
429
|
+
# transpose data
|
430
|
+
tbl_rows = tbl_data.transpose
|
431
|
+
|
432
|
+
@logger.info tbl_rows
|
433
|
+
# write electricity data to CSV
|
434
|
+
CSV.open("#{@run_directory}/eplustbl.csv", 'wb') do |csv|
|
435
|
+
tbl_rows.each do |row|
|
436
|
+
csv << row
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
# TODO: This is ugly. Move this out of here entirely and into a reporting measure if we need it at all
|
442
|
+
def run_standard_postprocess
|
443
|
+
def sql_query(sql, report_name, query)
|
444
|
+
val = nil
|
445
|
+
result = sql.execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='#{report_name}' AND #{query}")
|
446
|
+
if result.empty?
|
447
|
+
@logger.warn "Query for run_standard_postprocess failed for #{query}"
|
448
|
+
else
|
449
|
+
begin
|
450
|
+
val = result.get
|
451
|
+
rescue => e
|
452
|
+
@logger.info "#{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
|
453
|
+
val = nil
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
val
|
458
|
+
end
|
459
|
+
|
460
|
+
def add_element(hash, var_name, value, xpath = nil)
|
461
|
+
values_hash = {}
|
462
|
+
values_hash['name'] = var_name
|
463
|
+
|
464
|
+
# store correct datatype
|
465
|
+
store_val = nil
|
466
|
+
if value.nil?
|
467
|
+
store_val = nil
|
468
|
+
elsif value == 'true'
|
469
|
+
store_val = true
|
470
|
+
elsif value == 'false'
|
471
|
+
store_val = false
|
472
|
+
else
|
473
|
+
test = value.to_s
|
474
|
+
value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
|
475
|
+
if value.is_a?(Fixnum) || value.is_a?(Float)
|
476
|
+
store_val = value.to_f
|
477
|
+
else
|
478
|
+
store_val = value.to_s
|
479
|
+
end
|
480
|
+
end
|
481
|
+
values_hash['value'] = store_val
|
482
|
+
values_hash['xpath'] = xpath unless xpath.nil?
|
483
|
+
|
484
|
+
hash['data']['variables'] << values_hash
|
485
|
+
end
|
486
|
+
|
487
|
+
# add results from sql method
|
488
|
+
def add_data(sql, query, hdr, area, val)
|
489
|
+
row = []
|
490
|
+
val = sql_query(sql, 'AnnualBuildingUtilityPerformanceSummary', query) if val.nil?
|
491
|
+
row << hdr
|
492
|
+
if area.nil?
|
493
|
+
row << val
|
494
|
+
else
|
495
|
+
row << (val * 1000) / area
|
496
|
+
end
|
497
|
+
row
|
498
|
+
end
|
499
|
+
|
500
|
+
# open sql file
|
501
|
+
sql_file = OpenStudio::SqlFile.new(@sql_filename)
|
502
|
+
|
503
|
+
# get building area
|
504
|
+
bldg_area = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Building Area' AND RowName='Net Conditioned Building Area' AND ColumnName='Area'")
|
505
|
+
# populate data array
|
506
|
+
|
507
|
+
tbl_data = []
|
508
|
+
tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Site Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Energy (MJ/m2)', nil, nil)
|
509
|
+
tbl_data << add_data(sql_file, "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Energy Per Conditioned Building Area'", 'Total Source Energy (MJ/m2)', nil, nil)
|
510
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Electricity'", 'Total Electricity (MJ/m2)', bldg_area, nil)
|
511
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Natural Gas'", 'Total Natural Gas (MJ/m2)', bldg_area, nil)
|
512
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Electricity'", 'Heating Electricity (MJ/m2)', bldg_area, nil)
|
513
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heating' AND ColumnName='Natural Gas'", 'Heating Natural Gas (MJ/m2)', bldg_area, nil)
|
514
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Cooling' AND ColumnName='Electricity'", 'Cooling Electricity (MJ/m2)', bldg_area, nil)
|
515
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Lighting' AND ColumnName='Electricity'", 'Interior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
516
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Lighting' AND ColumnName='Electricity'", 'Exterior Lighting Electricity (MJ/m2)', bldg_area, nil)
|
517
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Electricity'", 'Interior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
518
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Interior Equipment' AND ColumnName='Natural Gas'", 'Interior Equipment Natural Gas (MJ/m2)', bldg_area, nil)
|
519
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Exterior Equipment' AND ColumnName='Electricity'", 'Exterior Equipment Electricity (MJ/m2)', bldg_area, nil)
|
520
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Fans' AND ColumnName='Electricity'", 'Fans Electricity (MJ/m2)', bldg_area, nil)
|
521
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Pumps' AND ColumnName='Electricity'", 'Pumps Electricity (MJ/m2)', bldg_area, nil)
|
522
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Heat Rejection' AND ColumnName='Electricity'", 'Heat Rejection Electricity (MJ/m2)', bldg_area, nil)
|
523
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Humidification' AND ColumnName='Electricity'", 'Humidification Electricity (MJ/m2)', bldg_area, nil)
|
524
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Electricity'", 'Water Systems Electricity (MJ/m2)', bldg_area, nil)
|
525
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Water Systems' AND ColumnName='Natural Gas'", 'Water Systems Natural Gas (MJ/m2)', bldg_area, nil)
|
526
|
+
tbl_data << add_data(sql_file, "TableName='End Uses' AND RowName='Refrigeration' AND ColumnName='Electricity'", 'Refrigeration Electricity (MJ/m2)', bldg_area, nil)
|
527
|
+
htg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Heating' AND ColumnName='Facility'")
|
528
|
+
clg_hrs = sql_query(sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Comfort and Setpoint Not Met Summary' AND RowName='Time Setpoint Not Met During Occupied Cooling' AND ColumnName='Facility'")
|
529
|
+
tot_hrs = clg_hrs && htg_hrs ? htg_hrs + clg_hrs : nil
|
530
|
+
tbl_data << add_data(sql_file, nil, 'Heating Hours Unmet (hr)', nil, htg_hrs)
|
531
|
+
tbl_data << add_data(sql_file, nil, 'Cooling Hours Unmet (hr)', nil, clg_hrs)
|
532
|
+
tbl_data << add_data(sql_file, nil, 'Total Hours Unmet (hr)', nil, tot_hrs)
|
533
|
+
total_cost = sql_query(sql_file, 'Life-Cycle Cost Report', "TableName='Present Value by Category' AND RowName='Grand Total' AND ColumnName='Present Value'")
|
534
|
+
tbl_data << add_data(sql_file, nil, 'Total Life Cycle Cost ($)', nil, total_cost)
|
535
|
+
# close SQL file
|
536
|
+
sql_file.close
|
537
|
+
# transpose data
|
538
|
+
tbl_rows = tbl_data.transpose
|
539
|
+
|
540
|
+
@logger.info tbl_rows
|
541
|
+
# write electricity data to CSV
|
542
|
+
CSV.open("#{@run_directory}/eplustbl.csv", 'wb') do |csv|
|
543
|
+
tbl_rows.each do |row|
|
544
|
+
csv << row
|
545
|
+
end
|
546
|
+
end
|
547
|
+
end
|
548
|
+
end
|