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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +16 -68
  4. data/Rakefile +9 -9
  5. data/bin/openstudio_cli +786 -0
  6. data/lib/openstudio/workflow/adapters/input/local.rb +97 -0
  7. data/lib/openstudio/workflow/adapters/output/local.rb +90 -0
  8. data/lib/openstudio/workflow/adapters/output/socket.rb +70 -0
  9. data/lib/openstudio/workflow/{jobs/run_preflight/run_preflight.rb → adapters/output/web.rb} +37 -19
  10. data/lib/openstudio/workflow/{adapter.rb → adapters/output_adapter.rb} +53 -51
  11. data/lib/openstudio/workflow/job.rb +22 -0
  12. data/lib/openstudio/workflow/jobs/{run_energyplus → resources}/monthly_report.idf +0 -0
  13. data/lib/openstudio/workflow/jobs/run_energyplus.rb +49 -0
  14. data/lib/openstudio/workflow/jobs/run_ep_measures.rb +55 -0
  15. data/lib/openstudio/workflow/jobs/run_initialization.rb +136 -0
  16. data/lib/openstudio/workflow/jobs/run_os_measures.rb +59 -0
  17. data/lib/openstudio/workflow/jobs/run_postprocess.rb +53 -0
  18. data/lib/openstudio/workflow/jobs/run_preprocess.rb +81 -0
  19. data/lib/openstudio/workflow/jobs/run_reporting_measures.rb +86 -0
  20. data/lib/openstudio/workflow/jobs/run_translation.rb +49 -0
  21. data/lib/openstudio/workflow/multi_delegator.rb +1 -3
  22. data/lib/openstudio/workflow/registry.rb +137 -0
  23. data/lib/openstudio/workflow/run.rb +182 -221
  24. data/lib/openstudio/workflow/time_logger.rb +1 -1
  25. data/lib/openstudio/workflow/util/energyplus.rb +564 -0
  26. data/lib/openstudio/workflow/util/io.rb +33 -0
  27. data/lib/openstudio/workflow/util/measure.rb +520 -0
  28. data/lib/openstudio/workflow/util/model.rb +100 -0
  29. data/lib/openstudio/workflow/util/post_process.rb +177 -0
  30. data/lib/openstudio/workflow/util/weather_file.rb +108 -0
  31. data/lib/openstudio/workflow/util.rb +14 -0
  32. data/lib/openstudio/workflow/version.rb +1 -1
  33. data/lib/openstudio/workflow_json.rb +399 -0
  34. data/lib/openstudio/workflow_runner.rb +213 -0
  35. data/lib/openstudio-workflow.rb +13 -118
  36. metadata +45 -85
  37. data/lib/openstudio/extended_runner.rb +0 -105
  38. data/lib/openstudio/workflow/adapters/local.rb +0 -101
  39. data/lib/openstudio/workflow/adapters/mongo.rb +0 -227
  40. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +0 -253
  41. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +0 -314
  42. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +0 -230
  43. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +0 -110
  44. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +0 -471
  45. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +0 -247
  46. 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
- alias_method :to, :new
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