openstudio-workflow 1.0.0.pat1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +16 -68
- data/Rakefile +9 -9
- data/bin/openstudio_cli +786 -0
- data/lib/openstudio/workflow/adapters/input/local.rb +97 -0
- data/lib/openstudio/workflow/adapters/output/local.rb +90 -0
- data/lib/openstudio/workflow/adapters/output/socket.rb +70 -0
- data/lib/openstudio/workflow/{jobs/run_preflight/run_preflight.rb → adapters/output/web.rb} +37 -19
- data/lib/openstudio/workflow/{adapter.rb → adapters/output_adapter.rb} +53 -51
- data/lib/openstudio/workflow/job.rb +22 -0
- data/lib/openstudio/workflow/jobs/{run_energyplus → resources}/monthly_report.idf +0 -0
- data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -0
- data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -0
- data/lib/openstudio/workflow/jobs/run_initialization.rb +136 -0
- data/lib/openstudio/workflow/jobs/run_os_measures.rb +59 -0
- data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -0
- data/lib/openstudio/workflow/jobs/run_preprocess.rb +81 -0
- data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +86 -0
- data/lib/openstudio/workflow/jobs/run_translation.rb +49 -0
- data/lib/openstudio/workflow/multi_delegator.rb +1 -3
- data/lib/openstudio/workflow/registry.rb +137 -0
- data/lib/openstudio/workflow/run.rb +182 -221
- data/lib/openstudio/workflow/time_logger.rb +1 -1
- data/lib/openstudio/workflow/util/energyplus.rb +564 -0
- data/lib/openstudio/workflow/util/io.rb +33 -0
- data/lib/openstudio/workflow/util/measure.rb +520 -0
- data/lib/openstudio/workflow/util/model.rb +100 -0
- data/lib/openstudio/workflow/util/post_process.rb +177 -0
- data/lib/openstudio/workflow/util/weather_file.rb +108 -0
- data/lib/openstudio/workflow/util.rb +14 -0
- data/lib/openstudio/workflow/version.rb +1 -1
- data/lib/openstudio/workflow_json.rb +399 -0
- data/lib/openstudio/workflow_runner.rb +213 -0
- data/lib/openstudio-workflow.rb +13 -118
- metadata +45 -85
- data/lib/openstudio/extended_runner.rb +0 -105
- data/lib/openstudio/workflow/adapters/local.rb +0 -101
- data/lib/openstudio/workflow/adapters/mongo.rb +0 -227
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +0 -253
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +0 -314
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +0 -230
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +0 -110
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +0 -471
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +0 -247
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +0 -279
@@ -0,0 +1,136 @@
|
|
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 the initialization job to run validations and initializations
|
21
|
+
class RunInitialization < OpenStudio::Workflow::Job
|
22
|
+
require 'openstudio/workflow/util'
|
23
|
+
include OpenStudio::Workflow::Util::WeatherFile
|
24
|
+
include OpenStudio::Workflow::Util::Model
|
25
|
+
include OpenStudio::Workflow::Util::Measure
|
26
|
+
|
27
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
28
|
+
defaults = {
|
29
|
+
verify_osw: true
|
30
|
+
}
|
31
|
+
options = defaults.merge(options)
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def perform
|
36
|
+
# DLM: why are there multiple loggers running around? there is one in the registry can we just use that?
|
37
|
+
@logger.info "Calling #{__method__} in the #{self.class} class"
|
38
|
+
|
39
|
+
# Communicate that the workflow has been started
|
40
|
+
@logger.debug 'Registering that the workflow has started with the adapter'
|
41
|
+
@output_adapter.communicate_started
|
42
|
+
|
43
|
+
# Load various files and set basic directories for the registry
|
44
|
+
@registry.register(:workflow) { @input_adapter.workflow }
|
45
|
+
raise 'Specified workflow was nil' unless @registry[:workflow]
|
46
|
+
@logger.debug 'Retrieved the workflow from the adapter'
|
47
|
+
|
48
|
+
@registry.register(:osw_dir) { @input_adapter.osw_dir }
|
49
|
+
@logger.debug "osw_dir is #{@registry[:osw_dir]}"
|
50
|
+
|
51
|
+
@registry.register(:datapoint) { @input_adapter.datapoint }
|
52
|
+
@logger.debug 'Found associated OSD file' if @registry[:datapoint]
|
53
|
+
|
54
|
+
@registry.register(:analysis) { @input_adapter.analysis }
|
55
|
+
@logger.debug 'Found associated OSA file' if @registry[:analysis]
|
56
|
+
|
57
|
+
# create the real WorkflowJSON here, we will be able to edit this during the run
|
58
|
+
if @registry[:openstudio_2]
|
59
|
+
workflow_json = OpenStudio::WorkflowJSON.new(JSON.fast_generate(@registry[:workflow]))
|
60
|
+
workflow_json.setOswDir(@registry[:osw_dir])
|
61
|
+
else
|
62
|
+
workflow_json = WorkflowJSON_Shim.new(@registry[:workflow], @registry[:osw_dir])
|
63
|
+
end
|
64
|
+
@registry.register(:workflow_json) { workflow_json }
|
65
|
+
|
66
|
+
@registry.register(:root_dir) { workflow_json.absoluteRootDir }
|
67
|
+
@logger.debug "The root_dir for the datapoint is #{@registry[:root_dir]}"
|
68
|
+
|
69
|
+
# create the runner with our WorkflowJSON
|
70
|
+
@registry.register(:runner) { WorkflowRunner.new(@registry[:logger], @registry[:workflow_json], @registry[:openstudio_2]) }
|
71
|
+
@logger.debug 'Initialized runner'
|
72
|
+
|
73
|
+
workflow_json.start
|
74
|
+
|
75
|
+
# Validate the OSW measures if the flag is set to true, (the default state)
|
76
|
+
if @options[:verify_osw]
|
77
|
+
@logger.info 'Attempting to validate the measure workflow'
|
78
|
+
validate_measures(@registry, @logger)
|
79
|
+
@logger.info 'Validated the measure workflow'
|
80
|
+
end
|
81
|
+
|
82
|
+
# Load or create the seed OSM object
|
83
|
+
@logger.debug 'Finding and loading the seed file'
|
84
|
+
model_path = workflow_json.seedFile
|
85
|
+
if !model_path.empty?
|
86
|
+
|
87
|
+
model_full_path = workflow_json.findFile(model_path.get)
|
88
|
+
if model_full_path.empty?
|
89
|
+
raise "Seed model #{model_path.get} specified in OSW cannot be found"
|
90
|
+
end
|
91
|
+
model_full_path = model_full_path.get
|
92
|
+
|
93
|
+
if File.extname(model_full_path.to_s) == '.idf'
|
94
|
+
@registry.register(:model_idf) { load_idf(model_full_path, @logger) }
|
95
|
+
@registry.register(:model) { nil }
|
96
|
+
else
|
97
|
+
@registry.register(:model) { load_osm(model_full_path, @logger) }
|
98
|
+
end
|
99
|
+
else
|
100
|
+
@registry.register(:model) { OpenStudio::Model::Model.new }
|
101
|
+
end
|
102
|
+
|
103
|
+
# Find the weather file, should it exist and be findable
|
104
|
+
@logger.debug 'Getting the initial weather file'
|
105
|
+
weather_path = workflow_json.weatherFile
|
106
|
+
if weather_path.empty?
|
107
|
+
@logger.debug 'No weather file specified in OSW, looking in model'
|
108
|
+
if @registry[:model]
|
109
|
+
model = @registry[:model]
|
110
|
+
unless model.weatherFile.empty?
|
111
|
+
weather_path = model.weatherFile.get.path
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
unless weather_path.empty?
|
117
|
+
weather_path = weather_path.get
|
118
|
+
@logger.debug 'Searching for weather file #{weather_path}'
|
119
|
+
|
120
|
+
weather_full_path = workflow_json.findFile(weather_path)
|
121
|
+
if weather_full_path.empty?
|
122
|
+
weather_full_path = workflow_json.findFile(File.basename(weather_path.to_s))
|
123
|
+
end
|
124
|
+
|
125
|
+
if weather_full_path.empty?
|
126
|
+
raise "Weather file #{weather_path} specified but cannot be found"
|
127
|
+
end
|
128
|
+
weather_full_path = weather_full_path.get
|
129
|
+
|
130
|
+
@registry.register(:wf) { weather_full_path.to_s }
|
131
|
+
end
|
132
|
+
@logger.warn 'No valid weather file defined in either the osm or osw.' unless @registry[:wf]
|
133
|
+
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,59 @@
|
|
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 any OpenStudio measures contained in the OSW
|
21
|
+
class RunOpenStudioMeasures < OpenStudio::Workflow::Job
|
22
|
+
# Mixin the required util modules
|
23
|
+
require 'openstudio/workflow/util'
|
24
|
+
include OpenStudio::Workflow::Util::Measure
|
25
|
+
include OpenStudio::Workflow::Util::Model
|
26
|
+
|
27
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform
|
32
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
33
|
+
|
34
|
+
# Ensure output_attributes is initialized in the registry
|
35
|
+
@registry.register(:output_attributes) { {} } unless @registry[:output_attributes]
|
36
|
+
|
37
|
+
# Execute the OpenStudio measures
|
38
|
+
@options[:output_adapter] = @output_adapter
|
39
|
+
@logger.info 'Beginning to execute OpenStudio measures.'
|
40
|
+
apply_measures('ModelMeasure'.to_MeasureType, @registry, @options)
|
41
|
+
@logger.info('Finished applying OpenStudio measures.')
|
42
|
+
|
43
|
+
# Send the measure output attributes to the output adapter
|
44
|
+
@logger.debug 'Communicating measure output attributes to the output adapter'
|
45
|
+
@output_adapter.communicate_measure_attributes @registry[:output_attributes]
|
46
|
+
|
47
|
+
# save the final OSM
|
48
|
+
save_osm(@registry[:model], @registry[:run_dir])
|
49
|
+
|
50
|
+
# Save the OSM if the :debug option is true
|
51
|
+
return nil unless @options[:debug]
|
52
|
+
@registry[:time_logger].start('Saving OSM') if @registry[:time_logger]
|
53
|
+
osm_name = save_osm(@registry[:model], @registry[:root_dir])
|
54
|
+
@registry[:time_logger].stop('Saving OSM') if @registry[:time_logger]
|
55
|
+
@logger.debug "Saved model as #{osm_name}"
|
56
|
+
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,53 @@
|
|
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
|
+
# Clean up the run directory. Currently this class does nothing else, although eventually cleanup should become driven
|
21
|
+
# and responsive to options
|
22
|
+
class RunPostprocess < OpenStudio::Workflow::Job
|
23
|
+
require 'openstudio/workflow/util/post_process'
|
24
|
+
include OpenStudio::Workflow::Util::PostProcess
|
25
|
+
|
26
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
27
|
+
defaults = {
|
28
|
+
cleanup: true
|
29
|
+
}
|
30
|
+
options = defaults.merge(options)
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def perform
|
35
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
36
|
+
|
37
|
+
@logger.info 'Gathering reports'
|
38
|
+
gather_reports(@registry[:run_dir], @registry[:root_dir], @logger)
|
39
|
+
@logger.info 'Finished gathering reports'
|
40
|
+
|
41
|
+
if @options[:cleanup]
|
42
|
+
@logger.info 'Beginning cleanup of the run directory'
|
43
|
+
cleanup(@registry[:run_dir], @registry[:root_dir], @logger)
|
44
|
+
@logger.info 'Finished cleanup of the run directory'
|
45
|
+
else
|
46
|
+
@logger.info 'Flag for cleanup in options set to false. Moving to next step.'
|
47
|
+
end
|
48
|
+
|
49
|
+
@logger.info 'Finished postprocess'
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,81 @@
|
|
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
|
+
# Prepares the directory for the EnergyPlus simulation
|
21
|
+
class RunPreprocess < OpenStudio::Workflow::Job
|
22
|
+
require 'openstudio/workflow/util'
|
23
|
+
include OpenStudio::Workflow::Util::EnergyPlus
|
24
|
+
include OpenStudio::Workflow::Util::Model
|
25
|
+
include OpenStudio::Workflow::Util::Measure
|
26
|
+
|
27
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform
|
32
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
33
|
+
|
34
|
+
# Ensure that the directory is created (but it should already be at this point)
|
35
|
+
FileUtils.mkdir_p(@registry[:run_dir])
|
36
|
+
|
37
|
+
# Copy in the weather file defined in the registry, or alternately in the options
|
38
|
+
if @registry[:wf]
|
39
|
+
@logger.info "Weather file for EnergyPlus simulation is #{@registry[:wf]}"
|
40
|
+
FileUtils.copy(@registry[:wf], "#{@registry[:run_dir]}/in.epw")
|
41
|
+
elsif @options[:simulation_weather_file]
|
42
|
+
@logger.warn "Using weather file defined in options: #{@options[:simulation_weather_file]}"
|
43
|
+
FileUtils.copy(@options[:simulation_weather_file], "#{@registry[:run_dir]}/in.epw")
|
44
|
+
else
|
45
|
+
@logger.warn "EPW file not found or not sent to #{self.class}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# save the pre-preprocess file
|
49
|
+
File.open("#{@registry[:run_dir]}/pre-preprocess.idf", 'w') { |f| f << @registry[:model_idf].to_s }
|
50
|
+
|
51
|
+
# Add any EnergyPlus Output Requests from Reporting Measures
|
52
|
+
@logger.info 'Beginning to collect output requests from Reporting measures.'
|
53
|
+
@options[:energyplus_output_requests] = true
|
54
|
+
apply_measures('ReportingMeasure'.to_MeasureType, @registry, @options)
|
55
|
+
@options[:energyplus_output_requests] = nil
|
56
|
+
@logger.info('Finished collect output requests from Reporting measures.')
|
57
|
+
|
58
|
+
# Perform pre-processing on in.idf to capture logic in RunManager
|
59
|
+
@registry[:time_logger].start('Running EnergyPlus Preprocess') if @registry[:time_logger]
|
60
|
+
energyplus_preprocess(@registry[:model_idf], @logger)
|
61
|
+
@registry[:time_logger].start('Running EnergyPlus Preprocess') if @registry[:time_logger]
|
62
|
+
@logger.info 'Finished preprocess job for EnergyPlus simulation'
|
63
|
+
|
64
|
+
# Save the model objects in the registry to the run directory
|
65
|
+
if File.exist?("#{@registry[:run_dir]}/in.idf")
|
66
|
+
# DLM: why is this here?
|
67
|
+
@logger.warn 'IDF (in.idf) already exists in the run directory. Will simulate using this file'
|
68
|
+
else
|
69
|
+
save_idf(@registry[:model_idf], @registry[:run_dir])
|
70
|
+
end
|
71
|
+
|
72
|
+
# Save the generated IDF file if the :debug option is true
|
73
|
+
return nil unless @options[:debug]
|
74
|
+
@registry[:time_logger].start('Saving IDF') if @registry[:time_logger]
|
75
|
+
idf_name = save_idf(@registry[:model_idf], @registry[:root_dir])
|
76
|
+
@registry[:time_logger].stop('Saving IDF') if @registry[:time_logger]
|
77
|
+
@logger.debug "Saved IDF as #{idf_name}"
|
78
|
+
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,86 @@
|
|
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 reporting measures and execute scripts to post-process objective functions and results on the filesystem
|
21
|
+
class RunReportingMeasures < OpenStudio::Workflow::Job
|
22
|
+
require 'csv'
|
23
|
+
require 'ostruct'
|
24
|
+
require 'openstudio/workflow/util'
|
25
|
+
include OpenStudio::Workflow::Util::Model
|
26
|
+
include OpenStudio::Workflow::Util::Measure
|
27
|
+
include OpenStudio::Workflow::Util::PostProcess
|
28
|
+
|
29
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
30
|
+
defaults = {
|
31
|
+
load_simulation_osm: false,
|
32
|
+
load_simulation_idf: false,
|
33
|
+
load_simulation_sql: false
|
34
|
+
}
|
35
|
+
options = defaults.merge(options)
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def perform
|
40
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
41
|
+
@logger.debug 'RunPostProcess Retrieving datapoint and problem'
|
42
|
+
|
43
|
+
# Ensure output_attributes is initialized in the registry
|
44
|
+
@registry.register(:output_attributes) { {} } unless @registry[:output_attributes]
|
45
|
+
|
46
|
+
# Load simulation files as required
|
47
|
+
if @options[:load_simulation_osm]
|
48
|
+
osm_path = File.absolute_path(File.join(@registry[:run_dir], 'in.osm'))
|
49
|
+
@logger.debug "Attempting to load #{osm_path}"
|
50
|
+
@registry.register(:model) { load_osm('.', osm_path) }
|
51
|
+
raise "Unable to load #{osm_path}" unless @registry[:model]
|
52
|
+
@logger.debug "Successfully loaded #{osm_path}"
|
53
|
+
end
|
54
|
+
if @options[:load_simulation_idf]
|
55
|
+
idf_path = File.absolute_path(File.join(@registry[:run_dir], 'in.idf'))
|
56
|
+
@logger.debug "Attempting to load #{idf_path}"
|
57
|
+
@registry.register(:model_idf) { load_idf('.', idf_path) }
|
58
|
+
raise "Unable to load #{idf_path}" unless @registry[:model_idf]
|
59
|
+
@logger.debug "Successfully loaded #{idf_path}"
|
60
|
+
end
|
61
|
+
if @options[:load_simulation_sql]
|
62
|
+
@registry.register(:sql) { File.absolute_path(File.join(@registry[:run_dir], 'eplusout.sql')) }
|
63
|
+
@logger.debug "Registered the sql filepath as #{@registry[:sql]}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Apply reporting measures
|
67
|
+
@options[:output_adapter] = @output_adapter
|
68
|
+
@logger.info 'Beginning to execute Reporting measures.'
|
69
|
+
apply_measures('ReportingMeasure'.to_MeasureType, @registry, @options)
|
70
|
+
@logger.info('Finished applying Reporting measures.')
|
71
|
+
|
72
|
+
# Send the updated measure_attributes to the output adapter
|
73
|
+
@logger.debug 'Communicating measures output attributes to the output adapter'
|
74
|
+
@output_adapter.communicate_measure_attributes @registry[:output_attributes]
|
75
|
+
|
76
|
+
# Parse the files generated by the local output adapter
|
77
|
+
results, objective_functions = run_extract_inputs_and_outputs @registry[:run_dir], @logger
|
78
|
+
@registry.register(:results) { results }
|
79
|
+
|
80
|
+
# Send the objective function results to the output adapter
|
81
|
+
@logger.debug "Objective Function JSON is #{objective_functions}"
|
82
|
+
@output_adapter.communicate_objective_function objective_functions
|
83
|
+
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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 the initialization job to validate the directory and initialize the adapters.
|
21
|
+
class RunTranslation < OpenStudio::Workflow::Job
|
22
|
+
require 'openstudio/workflow/util/model'
|
23
|
+
include OpenStudio::Workflow::Util::Model
|
24
|
+
|
25
|
+
def initialize(input_adapter, output_adapter, registry, options = {})
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def perform
|
30
|
+
@logger.debug "Calling #{__method__} in the #{self.class} class"
|
31
|
+
|
32
|
+
# Translate the OSM to an IDF
|
33
|
+
@logger.info 'Beginning the translation to IDF'
|
34
|
+
@registry[:time_logger].start('Translating to EnergyPlus') if @registry[:time_logger]
|
35
|
+
model_idf = translate_to_energyplus @registry[:model], @logger
|
36
|
+
@registry[:time_logger].stop('Translating to EnergyPlus') if @registry[:time_logger]
|
37
|
+
@registry.register(:model_idf) { model_idf }
|
38
|
+
@logger.info 'Successfully translated to IDF'
|
39
|
+
|
40
|
+
# Save the generated IDF file if the :debug option is true
|
41
|
+
return nil unless @options[:debug]
|
42
|
+
@registry[:time_logger].start('Saving IDF') if @registry[:time_logger]
|
43
|
+
idf_name = save_idf(@registry[:model_idf], @registry[:root_dir])
|
44
|
+
@registry[:time_logger].stop('Saving IDF') if @registry[:time_logger]
|
45
|
+
@logger.debug "Saved IDF as #{idf_name}"
|
46
|
+
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
@@ -21,8 +21,6 @@ require 'logger'
|
|
21
21
|
|
22
22
|
class Logger
|
23
23
|
def format_message(severity, datetime, _progname, msg)
|
24
|
-
# "#{datetime} (#{$$}) #{msg}\n"
|
25
|
-
# "#{datetime}: #{msg}\n"
|
26
24
|
"[%s %s] %s\n" % [datetime.strftime('%H:%M:%S.%6N'), severity, msg]
|
27
25
|
end
|
28
26
|
end
|
@@ -43,6 +41,6 @@ class MultiDelegator
|
|
43
41
|
end
|
44
42
|
|
45
43
|
class <<self
|
46
|
-
|
44
|
+
alias to new
|
47
45
|
end
|
48
46
|
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module OpenStudio
|
2
|
+
module Workflow
|
3
|
+
# Registers objects in a single place. Based on Hashicorps's Vagrant Registry class
|
4
|
+
#
|
5
|
+
# This allows certain components (such as models, weather files, proxy settings, etc.) to be registered as blocks
|
6
|
+
# and lazily updated. This allows for the state of various objects to be updated through evaluation of or
|
7
|
+
# overwriting the key. An instance of this class is passed between jobs to allow for highly flexible workflow
|
8
|
+
# definitions. Note that hashes can be passed into the registry as follows: hash = {...};
|
9
|
+
# Registry.new.register(:hash) { hash } or Registry.new.register(:hash) { {...} }. This class will likely absorb
|
10
|
+
# un-abstracted elements of the adapter class, see Workflow#Adapter
|
11
|
+
|
12
|
+
# @todo (rhorsey) registry should be a member of WorkflowRunner - DLM
|
13
|
+
# @todo (rhorsey) how is this different than a regular hash? why is it important to be able to register keys with blocks that return values instead of values, looks like the block is called on insert anyway? let's not go crazy on performance optimizations until we have to - DLM
|
14
|
+
class Registry
|
15
|
+
def initialize
|
16
|
+
@items = {}
|
17
|
+
@results_cache = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Register a key and cache it's value. Note that if a key with the given name already exists it is overwritten
|
21
|
+
#
|
22
|
+
# @param [] key The key for the passed in block. Symbols are highly recommended
|
23
|
+
# @param [Proc] block The block (Proc) which contains the registered information
|
24
|
+
# @return [] Returns block.call from the registries cache
|
25
|
+
#
|
26
|
+
def register(key, &block)
|
27
|
+
raise ArgumentError, 'block required' unless block_given?
|
28
|
+
@items[key] = block
|
29
|
+
@results_cache[key] = @items[key].call
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get the cached value of the given key
|
33
|
+
#
|
34
|
+
# @param [] key The key defining the block
|
35
|
+
# @return [] Returns the registries cached value for the key or nil if the key was not found
|
36
|
+
#
|
37
|
+
def get(key)
|
38
|
+
return nil unless @items.key?(key)
|
39
|
+
@results_cache[key]
|
40
|
+
end
|
41
|
+
alias [] get
|
42
|
+
|
43
|
+
# Re-evaluate the proc of a key and update the cache
|
44
|
+
#
|
45
|
+
# @param [Sym or String] key This will evaluate the item assigned to the key and update the cache if possible
|
46
|
+
# @return [] If successful the method returns the new value, and if it cannot find or cannot update the key it
|
47
|
+
# returns nil
|
48
|
+
#
|
49
|
+
def eval(key)
|
50
|
+
return nil unless @items.key?(key)
|
51
|
+
begin
|
52
|
+
@items[key].call
|
53
|
+
rescue
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
@results_cache[key] = @items[key].call
|
57
|
+
end
|
58
|
+
|
59
|
+
# Checks if the given key is registered with the registry
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
def key?(key)
|
64
|
+
@items.key?(key)
|
65
|
+
end
|
66
|
+
alias has_key? key?
|
67
|
+
|
68
|
+
# Returns an array populated with the keys of this object
|
69
|
+
#
|
70
|
+
# @return [Array]
|
71
|
+
#
|
72
|
+
def keys
|
73
|
+
@items.keys
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the number of elements in this registry
|
77
|
+
#
|
78
|
+
# @return [Fixnum]
|
79
|
+
#
|
80
|
+
def length
|
81
|
+
@items.keys.length
|
82
|
+
end
|
83
|
+
alias size length
|
84
|
+
|
85
|
+
# Checks if this registry has any items
|
86
|
+
#
|
87
|
+
# @return [Boolean]
|
88
|
+
#
|
89
|
+
def empty?
|
90
|
+
@items.keys.empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Merge one registry with another and return a completely new registry. Note that the result cache is completely
|
94
|
+
# busted, so any gets on the new registry will result in a cache miss
|
95
|
+
#
|
96
|
+
# @param [Registry] other The other #Registry to merge onto of self
|
97
|
+
# @return [Registry] A merged #Registry
|
98
|
+
#
|
99
|
+
def merge(other)
|
100
|
+
self.class.new.tap do |result|
|
101
|
+
result.merge!(self)
|
102
|
+
result.merge!(other)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Like #merge but updates self
|
107
|
+
#
|
108
|
+
# @param [Registry] other The other #Registry to merge onto of self
|
109
|
+
# @return [Void]
|
110
|
+
#
|
111
|
+
def merge!(other)
|
112
|
+
@items.merge!(other.__internal_state[:items])
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Converts the registry to a hash
|
117
|
+
#
|
118
|
+
# @return [Hash] The registry as a hash
|
119
|
+
#
|
120
|
+
def to_hash
|
121
|
+
result = {}
|
122
|
+
@results_cache.each_pair do |key, value|
|
123
|
+
result[key] = value
|
124
|
+
end
|
125
|
+
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
def __internal_state
|
130
|
+
{
|
131
|
+
items: @items,
|
132
|
+
results_cache: @results_cache
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|