openstudio-workflow 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/README.md +24 -63
  4. data/lib/openstudio/extended_runner.rb +94 -0
  5. data/lib/openstudio/workflow/adapter.rb +10 -0
  6. data/lib/openstudio/workflow/adapters/mongo.rb +1 -1
  7. data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +12 -17
  8. data/lib/openstudio/workflow/jobs/{run_openstudio → run_energyplus}/monthly_report.idf +8 -4
  9. data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +132 -21
  10. data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +6 -11
  11. data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +7 -6
  12. data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +2 -1
  13. data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +27 -148
  14. data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +31 -10
  15. data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +4 -3
  16. data/lib/openstudio/workflow/run.rb +4 -5
  17. data/lib/openstudio/workflow/version.rb +1 -1
  18. data/lib/openstudio-workflow.rb +6 -10
  19. metadata +9 -12
  20. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md +0 -5
  21. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb +0 -206
  22. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml +0 -53
  23. data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/resources/report.html.erb +0 -298
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e81fcf5450aa2cf5f13bc03f0a253f14b95d74e9
4
- data.tar.gz: 90a64f53393b213e23b9961a3096895de4fe4f4b
3
+ metadata.gz: 859f53e5f54c14eee213cff7b0bdd7a6bc9d4c98
4
+ data.tar.gz: b58de6c2993630809e26a27bf735fcac371280cc
5
5
  SHA512:
6
- metadata.gz: 6d95bdac9f31a85775003125291db53cabf63be1bf2a054fe79def4a1281f05f422b68cd23d4cc2f37132d286288ed0cdcf610b790ea7c92103f42ae20499dd2
7
- data.tar.gz: 22491f3a0392364381028ef6287cf0dc2a4a837388da2a62013caa981799cb797f98a2150176b05b6055f87fb350230609e99c95c7ca7ccfc301435111758636
6
+ metadata.gz: dcb4afd15fa0d9eecb08ee60835a87310c4dc4f8e7c3cc97d87919f6127c6c706df7074315200c054280c2cf6c84a0ce4baacebeefcc6fcdeded08a28dafdeff
7
+ data.tar.gz: 9fd2d0449335fb0998b936851e042f1f1957817a55e0654bf37d3168420bf5def9bdab975b180ccc381cb66f80e963f9e54b38347d93db7804ea7036f6eddce4
data/CHANGELOG.md CHANGED
@@ -1,6 +1,18 @@
1
1
  OpenStudio::Workflow Change Log
2
2
  ==================================
3
3
 
4
+ Version 0.2.0
5
+ ------------------
6
+ * Use EnergyPlus that is packaged with OpenStudio. The branch of this repo is no longer tied to the version of EnergyPlus
7
+ * Update find_energyplus to use new OpenStudio method instead of RUBYLIB env var
8
+ * Update dependencies
9
+ * Support tests running on Docker
10
+ * Skip the PAT tests for now since they are broken
11
+ * Remove snake_case method as it conflicts with another libraries method, now called to_underscore
12
+ * Add test for persisting JSONs as reports. Rename reports in the form of <measure_name_underscored>_<report_name>.<ext>
13
+ * Always add in Monthly Reports (Deprecate the :run_monthly_reports option)
14
+ * Remove the old Standard Reports and use the version in the OpenStudio Release (along with the calibration report)
15
+
4
16
  Version 0.1.1
5
17
  ------------------
6
18
  * Catch exception when loading a measure file.
@@ -12,7 +24,6 @@ Version 0.1.1
12
24
  * Better cleanup after EnergyPlus simulation
13
25
  * Read machine information from /etc/openstudio-server directory, if available
14
26
 
15
-
16
27
  Version 0.1.0
17
28
  -------------
