openstudio-workflow 1.3.4 → 1.3.5
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 +89 -77
- data/README.md +67 -93
- data/Rakefile +36 -36
- data/lib/openstudio-workflow.rb +65 -65
- data/lib/openstudio/workflow/adapters/input/local.rb +311 -324
- data/lib/openstudio/workflow/adapters/output/local.rb +158 -161
- data/lib/openstudio/workflow/adapters/output/socket.rb +106 -107
- data/lib/openstudio/workflow/adapters/output/web.rb +82 -82
- data/lib/openstudio/workflow/adapters/output_adapter.rb +163 -163
- data/lib/openstudio/workflow/job.rb +57 -57
- data/lib/openstudio/workflow/jobs/resources/monthly_report.idf +222 -222
- data/lib/openstudio/workflow/jobs/run_energyplus.rb +70 -70
- data/lib/openstudio/workflow/jobs/run_ep_measures.rb +73 -73
- data/lib/openstudio/workflow/jobs/run_initialization.rb +203 -203
- data/lib/openstudio/workflow/jobs/run_os_measures.rb +89 -89
- data/lib/openstudio/workflow/jobs/run_postprocess.rb +73 -73
- data/lib/openstudio/workflow/jobs/run_preprocess.rb +104 -104
- data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +118 -118
- data/lib/openstudio/workflow/jobs/run_translation.rb +84 -84
- data/lib/openstudio/workflow/multi_delegator.rb +62 -62
- data/lib/openstudio/workflow/registry.rb +172 -172
- data/lib/openstudio/workflow/run.rb +342 -328
- data/lib/openstudio/workflow/time_logger.rb +96 -96
- data/lib/openstudio/workflow/util.rb +49 -49
- data/lib/openstudio/workflow/util/energyplus.rb +575 -605
- data/lib/openstudio/workflow/util/io.rb +68 -68
- data/lib/openstudio/workflow/util/measure.rb +658 -650
- data/lib/openstudio/workflow/util/model.rb +151 -151
- data/lib/openstudio/workflow/util/post_process.rb +235 -238
- data/lib/openstudio/workflow/util/weather_file.rb +143 -143
- data/lib/openstudio/workflow/version.rb +40 -40
- data/lib/openstudio/workflow_json.rb +475 -476
- data/lib/openstudio/workflow_runner.rb +263 -268
- metadata +24 -24
@@ -1,151 +1,151 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
3
|
-
# All rights reserved.
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
24
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
25
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
|
27
|
-
# GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
28
|
-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
29
|
-
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30
|
-
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31
|
-
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32
|
-
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
33
|
-
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
-
# *******************************************************************************
|
35
|
-
|
36
|
-
module OpenStudio
|
37
|
-
module Workflow
|
38
|
-
module Util
|
39
|
-
# Manages routine tasks involving OpenStudio::Model or OpenStudio::Workflow objects, such as loading, saving, and
|
40
|
-
# translating them.
|
41
|
-
#
|
42
|
-
module Model
|
43
|
-
# Method to create / load an OSM file
|
44
|
-
#
|
45
|
-
# @param [String] osm_path The full path to an OSM file to load
|
46
|
-
# @param [Object] logger An optional logger to use for finding the OSM model
|
47
|
-
# @return [Object] The return from this method is a loaded OSM or a failure.
|
48
|
-
#
|
49
|
-
def load_osm(osm_path, logger)
|
50
|
-
logger.info 'Loading OSM model'
|
51
|
-
|
52
|
-
# Load the model and return it
|
53
|
-
logger.info "Reading in OSM model #{osm_path}"
|
54
|
-
|
55
|
-
loaded_model = nil
|
56
|
-
begin
|
57
|
-
translator = OpenStudio::OSVersion::VersionTranslator.new
|
58
|
-
loaded_model = translator.loadModel(osm_path)
|
59
|
-
rescue
|
60
|
-
# TODO: get translator working in embedded.
|
61
|
-
# Need to embed idd files
|
62
|
-
logger.warn 'OpenStudio VersionTranslator could not be loaded'
|
63
|
-
loaded_model = OpenStudio::Model::Model.load(osm_path)
|
64
|
-
end
|
65
|
-
raise "Failed to load OSM file #{osm_path}" if loaded_model.empty?
|
66
|
-
loaded_model.get
|
67
|
-
end
|
68
|
-
|
69
|
-
# Method to create / load an IDF file
|
70
|
-
#
|
71
|
-
# @param [String] idf_path Full path to the IDF
|
72
|
-
# @param [Object] logger An optional logger to use for finding the idf model
|
73
|
-
# @return [Object] The return from this method is a loaded IDF or a failure.
|
74
|
-
#
|
75
|
-
def load_idf(idf_path, logger)
|
76
|
-
logger.info 'Loading IDF model'
|
77
|
-
|
78
|
-
# Load the IDF into a workspace object and return it
|
79
|
-
logger.info "Reading in IDF model #{idf_path}"
|
80
|
-
|
81
|
-
idf = OpenStudio::Workspace.load(idf_path)
|
82
|
-
raise "Failed to load IDF file #{idf_path}" if idf.empty?
|
83
|
-
idf.get
|
84
|
-
end
|
85
|
-
|
86
|
-
# Translates a OpenStudio model object into an OpenStudio IDF object
|
87
|
-
#
|
88
|
-
# @param [Object] model the OpenStudio::Model instance to translate into an OpenStudio::Workspace object -- see
|
89
|
-
# the OpenStudio SDK for details on the process
|
90
|
-
# @return [Object] Returns and OpenStudio::Workspace object
|
91
|
-
# @todo (rhorsey) rescue errors here
|
92
|
-
#
|
93
|
-
def translate_to_energyplus(model, logger = nil)
|
94
|
-
logger
|
95
|
-
logger.info 'Translate object to EnergyPlus IDF in preparation for EnergyPlus'
|
96
|
-
a = ::Time.now
|
97
|
-
# ensure objects exist for reporting purposes
|
98
|
-
model.getFacility
|
99
|
-
model.getBuilding
|
100
|
-
forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
|
101
|
-
model_idf = forward_translator.translateModel(model)
|
102
|
-
b = ::Time.now
|
103
|
-
logger.info "Translate object to EnergyPlus IDF took #{b.to_f - a.to_f}"
|
104
|
-
model_idf
|
105
|
-
end
|
106
|
-
|
107
|
-
# Saves an OpenStudio model object to file
|
108
|
-
#
|
109
|
-
# @param [Object] model The OpenStudio::Model instance to save to file
|
110
|
-
# @param [String] save_directory Folder to save the model in
|
111
|
-
# @param [String] name ('in.osm') Option to define a non-standard name
|
112
|
-
# @return [String] OSM file name
|
113
|
-
#
|
114
|
-
def save_osm(model, save_directory, name = 'in.osm')
|
115
|
-
osm_filename = File.join(save_directory.to_s, name.to_s)
|
116
|
-
File.open(osm_filename, 'w') do |f|
|
117
|
-
f << model.to_s
|
118
|
-
# make sure data is written to the disk one way or the other
|
119
|
-
begin
|
120
|
-
f.fsync
|
121
|
-
rescue
|
122
|
-
f.flush
|
123
|
-
end
|
124
|
-
end
|
125
|
-
osm_filename
|
126
|
-
end
|
127
|
-
|
128
|
-
# Saves an OpenStudio IDF model object to file
|
129
|
-
#
|
130
|
-
# @param [Object] model The OpenStudio::Workspace instance to save to file
|
131
|
-
# @param [String] save_directory Folder to save the model in
|
132
|
-
# @param [String] name ('in.osm') Option to define a non-standard name
|
133
|
-
# @return [String] IDF file name
|
134
|
-
#
|
135
|
-
def save_idf(model_idf, save_directory, name = 'in.idf')
|
136
|
-
idf_filename = File.join(save_directory.to_s, name.to_s)
|
137
|
-
File.open(idf_filename, 'w') do |f|
|
138
|
-
f << model_idf.to_s
|
139
|
-
# make sure data is written to the disk one way or the other
|
140
|
-
begin
|
141
|
-
f.fsync
|
142
|
-
rescue
|
143
|
-
f.flush
|
144
|
-
end
|
145
|
-
end
|
146
|
-
idf_filename
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
24
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
25
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
|
27
|
+
# GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
28
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
29
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
33
|
+
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
module OpenStudio
|
37
|
+
module Workflow
|
38
|
+
module Util
|
39
|
+
# Manages routine tasks involving OpenStudio::Model or OpenStudio::Workflow objects, such as loading, saving, and
|
40
|
+
# translating them.
|
41
|
+
#
|
42
|
+
module Model
|
43
|
+
# Method to create / load an OSM file
|
44
|
+
#
|
45
|
+
# @param [String] osm_path The full path to an OSM file to load
|
46
|
+
# @param [Object] logger An optional logger to use for finding the OSM model
|
47
|
+
# @return [Object] The return from this method is a loaded OSM or a failure.
|
48
|
+
#
|
49
|
+
def load_osm(osm_path, logger)
|
50
|
+
logger.info 'Loading OSM model'
|
51
|
+
|
52
|
+
# Load the model and return it
|
53
|
+
logger.info "Reading in OSM model #{osm_path}"
|
54
|
+
|
55
|
+
loaded_model = nil
|
56
|
+
begin
|
57
|
+
translator = OpenStudio::OSVersion::VersionTranslator.new
|
58
|
+
loaded_model = translator.loadModel(osm_path)
|
59
|
+
rescue StandardError
|
60
|
+
# TODO: get translator working in embedded.
|
61
|
+
# Need to embed idd files
|
62
|
+
logger.warn 'OpenStudio VersionTranslator could not be loaded'
|
63
|
+
loaded_model = OpenStudio::Model::Model.load(osm_path)
|
64
|
+
end
|
65
|
+
raise "Failed to load OSM file #{osm_path}" if loaded_model.empty?
|
66
|
+
loaded_model.get
|
67
|
+
end
|
68
|
+
|
69
|
+
# Method to create / load an IDF file
|
70
|
+
#
|
71
|
+
# @param [String] idf_path Full path to the IDF
|
72
|
+
# @param [Object] logger An optional logger to use for finding the idf model
|
73
|
+
# @return [Object] The return from this method is a loaded IDF or a failure.
|
74
|
+
#
|
75
|
+
def load_idf(idf_path, logger)
|
76
|
+
logger.info 'Loading IDF model'
|
77
|
+
|
78
|
+
# Load the IDF into a workspace object and return it
|
79
|
+
logger.info "Reading in IDF model #{idf_path}"
|
80
|
+
|
81
|
+
idf = OpenStudio::Workspace.load(idf_path)
|
82
|
+
raise "Failed to load IDF file #{idf_path}" if idf.empty?
|
83
|
+
idf.get
|
84
|
+
end
|
85
|
+
|
86
|
+
# Translates a OpenStudio model object into an OpenStudio IDF object
|
87
|
+
#
|
88
|
+
# @param [Object] model the OpenStudio::Model instance to translate into an OpenStudio::Workspace object -- see
|
89
|
+
# the OpenStudio SDK for details on the process
|
90
|
+
# @return [Object] Returns and OpenStudio::Workspace object
|
91
|
+
# @todo (rhorsey) rescue errors here
|
92
|
+
#
|
93
|
+
def translate_to_energyplus(model, logger = nil)
|
94
|
+
logger ||= ::Logger.new(STDOUT)
|
95
|
+
logger.info 'Translate object to EnergyPlus IDF in preparation for EnergyPlus'
|
96
|
+
a = ::Time.now
|
97
|
+
# ensure objects exist for reporting purposes
|
98
|
+
model.getFacility
|
99
|
+
model.getBuilding
|
100
|
+
forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
|
101
|
+
model_idf = forward_translator.translateModel(model)
|
102
|
+
b = ::Time.now
|
103
|
+
logger.info "Translate object to EnergyPlus IDF took #{b.to_f - a.to_f}"
|
104
|
+
model_idf
|
105
|
+
end
|
106
|
+
|
107
|
+
# Saves an OpenStudio model object to file
|
108
|
+
#
|
109
|
+
# @param [Object] model The OpenStudio::Model instance to save to file
|
110
|
+
# @param [String] save_directory Folder to save the model in
|
111
|
+
# @param [String] name ('in.osm') Option to define a non-standard name
|
112
|
+
# @return [String] OSM file name
|
113
|
+
#
|
114
|
+
def save_osm(model, save_directory, name = 'in.osm')
|
115
|
+
osm_filename = File.join(save_directory.to_s, name.to_s)
|
116
|
+
File.open(osm_filename, 'w') do |f|
|
117
|
+
f << model.to_s
|
118
|
+
# make sure data is written to the disk one way or the other
|
119
|
+
begin
|
120
|
+
f.fsync
|
121
|
+
rescue StandardError
|
122
|
+
f.flush
|
123
|
+
end
|
124
|
+
end
|
125
|
+
osm_filename
|
126
|
+
end
|
127
|
+
|
128
|
+
# Saves an OpenStudio IDF model object to file
|
129
|
+
#
|
130
|
+
# @param [Object] model The OpenStudio::Workspace instance to save to file
|
131
|
+
# @param [String] save_directory Folder to save the model in
|
132
|
+
# @param [String] name ('in.osm') Option to define a non-standard name
|
133
|
+
# @return [String] IDF file name
|
134
|
+
#
|
135
|
+
def save_idf(model_idf, save_directory, name = 'in.idf')
|
136
|
+
idf_filename = File.join(save_directory.to_s, name.to_s)
|
137
|
+
File.open(idf_filename, 'w') do |f|
|
138
|
+
f << model_idf.to_s
|
139
|
+
# make sure data is written to the disk one way or the other
|
140
|
+
begin
|
141
|
+
f.fsync
|
142
|
+
rescue StandardError
|
143
|
+
f.flush
|
144
|
+
end
|
145
|
+
end
|
146
|
+
idf_filename
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -1,238 +1,235 @@
|
|
1
|
-
# *******************************************************************************
|
2
|
-
# OpenStudio(R), Copyright (c) 2008-
|
3
|
-
# All rights reserved.
|
4
|
-
# Redistribution and use in source and binary forms, with or without
|
5
|
-
# modification, are permitted provided that the following conditions are met:
|
6
|
-
#
|
7
|
-
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
-
# this list of conditions and the following disclaimer.
|
9
|
-
#
|
10
|
-
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
-
# this list of conditions and the following disclaimer in the documentation
|
12
|
-
# and/or other materials provided with the distribution.
|
13
|
-
#
|
14
|
-
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
-
# may be used to endorse or promote products derived from this software without
|
16
|
-
# specific prior written permission from the respective party.
|
17
|
-
#
|
18
|
-
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
-
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
-
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
-
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
-
#
|
23
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
24
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
25
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
-
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
|
27
|
-
# GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
28
|
-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
29
|
-
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30
|
-
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31
|
-
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32
|
-
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
33
|
-
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
-
# *******************************************************************************
|
35
|
-
|
36
|
-
module OpenStudio
|
37
|
-
module Workflow
|
38
|
-
module Util
|
39
|
-
require 'openstudio/workflow/util/measure'
|
40
|
-
require 'csv'
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
#
|
50
|
-
#
|
51
|
-
# @
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# @
|
62
|
-
# @
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
h =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
analysis_json
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
objective_functions["
|
118
|
-
objective_functions["
|
119
|
-
objective_functions["
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
# @param [
|
135
|
-
#
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
#
|
159
|
-
#
|
160
|
-
# @param [String]
|
161
|
-
#
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
html
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
f.
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
measure_xml = REXML::Document.new File.read(measure_xml_path)
|
197
|
-
measure_class_name = OpenStudio.toUnderscoreCase(measure_xml.root.elements['class_name'].text)
|
198
|
-
else
|
199
|
-
measure_class_name = OpenStudio.toUnderscoreCase(measure_dir_name)
|
200
|
-
end
|
201
|
-
file_ext = File.extname(report)
|
202
|
-
append_str = File.basename(report, '.*')
|
203
|
-
new_file_name = "#{directory}/reports/#{measure_class_name}_#{append_str}#{file_ext}"
|
204
|
-
logger.info "Saving report #{report} to #{new_file_name}"
|
205
|
-
FileUtils.copy report, new_file_name
|
206
|
-
end
|
207
|
-
|
208
|
-
# Remove empty directories in run folder
|
209
|
-
Dir["#{run_dir}/*"].select { |d| File.directory? d }.select { |d| (Dir.entries(d) -
|
210
|
-
logger.info "Removing empty directory #{d}"
|
211
|
-
Dir.rmdir d
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
paths_to_rm
|
224
|
-
# paths_to_rm << Pathname.glob("
|
225
|
-
# paths_to_rm << Pathname.glob("#{run_dir}/*.
|
226
|
-
|
227
|
-
|
228
|
-
# paths_to_rm << Pathname.glob("#{run_dir}/*.
|
229
|
-
paths_to_rm << Pathname.glob("#{run_dir}/*.
|
230
|
-
paths_to_rm
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
24
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
25
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES
|
27
|
+
# GOVERNMENT, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
28
|
+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
29
|
+
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30
|
+
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
33
|
+
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
module OpenStudio
|
37
|
+
module Workflow
|
38
|
+
module Util
|
39
|
+
require 'openstudio/workflow/util/measure'
|
40
|
+
require 'csv'
|
41
|
+
|
42
|
+
# This module serves as a wrapper around various post-processing tasks used to manage outputs
|
43
|
+
# @todo (rhorsey) ummmm. So some of this is pretty ugly. Since @dmacumber had ideas about this maybe he can figure
|
44
|
+
# out what to do about it all
|
45
|
+
# @todo (nlong) the output adapter restructure will frack up the extraction method royally
|
46
|
+
#
|
47
|
+
module PostProcess
|
48
|
+
# This method loads a sql file into OpenStudio and returns it
|
49
|
+
#
|
50
|
+
# @param [String] sql_file Absolute path to the sql file to be loaded
|
51
|
+
# @return [Object, nil] The OpenStudio::SqlFile object, or nil if it could not be found
|
52
|
+
#
|
53
|
+
def load_sql_file(sql_file)
|
54
|
+
return nil unless File.exist? sql_file
|
55
|
+
OpenStudio::SqlFile.new(@sql_filename)
|
56
|
+
end
|
57
|
+
|
58
|
+
# This method parses all sorts of stuff which something needs
|
59
|
+
#
|
60
|
+
# @param [String] run_dir The directory that the simulation was run in
|
61
|
+
# @return [Hash, Hash] results and objective_function (which may be empty) are returned
|
62
|
+
# @todo (rhorsey) fix the description
|
63
|
+
#
|
64
|
+
def run_extract_inputs_and_outputs(run_dir, logger)
|
65
|
+
# For xml, the measure attributes are in the measure_attributes_xml.json file
|
66
|
+
# TODO: somehow pass the metadata around on which JSONs to suck into the database
|
67
|
+
results = {}
|
68
|
+
# Inputs are in the measure_attributes.json file
|
69
|
+
if File.exist? "#{run_dir}/measure_attributes.json"
|
70
|
+
h = JSON.parse(File.read("#{run_dir}/measure_attributes.json"), symbolize_names: true)
|
71
|
+
h = rename_hash_keys(h, logger)
|
72
|
+
results.merge! h
|
73
|
+
end
|
74
|
+
|
75
|
+
logger.info 'Saving the result hash to file'
|
76
|
+
File.open("#{run_dir}/results.json", 'w') do |f|
|
77
|
+
f << JSON.pretty_generate(results)
|
78
|
+
# make sure data is written to the disk one way or the other
|
79
|
+
begin
|
80
|
+
f.fsync
|
81
|
+
rescue StandardError
|
82
|
+
f.flush
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
objective_functions = {}
|
87
|
+
if @registry[:analysis]
|
88
|
+
logger.info 'Iterating over Analysis JSON Output Variables'
|
89
|
+
# Save the objective functions to the object for sending back to the simulation executive
|
90
|
+
analysis_json = @registry[:analysis]
|
91
|
+
if analysis_json[:analysis] && analysis_json[:analysis][:output_variables]
|
92
|
+
analysis_json[:analysis][:output_variables].each do |variable|
|
93
|
+
# determine which ones are the objective functions (code smell: todo: use enumerator)
|
94
|
+
if variable[:objective_function]
|
95
|
+
logger.info "Looking for objective function #{variable[:name]}"
|
96
|
+
# TODO: move this to cleaner logic. Use ostruct?
|
97
|
+
k, v = variable[:name].split('.')
|
98
|
+
|
99
|
+
# look for the objective function key and make sure that it is not nil. False is an okay obj function.
|
100
|
+
if results.key?(k.to_sym) && !results[k.to_sym][v.to_sym].nil?
|
101
|
+
objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = results[k.to_sym][v.to_sym]
|
102
|
+
if variable[:objective_function_target]
|
103
|
+
logger.info "Found objective function target for #{variable[:name]}"
|
104
|
+
objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_target].to_f
|
105
|
+
end
|
106
|
+
if variable[:scaling_factor]
|
107
|
+
logger.info "Found scaling factor for #{variable[:name]}"
|
108
|
+
objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = variable[:scaling_factor].to_f
|
109
|
+
end
|
110
|
+
if variable[:objective_function_group]
|
111
|
+
logger.info "Found objective function group for #{variable[:name]}"
|
112
|
+
objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = variable[:objective_function_group].to_f
|
113
|
+
end
|
114
|
+
else
|
115
|
+
logger.warn "No results for objective function #{variable[:name]}"
|
116
|
+
objective_functions["objective_function_#{variable[:objective_function_index] + 1}"] = Float::MAX
|
117
|
+
objective_functions["objective_function_target_#{variable[:objective_function_index] + 1}"] = nil
|
118
|
+
objective_functions["scaling_factor_#{variable[:objective_function_index] + 1}"] = nil
|
119
|
+
objective_functions["objective_function_group_#{variable[:objective_function_index] + 1}"] = nil
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
return results, objective_functions
|
127
|
+
end
|
128
|
+
|
129
|
+
# Remove any invalid characters in the measure attribute keys. Periods and Pipes are the most problematic
|
130
|
+
# because mongo does not allow hash keys with periods, and the pipes are used in the map/reduce method that
|
131
|
+
# was written to speed up the data write in openstudio-server. Also remove any trailing underscores and spaces
|
132
|
+
#
|
133
|
+
# @param [Hash] hash Any hash with potentially problematic characters
|
134
|
+
# @param [Logger] logger Logger to write to
|
135
|
+
#
|
136
|
+
def rename_hash_keys(hash, logger)
|
137
|
+
# @todo should we log the name changes?
|
138
|
+
regex = /[|!@#\$%^&\*\(\)\{\}\\\[\];:'",<.>\/?\+=]+/
|
139
|
+
|
140
|
+
rename_keys = lambda do |h|
|
141
|
+
if Hash === h
|
142
|
+
h.each_key do |key|
|
143
|
+
if key.to_s =~ regex
|
144
|
+
logger.warn "Renaming result key '#{key}' to remove invalid characters"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
Hash[h.map { |k, v| [k.to_s.gsub(regex, '_').squeeze('_').gsub(/[_\s]+$/, '').chomp.to_sym, rename_keys[v]] }]
|
148
|
+
else
|
149
|
+
h
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
rename_keys[hash]
|
154
|
+
end
|
155
|
+
|
156
|
+
# Save reports to a common directory
|
157
|
+
#
|
158
|
+
# @param [String] run_dir
|
159
|
+
# @param [String] directory
|
160
|
+
# @param [String] logger
|
161
|
+
#
|
162
|
+
def gather_reports(run_dir, directory, workflow_json, logger)
|
163
|
+
logger.info run_dir
|
164
|
+
logger.info directory
|
165
|
+
|
166
|
+
FileUtils.mkdir_p "#{directory}/reports"
|
167
|
+
|
168
|
+
# try to find the energyplus result file
|
169
|
+
eplus_html = "#{run_dir}/eplustbl.htm"
|
170
|
+
if File.exist? eplus_html
|
171
|
+
# do some encoding on the html if possible
|
172
|
+
html = File.read(eplus_html)
|
173
|
+
html = html.force_encoding('ISO-8859-1').encode('utf-8', replace: nil)
|
174
|
+
logger.info "Saving EnergyPlus HTML report to #{directory}/reports/eplustbl.html"
|
175
|
+
File.open("#{directory}/reports/eplustbl.html", 'w') do |f|
|
176
|
+
f << html
|
177
|
+
# make sure data is written to the disk one way or the other
|
178
|
+
begin
|
179
|
+
f.fsync
|
180
|
+
rescue StandardError
|
181
|
+
f.flush
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# Also, find any "report*.*" files
|
187
|
+
Dir["#{run_dir}/*/report*.*"].each do |report|
|
188
|
+
# HRH: This is a temporary work-around to support PAT 2.1 pretty names AND the CLI while we roll a WorkflowJSON solution
|
189
|
+
measure_dir_name = File.dirname(report).split(File::SEPARATOR).last.gsub(/[0-9][0-9][0-9]_/, '')
|
190
|
+
measure_xml_path = File.absolute_path(File.join(File.dirname(report), '../../..', 'measures',
|
191
|
+
measure_dir_name, 'measure.xml'))
|
192
|
+
logger.info "measure_xml_path: #{measure_xml_path}"
|
193
|
+
if File.exist? measure_xml_path
|
194
|
+
# REXML is slow, so we lazy load only as needed
|
195
|
+
require 'rexml/document'
|
196
|
+
measure_xml = REXML::Document.new File.read(measure_xml_path)
|
197
|
+
measure_class_name = OpenStudio.toUnderscoreCase(measure_xml.root.elements['class_name'].text)
|
198
|
+
else
|
199
|
+
measure_class_name = OpenStudio.toUnderscoreCase(measure_dir_name)
|
200
|
+
end
|
201
|
+
file_ext = File.extname(report)
|
202
|
+
append_str = File.basename(report, '.*')
|
203
|
+
new_file_name = "#{directory}/reports/#{measure_class_name}_#{append_str}#{file_ext}"
|
204
|
+
logger.info "Saving report #{report} to #{new_file_name}"
|
205
|
+
FileUtils.copy report, new_file_name
|
206
|
+
end
|
207
|
+
|
208
|
+
# Remove empty directories in run folder
|
209
|
+
Dir["#{run_dir}/*"].select { |d| File.directory? d }.select { |d| (Dir.entries(d) - ['.', '..']).empty? }.each do |d|
|
210
|
+
logger.info "Removing empty directory #{d}"
|
211
|
+
Dir.rmdir d
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# A general post-processing step which could be made significantly more modular
|
216
|
+
#
|
217
|
+
# @param [String] run_dir
|
218
|
+
#
|
219
|
+
def cleanup(run_dir, directory, logger)
|
220
|
+
paths_to_rm = []
|
221
|
+
# paths_to_rm << Pathname.glob("#{run_dir}/*.osm")
|
222
|
+
# paths_to_rm << Pathname.glob("#{run_dir}/*.idf") # keep the idfs
|
223
|
+
# paths_to_rm << Pathname.glob("*.audit")
|
224
|
+
# paths_to_rm << Pathname.glob("*.bnd")
|
225
|
+
# paths_to_rm << Pathname.glob("#{run_dir}/*.eso")
|
226
|
+
paths_to_rm << Pathname.glob("#{run_dir}/*.mtr")
|
227
|
+
paths_to_rm << Pathname.glob("#{run_dir}/*.epw")
|
228
|
+
# paths_to_rm << Pathname.glob("#{run_dir}/*.mtd")
|
229
|
+
# paths_to_rm << Pathname.glob("#{run_dir}/*.rdd")
|
230
|
+
paths_to_rm.each { |p| FileUtils.rm_rf(p) }
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|