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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -1
- data/README.md +24 -63
- data/lib/openstudio/extended_runner.rb +94 -0
- data/lib/openstudio/workflow/adapter.rb +10 -0
- data/lib/openstudio/workflow/adapters/mongo.rb +1 -1
- data/lib/openstudio/workflow/jobs/lib/apply_measures.rb +12 -17
- data/lib/openstudio/workflow/jobs/{run_openstudio → run_energyplus}/monthly_report.idf +8 -4
- data/lib/openstudio/workflow/jobs/run_energyplus/run_energyplus.rb +132 -21
- data/lib/openstudio/workflow/jobs/run_openstudio/run_openstudio.rb +6 -11
- data/lib/openstudio/workflow/jobs/run_postprocess/run_postprocess.rb +7 -6
- data/lib/openstudio/workflow/jobs/run_preflight/run_preflight.rb +2 -1
- data/lib/openstudio/workflow/jobs/run_reporting_measures/run_reporting_measures.rb +27 -148
- data/lib/openstudio/workflow/jobs/run_runmanager/run_runmanager.rb +31 -10
- data/lib/openstudio/workflow/jobs/run_xml/run_xml.rb +4 -3
- data/lib/openstudio/workflow/run.rb +4 -5
- data/lib/openstudio/workflow/version.rb +1 -1
- data/lib/openstudio-workflow.rb +6 -10
- metadata +9 -12
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/README.md +0 -5
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.rb +0 -206
- data/lib/openstudio/workflow/jobs/run_reporting_measures/packaged_measures/StandardReports/measure.xml +0 -53
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 859f53e5f54c14eee213cff7b0bdd7a6bc9d4c98
|
4
|
+
data.tar.gz: b58de6c2993630809e26a27bf735fcac371280cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
80
|
-
* ~~Add xml workflow item~~
|
69
|
+
* Hook up the measure group based workflows
|
81
70
|
|
82
|
-
## Testing
|
71
|
+
## Testing
|
83
72
|
|
84
|
-
|
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
|
-
|
75
|
+
### Locally
|
87
76
|
|
88
|
-
|
77
|
+
```
|
78
|
+
rake
|
79
|
+
```
|
89
80
|
|
90
|
-
|
81
|
+
### Docker
|
91
82
|
|
92
|
-
|
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
|
-
|
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)
|
@@ -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 =
|
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
|
151
|
-
|
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
|
-
|
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
|
-
|
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-
|
129
|
-
|
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
|
-
|
140
|
+
return 'C:/EnergyPlus-8-3-0'
|
134
141
|
else
|
135
|
-
|
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) =~
|
168
|
-
@expand_objects_exe = File.basename(dest_file) if File.basename(dest_file) =~
|
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
|
173
|
-
fail "Could not find ExpandObjects
|
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
|