18
29
  * Tests for programmatically creating the analysis.json files from the OpenStudio-analysis-gem
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # OpenStudio::Workflow
2
+ [![Circle CI](https://circleci.com/gh/NREL/OpenStudio-workflow-gem/tree/EnergyPlus-8.3.0.svg?style=svg)](https://circleci.com/gh/NREL/OpenStudio-workflow-gem/tree/EnergyPlus-8.3.0)
3
+ [![Coverage Status](https://coveralls.io/repos/NREL/OpenStudio-workflow-gem/badge.svg?branch=EnergyPlus-8.3.0&service=github)](https://coveralls.io/github/NREL/OpenStudio-workflow-gem?branch=EnergyPlus-8.3.0)
2
4
  [![Dependency Status](https://www.versioneye.com/user/projects/5531fb7b10e714121100102e/badge.svg?style=flat)](https://www.versioneye.com/user/projects/5531fb7b10e714121100102e)
3
5
 
4
6
  Run an EnergyPlus simulation using a file-based workflow that is read from a Local or MongoDB adapter.
@@ -9,7 +11,7 @@ The OpenStudio Workflow Gem has the following dependencies:
9
11
 
10
12
  * Ruby 2.0
11
13
  * OpenStudio with Ruby 2.0 bindings
12
- * EnergyPlus 8.2 (assuming OpenStudio >= 1.5.4)
14
+ * EnergyPlus 8.3 (assuming OpenStudio >= 1.7.2)
13
15
  * MongoDB if using MongoDB Adapter (or when running rspec)
14
16
 
15
17
  [OpenStudio](http://developer.nrel.gov/downloads/buildings/openstudio/builds/) needs to be installed
@@ -58,40 +60,40 @@ The workflow manager can also use MongoDB to receive instructions on the workflo
58
60
 
59
61
  ## Caveats and Todos
60
62
 
61
- ### Caveats
62
-
63
- * There are currently several hard coded workflow options
64
- * Must use OpenStudio with Ruby 2.0 support
65
- * Using MongoDB as the Adapter requires a command line zip (gnuzip) utility
66
-
67
63
  ### Todos
68
64
 
69
65
  * Read the analysis.json file to determine the states that are going to run instead of (or in addition to) passing them into the constructor
70
66
  * Implement better error handling with custom exception classes
71
- * ~Implement a different measure directory, seed model directory, and weather file directory option~
72
- * ~Dynamically add other "states" to the workflow~
73
- * ~~Create and change into a unique directory when running measures~~
74
- * ~~Implement Error State~~
75
- * ~~Implement MongoDB Adapter~~
76
- * ~~Implement remaining Adapter states (i.e. communicate success, communicate failure etc~~
77
67
  * Add a results adapter to return a string as the last call based on the source of the call. (e.g. R, command line, C++, etc).
78
68
  * Implement a logger in the Adapters, right now they are unable to log
79
- * Hook up the measure groups based workflows
80
- * ~~Add xml workflow item~~
69
+ * Hook up the measure group based workflows
81
70
 
82
- ## Testing and Development
71
+ ## Testing
83
72
 
84
- Depending on what adapter is being tested it may be preferable to skip installing various gems. This can be done by calling
73
+ The preferred way for testing is to run rspec either natively or via docker. The issue with natively running the tests locally is the requirement to have mongo installed and running.
85
74
 
86
- bundle install --without mongo
75
+ ### Locally
87
76
 
88
- On Windows it is recommended to bundle without mongo nor ci as they may require native extensions.
77
+ ```
78
+ rake
79
+ ```
89
80
 
90
- bundle install --without mongo ci
81
+ ### Docker
91
82
 
92
- ### Testing
83
+ To run all the tests automatically run:
84
+ ```
85
+ docker run --rm -v $(pwd):/var/simdata/openstudio nrel/docker-test-containers:openstudio-1.8.5-mongo-2.4 /var/simdata/openstudio/test/bin/docker-run.sh
86
+ ```
93
87
 
94
- Run `rspec` or `rake` to execute the tests.
88
+ To run the tests inside docker and enable debugging, then create a bash shell in docker with:
89
+ ```
90
+ docker run -it --rm -v $(pwd):/var/simdata/openstudio nrel/docker-test-containers:openstudio-1.8.5-mongo-2.4 bash
91
+ service mongodb start
92
+ bundle update
93
+ rake
94
+ # or
95
+ bundle exec rspec <file>:<line>
96
+ ```
95
97
 
96
98
  ## Contributing
97
99
 
@@ -100,44 +102,3 @@ Run `rspec` or `rake` to execute the tests.
100
102
  3. Commit your changes (`git commit -am 'Add some feature'`)
101
103
  4. Push to the branch (`git push origin my-new-feature`)
102
104
  5. Create a new Pull Request
103
-
104
- ## Development
105
-
106
- If you are testing changes to OpenStudio source code and want to test these on the Vagrant machine you can use the source configuration. This creates a new virtual machine which can be accessed by adding the name 'source' to the end of standard Vagrant commands. To set up this machine, build a custom version of OpenStudio, and install that version for testing follow these steps:
107
-
108
- * vagrant up source
109
- * vagrant ssh source
110
- * sudo apt-get install dpkg-dev git cmake-curses-gui qt5-default libqt5webkit5-dev libboost1.55-all-dev swig ruby2.0 libssl-dev libxt-dev doxygen graphviz
111
- * sudo ln -s /usr/lib/x86_64-linux-gnu/libruby-2.0.so.2.0.0 /usr/lib/x86_64-linux-gnu/libruby.so.2.0
112
- ** Install clang (OPTIONAL):
113
- ** wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
114
- ** sudo apt-add-repository 'deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.5 main'
115
- ** sudo apt-get update
116
- ** sudo apt-get install clang-3.5
117
- ** echo 'export CC=/usr/bin/clang-3.5' >> ~/.bashrc
118
- ** echo 'export CXX=/usr/bin/clang++-3.5' >> ~/.bashrc
119
- ** source ~/.bashrc
120
- * cd /home/vagrant
121
- * git clone https://github.com/NREL/OpenStudio.git openstudio
122
- * cd openstudio
123
- * git checkout your_branch_name
124
- * mkdir build
125
- * cd build
126
- * cmake .. -DBUILD_PACKAGE=TRUE -DCMAKE_INSTALL_PREFIX=$OPENSTUDIO_ROOT -DRUBY_EXECUTABLE=/usr/local/rbenv/versions/2.0.0-p481/bin/ruby
127
- * make -j4
128
-
129
- To install do either:
130
- * cd OpenStudioCore-prefix/src/OpenStudioCore-build/
131
- * sudo make install
132
-
133
- or:
134
- * make package
135
- * sudo ./OpenStudio-1.5.1.02b7131b4c-Linux.sh --prefix=/usr/local --exclude-subdir --skip-license
136
-
137
- Next you have to do this:
138
- * export RUBYLIB=/usr/local/Ruby
139
- * export LD_LIBRARY_PATH=/usr/local/lib
140
-
141
- Then you can test that you are using your build by comparing the output of these two commands:
142
- * ruby -e "require 'openstudio'" -e "puts OpenStudio::openStudioLongVersion"
143
- * git rev-parse --short HEAD
@@ -0,0 +1,94 @@
1
+ # Extend OS Runner to persist measure information throughout the workflow
2
+ class ExtendedRunner < OpenStudio::Ruleset::OSRunner
3
+ # Allow former arguments to be set and read
4
+ # TODO: Consider having the former arguments passed in in initialization, and define as attr_reader
5
+ attr_accessor :former_workflow_arguments
6
+ attr_reader :workflow_arguments
7
+
8
+ # Add in @workflow_arguments
9
+ def initialize(multi_logger)
10
+ @multi_logger = multi_logger
11
+ @workflow_arguments = nil
12
+ super()
13
+ end
14
+
15
+ # Take the OS Argument type and map it correctly to the argument value.
16
+ # OPENSTUDIO_ENUM( OSArgumentType,
17
+ # ((Boolean)(Bool)(0))
18
+ # ((Double)(Double)(1))
19
+ # ((Quantity)(Quantity)(2))
20
+ # ((Integer)(Int)(3))
21
+ # ((String)(String)(4))
22
+ # ((Choice)(Choice)(5))
23
+ # ((Path)(Path)(6))
24
+ # );
25
+ # @param os_argument_name [String] The string of the argument to check
26
+ # @param user_arguments [OSArgumentMap] Map of the arguments to check
27
+ def bad_os_typecasting(os_argument_name, user_arguments)
28
+ out = nil
29
+ user_arguments.each do |arg_name, arg|
30
+ # get the type cast value
31
+ next unless os_argument_name == arg_name
32
+
33
+ case arg.type.valueName
34
+ when 'Boolean'
35
+ out = arg.valueAsBool if arg.hasValue
36
+ when 'Double'
37
+ out = arg.valueAsDouble if arg.hasValue
38
+ when 'Quantity'
39
+ warn 'This OpenStudio Argument Type is deprecated'
40
+ when 'Integer'
41
+ out = arg.valueAsInteger if arg.hasValue
42
+ when 'String'
43
+ out = arg.valueAsString if arg.hasValue
44
+ when 'Choice'
45
+ out = arg.valueAsString if arg.hasValue
46
+ when 'Path'
47
+ out = arg.valueAsPath.to_s if arg.hasValue
48
+ end
49
+ end
50
+
51
+ out
52
+ end
53
+
54
+ # Overloaded argument parsing
55
+ def validateUserArguments(script_arguments, user_arguments)
56
+ @workflow_arguments = {}
57
+ user_arguments.each do |hash|
58
+ value = bad_os_typecasting(hash, user_arguments)
59
+ @workflow_arguments[hash.to_sym] = value if value
60
+ end
61
+
62
+ super
63
+ end
64
+
65
+ # Overload registerInfo
66
+ def registerInfo(message)
67
+ super
68
+ @multi_logger.info message
69
+ end
70
+
71
+ # Overload registerInfo
72
+ def registerWarning(message)
73
+ super
74
+ @multi_logger.warn message
75
+ end
76
+
77
+ # Overload registerError
78
+ def registerError(message)
79
+ super
80
+ @multi_logger.error message
81
+ end
82
+
83
+ # Overload registerInitialCondition
84
+ def registerInitialCondition(message)
85
+ super
86
+ @multi_logger.info message
87
+ end
88
+
89
+ # Overload registerFinalCondition
90
+ def registerFinalCondition(message)
91
+ super
92
+ @multi_logger.info message
93
+ end
94
+ end
@@ -90,10 +90,20 @@ module OpenStudio
90
90
  if File.basename(file) =~ /seed|measures|weather/
91
91
  next
92
92
  end
93
+ # skip x-large directory
94
+ if File.size?(file)
95
+ next if File.size?(file) >= 15000000
96
+ end
93
97
  add_directory_to_zip(zf, file, directory)
94
98
  else
95
99
  next if File.extname(file) =~ /\.rb.*/
96
100
  next if File.extname(file) =~ /\.zip.*/
101
+ # skip large non-osm/idf files
102
+ if File.size(file)
103
+ if File.size(file) >= 15000000
104
+ next unless File.extname(file) == '.osm' || File.extname(file) == '.idf'
105
+ end
106
+ end
97
107
 
98
108
  zip_file_to_add = file.gsub("#{directory}/", '')
99
109
  zf.add(zip_file_to_add, file)
@@ -29,7 +29,7 @@ module OpenStudio
29
29
  end
30
30
 
31
31
  def write(msg)
32
- @dp.sdp_log_file << msg.gsub("\n", '')
32
+ @dp.sdp_log_file << msg.delete("\n")
33
33
  @dp.save!
34
34
  end
35
35
  end
@@ -126,7 +126,8 @@ module OpenStudio
126
126
  begin
127
127
  require measure_file_path
128
128
  measure = Object.const_get(measure_name).new
129
- runner = OpenStudio::Ruleset::OSRunner.new
129
+ runner = ExtendedRunner.new @logger
130
+ runner.former_workflow_arguments = @workflow_arguments
130
131
  rescue => e
131
132
  log_message = "Error requiring measure #{__FILE__}. Failed with #{e.message}, #{e.backtrace.join("\n")}"
132
133
  raise log_message
@@ -143,12 +144,12 @@ module OpenStudio
143
144
  arguments = measure.arguments
144
145
  end
145
146
 
146
- @logger.info "Extracted the following arguments: #{arguments}"
147
-
148
147
  # Create argument map and initialize all the arguments
149
148
  argument_map = OpenStudio::Ruleset::OSArgumentMap.new
150
- arguments.each do |v|
151
- argument_map[v.name] = v.clone
149
+ if arguments
150
+ arguments.each do |v|
151
+ argument_map[v.name] = v.clone
152
+ end
152
153
  end
153
154
  # @logger.info "Argument map for measure is #{argument_map}"
154
155
 
@@ -177,15 +178,19 @@ module OpenStudio
177
178
  if workflow_item[:measure_type] == 'RubyMeasure'
178
179
  measure.run(@model, runner, argument_map)
179
180
  elsif workflow_item[:measure_type] == 'EnergyPlusMeasure'
181
+ runner.setLastOpenStudioModel(@model)
180
182
  measure.run(@model_idf, runner, argument_map)
181
183
  elsif workflow_item[:measure_type] == 'ReportingMeasure'
182
- # This is silly, set the last model and last sqlfile instead of passing it into the measure.run method
184
+ # This is silly, set the last model, last IDF, and last sqlfile instead of passing it into the measure.run method
183
185
  runner.setLastOpenStudioModel(@model)
186
+ runner.setLastEnergyPlusWorkspace(@model_idf)
184
187
  runner.setLastEnergyPlusSqlFilePath(@sql_filename)
185
188
 
186
189
  measure.run(runner, argument_map)
187
190
  end
191
+ @workflow_arguments[workflow_item[:name].to_sym] = runner.workflow_arguments
188
192
  @logger.info "Finished measure.run for '#{workflow_item[:name]}'"
193
+ GC.start
189
194
  rescue => e
190
195
  log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
191
196
  raise log_message
@@ -195,17 +200,7 @@ module OpenStudio
195
200
  result = runner.result
196
201
  @logger.info "Running of measure '#{workflow_item[:name]}' completed. Post-processing measure output"
197
202
 
198
- @logger.info result.initialCondition.get.logMessage unless result.initialCondition.empty?
199
- @logger.info result.finalCondition.get.logMessage unless result.finalCondition.empty?
200
-
201
- result.warnings.each { |w| @logger.warn w.logMessage }
202
- an_error = false
203
- result.errors.each do |w|
204
- @logger.error w.logMessage
205
- an_error = true
206
- end
207
- fail "Measure #{measure_name} reported an error, check log" if an_error
208
- result.info.each { |w| @logger.info w.logMessage }
203
+ fail "Measure #{measure_name} reported an error, check log" if result.errors.size != 0
209
204
  rescue => e
210
205
  log_message = "Runner error #{__FILE__} failed with #{e.message}, #{e.backtrace.join("\n")}"
211
206
  raise log_message
@@ -29,6 +29,7 @@ Output:Table:Monthly,
29
29
  SumOrAverage, !- Aggregation Type for Variable or Meter 13
30
30
  Refrigeration:Electricity,!- Variable or Meter 14 Name
31
31
  SumOrAverage; !- Aggregation Type for Variable or Meter 14
32
+
32
33
  Output:Table:Monthly,
33
34
  Building Energy Performance - Natural Gas, !- Name
34
35
  2, !- Digits After Decimal
@@ -44,6 +45,7 @@ Output:Table:Monthly,
44
45
  SumOrAverage, !- Aggregation Type for Variable or Meter 5
45
46
  Cogeneration:Gas, !- Variable or Meter 6 Name
46
47
  SumOrAverage; !- Aggregation Type for Variable or Meter 6
48
+
47
49
  Output:Table:Monthly,
48
50
  Building Energy Performance - District Heating, !- Name
49
51
  2, !- Digits After Decimal
@@ -73,6 +75,7 @@ Output:Table:Monthly,
73
75
  SumOrAverage, !- Aggregation Type for Variable or Meter 12
74
76
  Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
75
77
  SumOrAverage; !- Aggregation Type for Variable or Meter 13
78
+
76
79
  Output:Table:Monthly,
77
80
  Building Energy Performance - District Cooling, !- Name
78
81
  2, !- Digits After Decimal
@@ -102,6 +105,7 @@ Output:Table:Monthly,
102
105
  SumOrAverage, !- Aggregation Type for Variable or Meter 12
103
106
  Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
104
107
  SumOrAverage; !- Aggregation Type for Variable or Meter 13
108
+
105
109
  Output:Table:Monthly,
106
110
  Building Energy Performance - Electricity Peak Demand, !- Name
107
111
  2, !- Digits After Decimal
@@ -133,6 +137,7 @@ Output:Table:Monthly,
133
137
  ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
134
138
  Cogeneration:Electricity,!- Variable or Meter 13 Name
135
139
  ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
140
+
136
141
  Output:Table:Monthly,
137
142
  Building Energy Performance - Natural Gas Peak Demand, !- Name
138
143
  2, !- Digits After Decimal
@@ -150,6 +155,7 @@ Output:Table:Monthly,
150
155
  ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 5
151
156
  Cogeneration:Gas, !- Variable or Meter 6 Name
152
157
  ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 6
158
+
153
159
  Output:Table:Monthly,
154
160
  Building Energy Performance - District Heating Peak Demand, !- Name
155
161
  2, !- Digits After Decimal
@@ -181,6 +187,7 @@ Output:Table:Monthly,
181
187
  ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
182
188
  Cogeneration:DistrictHeating,!- Variable or Meter 13 Name
183
189
  ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
190
+
184
191
  Output:Table:Monthly,
185
192
  Building Energy Performance - District Cooling Peak Demand, !- Name
186
193
  2, !- Digits After Decimal
@@ -212,7 +219,4 @@ Output:Table:Monthly,
212
219
  ValueWhenMaximumOrMinimum, !- Aggregation Type for Variable or Meter 12
213
220
  Cogeneration:DistrictCooling,!- Variable or Meter 13 Name
214
221
  ValueWhenMaximumOrMinimum; !- Aggregation Type for Variable or Meter 13
215
- Output:Meter,Electricity:Facility,Timestep; !- [J]
216
- Output:Meter,Gas:Facility,Timestep; !- [J]
217
- Output:Meter,DistrictCooling:Facility,Timestep; !- [J]
218
- Output:Meter,DistrictHeating:Facility,Timestep; !- [J]
222
+
@@ -17,16 +17,14 @@
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
  ######################################################################
19
19
 
20
- # Force the MakeMakefile logger write file output to null.
21
- module MakeMakefile::Logging
22
- @logfile = File::NULL
23
- end
24
-
25
20
  class RunEnergyplus
21
+ ENERGYPLUS_REGEX = /^energyplus\D{0,4}$/i
22
+ EXPAND_OBJECTS_REGEX = /^expandobjects\D{0,4}$/i
23
+
26
24
  # Initialize
27
25
  # param directory: base directory where the simulation files are prepared
28
26
  # param logger: logger object in which to write log messages
29
- def initialize(directory, logger, time_logger, adapter, options = {})
27
+ def initialize(directory, logger, time_logger, adapter, workflow_arguments, options = {})
30
28
  @logger = logger
31
29
 
32
30
  energyplus_path = find_energyplus
@@ -40,6 +38,7 @@ class RunEnergyplus
40
38
  @run_directory = "#{@directory}/run"
41
39
  @adapter = adapter
42
40
  @time_logger = time_logger
41
+ @workflow_arguments = workflow_arguments
43
42
  @results = {}
44
43
 
45
44
  # container for storing the energyplus files there were copied into the local directory. These will be
@@ -108,6 +107,10 @@ class RunEnergyplus
108
107
  prepare_energyplus_dir
109
108
  @time_logger.stop('Copying EnergyPlus files')
110
109
 
110
+ @time_logger.start('Running EnergyPlus Preprocess Script')
111
+ energyplus_preprocess("#{@run_directory}/in.idf")
112
+ @time_logger.start('Running EnergyPlus Preprocess Script')
113
+
111
114
  @time_logger.start('Running EnergyPlus')
112
115
  @results = call_energyplus
113
116
  @time_logger.stop('Running EnergyPlus')
@@ -117,24 +120,27 @@ class RunEnergyplus
117
120
 
118
121
  private
119
122
 
120
- # Look for the location of EnergyPlus
121
123
  def find_energyplus
122
124
  if ENV['ENERGYPLUSDIR']
123
125
  return ENV['ENERGYPLUSDIR']
126
+ # TODO: check if method exists! first
127
+ elsif OpenStudio.respond_to? :getEnergyPlusDirectory
128
+ return OpenStudio.getEnergyPlusDirectory.to_s
124
129
  elsif ENV['RUBYLIB'] =~ /OpenStudio/
130
+ warn 'Finding EnergyPlus by RUBYLIB parsing will not be supported in the near future. Use either ENERGYPLUSDIR'\
131
+ 'env variable or a newer OpenStudio version that has the getEnergyPlusDirectory method'
125
132
  path = ENV['RUBYLIB'].split(':')
126
133
  path = File.dirname(path.find { |p| p =~ /OpenStudio/ })
127
134
  # Grab the version out of the openstudio path
128
- path += '/sharedresources/EnergyPlus-8-2-0'
129
- @logger.info "found EnergyPlus path of #{path}"
135
+ path += '/sharedresources/EnergyPlus-8-3-0'
136
+
130
137
  return path
131
138
  else
132
139
  if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
133
- energyplus_path = 'C:/EnergyPlus-8-2-0'
140
+ return 'C:/EnergyPlus-8-3-0'
134
141
  else
135
- energyplus_path = '/usr/local/EnergyPlus-8-2-0'
142
+ return '/usr/local/EnergyPlus-8-3-0'
136
143
  end
137
-
138
144
  end
139
145
  end
140
146
 
@@ -164,13 +170,13 @@ class RunEnergyplus
164
170
  dest_file = "#{@run_directory}/#{File.basename(file)}"
165
171
  @energyplus_files << dest_file
166
172
 
167
- @energyplus_exe = File.basename(dest_file) if File.basename(dest_file) =~ /^energyplus.{0,4}$/i
168
- @expand_objects_exe = File.basename(dest_file) if File.basename(dest_file) =~ /^ExpandObjects.{0,4}$/i
173
+ @energyplus_exe = File.basename(dest_file) if File.basename(dest_file) =~ ENERGYPLUS_REGEX
174
+ @expand_objects_exe = File.basename(dest_file) if File.basename(dest_file) =~ EXPAND_OBJECTS_REGEX
169
175
  FileUtils.copy file, dest_file
170
176
  end
171
177
 
172
- fail "Could not find EnergyPlus Executable in #{@options[:energyplus_path]}" unless @energyplus_exe
173
- fail "Could not find ExpandObjects Executable in #{@options[:energyplus_path]}" unless @expand_objects_exe
178
+ fail "Could not find EnergyPlus executable in #{@options[:energyplus_path]}" unless @energyplus_exe
179
+ fail "Could not find ExpandObjects executable in #{@options[:energyplus_path]}" unless @expand_objects_exe
174
180
 
175
181
  @energyplus_files.size > 0
176
182
  end
@@ -181,11 +187,6 @@ class RunEnergyplus
181
187
  Dir.chdir(@run_directory)
182
188
  @logger.info "Starting simulation in run directory: #{Dir.pwd}"
183
189
 
184
- # @logger.info "Contents of: #{Dir.pwd}"
185
- # Dir.glob("*").each do |f|
186
- # @logger.info " #{f}"
187
- # end
188
-
189
190
  File.open('stdout-expandobject', 'w') do |file|
190
191
  IO.popen("./#{@expand_objects_exe}") do |io|
191
192
  while (line = io.gets)
@@ -247,4 +248,114 @@ class RunEnergyplus
247
248
 
248
249
  {}
249
250
  end
251
+
252
+ # Run this code before running energyplus to make sure the reporting variables are setup correctly
253
+ def energyplus_preprocess(idf_filename)
254
+ @logger.info 'Running EnergyPlus Preprocess'
255
+
256
+ fail "Could not find IDF file in run directory (#{idf_filename})" unless File.exist? idf_filename
257
+
258
+ new_objects = []
259
+ needs_monthlyoutput = false
260
+
261
+ # this is a workaround for OpenStudio issue #1699
262
+ needs_detailedvariable = false
263
+ needs_hourlyvariable = false
264
+ needs_dailyvariable = false
265
+ needs_runperiodvariable = false
266
+
267
+ idf = OpenStudio::IdfFile.load(idf_filename).get
268
+ # save the pre-preprocess file
269
+ File.open("#{File.dirname(idf_filename)}/pre-preprocess.idf", 'w') { |f| f << idf.to_s }
270
+
271
+ needs_sqlobj = idf.getObjectsByType('Output:SQLite'.to_IddObjectType).empty?
272
+
273
+ needs_monthlyoutput = idf.getObjectsByName('Building Energy Performance - Natural Gas').empty? ||
274
+ idf.getObjectsByName('Building Energy Performance - Electricity').empty? ||
275
+ idf.getObjectsByName('Building Energy Performance - District Heating').empty? ||
276
+ idf.getObjectsByName('Building Energy Performance - District Cooling').empty?
277
+
278
+ # this is a workaround for issue #1699 -- get all the meter requests
279
+ meters = []
280
+ meters += idf.getObjectsByType('Output:Meter'.to_IddObjectType) unless idf.getObjectsByType('Output:Meter'.to_IddObjectType).empty?
281
+ meters += idf.getObjectsByType('Output:Meter:MeterFileOnly'.to_IddObjectType) unless idf.getObjectsByType('Output:Meter:MeterFileOnly'.to_IddObjectType).empty?
282
+ meters += idf.getObjectsByType('Output:Meter:Cumulative'.to_IddObjectType) unless idf.getObjectsByType('Output:Meter:Cumulative'.to_IddObjectType).empty?
283
+ meters += idf.getObjectsByType('Output:Meter:Cumulative:MeterFileOnly'.to_IddObjectType) unless idf.getObjectsByType('Output:Meter:Cumulative:MeterFileOnly'.to_IddObjectType).empty?
284
+
285
+ # go through each meter and check the reporting frequency
286
+ meters.each do |meter|
287
+ reporting_frequency = meter.getString(1, true)
288
+ if reporting_frequency =~ /detailed/i
289
+ needs_detailedvariable = true
290
+ elsif reporting_frequency =~ /hourly/i
291
+ needs_hourlyvariable = true
292
+ elsif reporting_frequency =~ /daily/i
293
+ needs_dailyvariable = true
294
+ elsif reporting_frequency =~ /monthly/i
295
+ needs_monthlyvariable = true
296
+ elsif reporting_frequency =~ /runperiod|environment|annual/i
297
+ needs_runperiodvariable = true
298
+ end
299
+ end
300
+
301
+ # turn off the requests if the meter is already a variable
302
+ variables = idf.getObjectsByType('Output:Variable'.to_IddObjectType)
303
+ variables.each do |variable|
304
+ reporting_frequency = variable.getString(2, true)
305
+ if reporting_frequency =~ /detailed/i
306
+ needs_detailedvariable = false
307
+ elsif reporting_frequency =~ /hourly/i
308
+ needs_hourlyvariable = false
309
+ elsif reporting_frequency =~ /daily/i
310
+ needs_dailyvariable = false
311
+ elsif reporting_frequency =~ /runperiod|environment|annual/i
312
+ needs_runperiodvariable = false
313
+ end
314
+ end
315
+
316
+ if needs_sqlobj
317
+ @logger.info 'Adding SQL Output to IDF'
318
+ new_objects << '
319
+ Output:SQLite,
320
+ SimpleAndTabular; ! Option Type
321
+ '
322
+ end
323
+
324
+ if needs_monthlyoutput
325
+ monthly_report_idf = File.join(File.dirname(__FILE__), 'monthly_report.idf')
326
+
327
+ idf_file = OpenStudio::IdfFile.load(File.read(monthly_report_idf), 'EnergyPlus'.to_IddFileType).get
328
+ idf.addObjects(idf_file.objects)
329
+ end
330
+
331
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Detailed;' if needs_detailedvariable
332
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Hourly;' if needs_hourlyvariable
333
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Daily;' if needs_dailyvariable
334
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,RunPeriod;' if needs_runperiodvariable
335
+
336
+ # These are supposedly needed for the calibration report
337
+ new_objects << 'Output:Meter:MeterFileOnly,Gas:Facility,Daily;'
338
+ new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Timestep;'
339
+ new_objects << 'Output:Meter:MeterFileOnly,Electricity:Facility,Daily;'
340
+ new_objects << 'Output:Variable,*,Zone Air Temperature,Hourly;'
341
+ new_objects << 'Output:Variable,*,Zone Air Relative Humidity,Hourly;'
342
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Monthly;'
343
+ new_objects << 'Output:Variable,*,Site Outdoor Air Drybulb Temperature,Timestep;'
344
+
345
+ # Always add in the timestep facility meters
346
+ new_objects << 'Output:Meter,Electricity:Facility,Timestep;'
347
+ new_objects << 'Output:Meter,Gas:Facility,Timestep;'
348
+ new_objects << 'Output:Meter,DistrictCooling:Facility,Timestep;'
349
+ new_objects << 'Output:Meter,DistrictHeating:Facility,Timestep;'
350
+
351
+ new_objects.each do |obj|
352
+ object = OpenStudio::IdfObject.load(obj).get
353
+ idf.addObject(object)
354
+ end
355
+
356
+ # save the file
357
+ File.open(idf_filename, 'w') { |f| f << idf.to_s }
358
+
359
+ @logger.info 'Finished EnergyPlus Preprocess'
360
+ end
250
361
  end