urbanopt-scenario 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/CONTRIBUTING.md +58 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/pull_request_template.md +23 -0
- data/.gitignore +26 -0
- data/.rdoc_options +36 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +43 -0
- data/Jenkinsfile +10 -0
- data/LICENSE.md +27 -0
- data/RDOC_MAIN.md +39 -0
- data/README.md +39 -0
- data/Rakefile +51 -0
- data/deploy_docs.sh +5 -0
- data/doc_templates/LICENSE.md +27 -0
- data/doc_templates/README.md.erb +42 -0
- data/doc_templates/copyright_erb.txt +31 -0
- data/doc_templates/copyright_js.txt +4 -0
- data/doc_templates/copyright_ruby.txt +29 -0
- data/docs/.gitignore +3 -0
- data/docs/.vuepress/components/InnerJsonSchema.vue +84 -0
- data/docs/.vuepress/components/JsonSchema.vue +12 -0
- data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
- data/docs/.vuepress/components/StaticLink.vue +8 -0
- data/docs/.vuepress/config.js +15 -0
- data/docs/.vuepress/highlight.js +8 -0
- data/docs/.vuepress/public/custom_rdoc_styles.css +74 -0
- data/docs/.vuepress/utils.js +17 -0
- data/docs/README.md +39 -0
- data/docs/package-lock.json +11817 -0
- data/docs/package.json +26 -0
- data/docs/schemas/scenario-schema.md +3 -0
- data/lib/change_log.rb +147 -0
- data/lib/measures/.rubocop.yml +5 -0
- data/lib/measures/default_feature_reports/LICENSE.md +27 -0
- data/lib/measures/default_feature_reports/README.md +56 -0
- data/lib/measures/default_feature_reports/README.md.erb +42 -0
- data/lib/measures/default_feature_reports/measure.rb +742 -0
- data/lib/measures/default_feature_reports/measure.xml +139 -0
- data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
- data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +238 -0
- data/lib/measures/default_feature_reports/tests/example_model.osm +4378 -0
- data/lib/urbanopt-scenario.rb +31 -0
- data/lib/urbanopt/scenario.rb +45 -0
- data/lib/urbanopt/scenario/default_reports.rb +40 -0
- data/lib/urbanopt/scenario/default_reports/construction_cost.rb +169 -0
- data/lib/urbanopt/scenario/default_reports/date.rb +97 -0
- data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +187 -0
- data/lib/urbanopt/scenario/default_reports/end_use.rb +159 -0
- data/lib/urbanopt/scenario/default_reports/end_uses.rb +140 -0
- data/lib/urbanopt/scenario/default_reports/feature_report.rb +213 -0
- data/lib/urbanopt/scenario/default_reports/generator.rb +92 -0
- data/lib/urbanopt/scenario/default_reports/location.rb +99 -0
- data/lib/urbanopt/scenario/default_reports/logger.rb +44 -0
- data/lib/urbanopt/scenario/default_reports/program.rb +261 -0
- data/lib/urbanopt/scenario/default_reports/reporting_period.rb +298 -0
- data/lib/urbanopt/scenario/default_reports/scenario_report.rb +300 -0
- data/lib/urbanopt/scenario/default_reports/schema/README.md +34 -0
- data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +13 -0
- data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +830 -0
- data/lib/urbanopt/scenario/default_reports/solar_pv.rb +92 -0
- data/lib/urbanopt/scenario/default_reports/storage.rb +105 -0
- data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +258 -0
- data/lib/urbanopt/scenario/default_reports/validator.rb +97 -0
- data/lib/urbanopt/scenario/default_reports/wind.rb +92 -0
- data/lib/urbanopt/scenario/extension.rb +63 -0
- data/lib/urbanopt/scenario/logger.rb +42 -0
- data/lib/urbanopt/scenario/scenario_base.rb +79 -0
- data/lib/urbanopt/scenario/scenario_csv.rb +122 -0
- data/lib/urbanopt/scenario/scenario_datapoint_base.rb +162 -0
- data/lib/urbanopt/scenario/scenario_post_processor_base.rb +69 -0
- data/lib/urbanopt/scenario/scenario_post_processor_default.rb +98 -0
- data/lib/urbanopt/scenario/scenario_runner_base.rb +63 -0
- data/lib/urbanopt/scenario/scenario_runner_osw.rb +158 -0
- data/lib/urbanopt/scenario/simulation_dir_base.rb +90 -0
- data/lib/urbanopt/scenario/simulation_dir_osw.rb +261 -0
- data/lib/urbanopt/scenario/simulation_mapper_base.rb +47 -0
- data/lib/urbanopt/scenario/version.rb +35 -0
- data/urbanopt-scenario-gem.gemspec +38 -0
- metadata +251 -0
@@ -0,0 +1,162 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
module URBANopt
|
32
|
+
module Scenario
|
33
|
+
class ScenarioDatapoint
|
34
|
+
attr_reader :scenario, :feature_id, :feature_name, :mapper_class #:nodoc:#
|
35
|
+
|
36
|
+
##
|
37
|
+
# ScenarioDatapoint is an agnostic description of the simulation of a Feature in a Scenario
|
38
|
+
# A Simulation Mapper will map the
|
39
|
+
##
|
40
|
+
# [parameters:]
|
41
|
+
# +scenario+ - _ScenarioBase_ - Scenario containing this ScenarioDatapoint.
|
42
|
+
# +feature_id+ - _String_ - Unique id of the feature for this ScenarioDatapoint.
|
43
|
+
# +feature_name+ - _String_ - Human readable name of the feature for this ScenarioDatapoint.
|
44
|
+
# +mapper_class+ - _String_ - Name of Ruby class used to translate feature to simulation OSW.
|
45
|
+
def initialize(scenario, feature_id, feature_name, mapper_class)
|
46
|
+
@scenario = scenario
|
47
|
+
@feature_id = feature_id
|
48
|
+
@feature_name = feature_name
|
49
|
+
@feature = scenario.feature_file.get_feature_by_id(feature_id)
|
50
|
+
@mapper_class = mapper_class
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_reader :feature #:nodoc:
|
54
|
+
|
55
|
+
##
|
56
|
+
# Gets the type of a feature
|
57
|
+
##
|
58
|
+
def feature_type
|
59
|
+
@feature.feature_type
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Return the directory that this datapoint will run in.
|
64
|
+
##
|
65
|
+
# [return:] _String_ - Directory that this datapoint will run in.
|
66
|
+
def run_dir
|
67
|
+
raise 'Feature ID not set' if @feature_id.nil?
|
68
|
+
raise 'Scenario run dir not set' if @scenario.run_dir.nil?
|
69
|
+
return File.join(@scenario.run_dir, @feature_id + '/')
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Return the directory that this datapoint will run in.
|
74
|
+
def clear
|
75
|
+
dir = run_dir
|
76
|
+
FileUtils.rm_rf(dir) if File.exist?(dir)
|
77
|
+
FileUtils.mkdir_p(dir) if !File.exist?(dir)
|
78
|
+
end
|
79
|
+
|
80
|
+
# rubocop: disable Security/Eval #:nodoc:
|
81
|
+
# rubocop: disable Style/EvalWithLocation #:nodoc:
|
82
|
+
# Disable Sceurity/Eval since there is no user input #:nodoc:
|
83
|
+
|
84
|
+
##
|
85
|
+
# Create run directory and generate simulation OSW, all previous contents of directory are removed
|
86
|
+
# The simulation OSW is created by evaluating the mapper_class's create_osw method
|
87
|
+
##
|
88
|
+
# [return:] _String_ - Path to the simulation OSW.
|
89
|
+
##
|
90
|
+
def create_osw
|
91
|
+
osw = eval("#{@mapper_class}.new.create_osw(@scenario, @feature_id, @feature_name)")
|
92
|
+
dir = run_dir
|
93
|
+
FileUtils.rm_rf(dir) if File.exist?(dir)
|
94
|
+
FileUtils.mkdir_p(dir) if !File.exist?(dir)
|
95
|
+
osw_path = File.join(dir, 'in.osw')
|
96
|
+
File.open(osw_path, 'w') do |f|
|
97
|
+
f << JSON.pretty_generate(osw)
|
98
|
+
# make sure data is written to the disk one way or the other
|
99
|
+
begin
|
100
|
+
f.fsync
|
101
|
+
rescue StandardError
|
102
|
+
f.flush
|
103
|
+
end
|
104
|
+
end
|
105
|
+
return osw_path
|
106
|
+
end
|
107
|
+
# rubocop: enable Security/Eval #:nodoc:
|
108
|
+
# rubocop: enable Style/EvalWithLocation #:nodoc:
|
109
|
+
|
110
|
+
##
|
111
|
+
# Return true if the datapoint is out of date, false otherwise. Non-existant files are out of date.
|
112
|
+
##
|
113
|
+
# [return:] _Boolean_ - True if the datapoint is out of date, false otherwise.
|
114
|
+
def out_of_date?
|
115
|
+
dir = run_dir
|
116
|
+
if !File.exist?(dir)
|
117
|
+
return true
|
118
|
+
end
|
119
|
+
|
120
|
+
out_osw = File.join(dir, 'out.osw')
|
121
|
+
if !File.exist?(out_osw)
|
122
|
+
return true
|
123
|
+
end
|
124
|
+
out_osw_time = File.mtime(out_osw)
|
125
|
+
|
126
|
+
# array of files that this datapoint depends on
|
127
|
+
dependencies = []
|
128
|
+
|
129
|
+
# depends on the feature file
|
130
|
+
dependencies << scenario.feature_file.path
|
131
|
+
|
132
|
+
# depends on the csv file
|
133
|
+
dependencies << scenario.csv_file
|
134
|
+
|
135
|
+
# depends on the mapper classes
|
136
|
+
Dir.glob(File.join(scenario.mapper_files_dir, '*')).each do |f|
|
137
|
+
dependencies << f
|
138
|
+
end
|
139
|
+
|
140
|
+
# depends on the root gemfile
|
141
|
+
dependencies << File.join(scenario.root_dir, 'Gemfile')
|
142
|
+
dependencies << File.join(scenario.root_dir, 'Gemfile.lock')
|
143
|
+
|
144
|
+
# todo, depends on all the measures?
|
145
|
+
|
146
|
+
# check if out of date
|
147
|
+
dependencies.each do |f|
|
148
|
+
if File.exist?(f)
|
149
|
+
if File.mtime(f) > out_osw_time
|
150
|
+
puts "File '#{f}' is newer than '#{out_osw}', datapoint out of date"
|
151
|
+
return true
|
152
|
+
end
|
153
|
+
else
|
154
|
+
puts "Dependency file '#{f}' does not exist"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
return false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
module URBANopt
|
32
|
+
module Scenario
|
33
|
+
class ScenarioPostProcessorBase
|
34
|
+
##
|
35
|
+
# ScenarioPostProcessorBase post-processes a Scenario to create scenario level results.
|
36
|
+
##
|
37
|
+
# [parameters:]
|
38
|
+
# +scenario_base+ - _ScenarioBase_ - An object of ScenarioBase class.
|
39
|
+
def initialize(scenario_base)
|
40
|
+
@scenario_base = scenario_base
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :scenario_base
|
44
|
+
|
45
|
+
##
|
46
|
+
# Run the post processor on this Scenario.
|
47
|
+
##
|
48
|
+
def run
|
49
|
+
raise 'run not implemented for ScenarioPostProcessorBase, override in your class'
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Add results from a simulation_dir to this result.
|
54
|
+
##
|
55
|
+
# [parameters:]
|
56
|
+
# +simulation_dir+ - _SimulationDirOSW_ - An object on SimulationDirOSW class.
|
57
|
+
def add_simulation_dir(simulation_dir)
|
58
|
+
raise 'add_simulation_dir not implemented for ScenarioPostProcessorBase, override in your class'
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Save scenario result.
|
63
|
+
##
|
64
|
+
def save
|
65
|
+
raise 'save not implemented for ScenarioPostProcessorBase, override in your class'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
require 'urbanopt/scenario/scenario_post_processor_base'
|
32
|
+
require 'urbanopt/scenario/default_reports'
|
33
|
+
require 'urbanopt/scenario/default_reports/logger'
|
34
|
+
|
35
|
+
require 'csv'
|
36
|
+
require 'json'
|
37
|
+
require 'fileutils'
|
38
|
+
|
39
|
+
module URBANopt
|
40
|
+
module Scenario
|
41
|
+
class ScenarioDefaultPostProcessor < ScenarioPostProcessorBase
|
42
|
+
##
|
43
|
+
# ScenarioPostProcessorBase post-processes a scenario to create scenario level results
|
44
|
+
##
|
45
|
+
# [parameters:]
|
46
|
+
# +scenario_base+ - _ScenarioBase_ - An object of ScenarioBase class.
|
47
|
+
def initialize(scenario_base)
|
48
|
+
super(scenario_base)
|
49
|
+
|
50
|
+
initialization_hash = { directory_name: scenario_base.run_dir, name: scenario_base.name, id: scenario_base.name }
|
51
|
+
@scenario_result = URBANopt::Scenario::DefaultReports::ScenarioReport.new(initialization_hash)
|
52
|
+
|
53
|
+
@@logger ||= URBANopt::Scenario::DefaultReports.logger
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Run the post processor on this Scenario.This will add all the simulation_dirs.
|
58
|
+
##
|
59
|
+
def run
|
60
|
+
# this run method adds all the simulation_dirs, you can extend it to do more custom stuff
|
61
|
+
@scenario_base.simulation_dirs.each do |simulation_dir|
|
62
|
+
add_simulation_dir(simulation_dir)
|
63
|
+
end
|
64
|
+
return @scenario_result
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Add results from a simulation_dir to this result.
|
69
|
+
##
|
70
|
+
# [parameters:]
|
71
|
+
# +simulation_dir+ - _SimulationDirOSW_ - An object on SimulationDirOSW class.
|
72
|
+
def add_simulation_dir(simulation_dir)
|
73
|
+
feature_reports = URBANopt::Scenario::DefaultReports::FeatureReport.from_simulation_dir(simulation_dir)
|
74
|
+
|
75
|
+
feature_reports.each do |feature_report|
|
76
|
+
if feature_report.to_hash[:simulation_status] == 'Complete'
|
77
|
+
@scenario_result.add_feature_report(feature_report)
|
78
|
+
else
|
79
|
+
@@logger.error("Feature #{feature_report.id} failed to run!")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
return feature_reports
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Save scenario result
|
88
|
+
##
|
89
|
+
# [parameters:]
|
90
|
+
# +file_name+ - _String_ - Assign a name to the saved scenario results file
|
91
|
+
def save(file_name = 'default_scenario_report')
|
92
|
+
@scenario_result.save
|
93
|
+
|
94
|
+
return @scenario_result
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
module URBANopt
|
32
|
+
module Scenario
|
33
|
+
class ScenarioRunnerBase
|
34
|
+
##
|
35
|
+
# ScenarioRunnerBase is the agnostic interface for a class which can create and run SimulationFiles.
|
36
|
+
##
|
37
|
+
def initialize; end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Create all SimulationDirs for Scenario.
|
41
|
+
##
|
42
|
+
# [parameters:]
|
43
|
+
# +scenario+ - _ScenarioBase_ - Scenario to create simulation input files for scenario.
|
44
|
+
# +force_clear+ - _Bool_ - Clear Scenario before creating simulation input files
|
45
|
+
# [return:] _Array_ Returns an array of all SimulationDirs, even those created previously, for Scenario.
|
46
|
+
def create_simulation_files(scenario, force_clear = false)
|
47
|
+
raise 'create_input_files is not implemented for ScenarioRunnerBase, override in your class'
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Create and run all SimulationFiles for Scenario.
|
52
|
+
##
|
53
|
+
# [parameters:]
|
54
|
+
# +scenario+ - _ScenarioBase_ - Scenario to create and run simulation input files for.
|
55
|
+
# +force_clear+ - _Bool_ - Clear Scenario before creating Simulation input files.
|
56
|
+
#
|
57
|
+
# [return:] _Array_ Returns an array of all SimulationDirs, even those created previously, for Scenario.
|
58
|
+
def run(scenario, force_clear = false)
|
59
|
+
raise 'run is not implemented for ScenarioRunnerBase, override in your class'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
|
3
|
+
# contributors. All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without modification,
|
6
|
+
# are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# Redistributions of source code must retain the above copyright notice, this list
|
9
|
+
# of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# Redistributions in binary form must reproduce the above copyright notice, this
|
12
|
+
# list of conditions and the following disclaimer in the documentation and/or other
|
13
|
+
# materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# Neither the name of the copyright holder nor the names of its contributors may be
|
16
|
+
# used to endorse or promote products derived from this software without specific
|
17
|
+
# prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
20
|
+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
22
|
+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
23
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
24
|
+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
25
|
+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
27
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
28
|
+
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
|
+
# *********************************************************************************
|
30
|
+
|
31
|
+
require 'urbanopt/scenario/scenario_runner_base'
|
32
|
+
require 'json'
|
33
|
+
|
34
|
+
require 'fileutils'
|
35
|
+
# require 'hash_parser'
|
36
|
+
|
37
|
+
module URBANopt
|
38
|
+
module Scenario
|
39
|
+
class ScenarioRunnerOSW < ScenarioRunnerBase
|
40
|
+
##
|
41
|
+
# ScenarioRunnerOSW is a class to create and run SimulationFileOSWs
|
42
|
+
##
|
43
|
+
def initialize; end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Create all OSWs for Scenario.
|
47
|
+
##
|
48
|
+
# [parameters:]
|
49
|
+
# +scenario+ - _ScenarioBase_ - Scenario to create simulation input files for.
|
50
|
+
# +force_clear+ - _Bool_ - Clear Scenario before creating simulation input files.
|
51
|
+
# [return:] _Array_ Returns array of all SimulationDirs, even those created previously, for Scenario.
|
52
|
+
def create_simulation_files(scenario, force_clear = false)
|
53
|
+
if force_clear
|
54
|
+
scenario.clear
|
55
|
+
end
|
56
|
+
|
57
|
+
FileUtils.mkdir_p(scenario.run_dir) if !File.exist?(scenario.run_dir)
|
58
|
+
|
59
|
+
simulation_dirs = scenario.simulation_dirs
|
60
|
+
|
61
|
+
simulation_dirs.each do |simulation_dir|
|
62
|
+
if simulation_dir.out_of_date?
|
63
|
+
puts "simulation_dir #{simulation_dir.run_dir} is out of date, regenerating input files"
|
64
|
+
simulation_dir.create_input_files
|
65
|
+
end
|
66
|
+
end
|
67
|
+
return simulation_dirs
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Create and run all SimulationFileOSW for Scenario.
|
72
|
+
# A staged runner is implented to run buildings, then transformers then district systems.
|
73
|
+
# - instantiate openstudio runner to run .osw files.
|
74
|
+
# - create simulation files for this scenario.
|
75
|
+
# - get feature_type value from in.osw files
|
76
|
+
# - cretae 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+)
|
77
|
+
# - add each osw file to its corresponding group id +simulation_dir+ is out_of_date
|
78
|
+
# - Run osw file groups in order and store simulation failure in a array.
|
79
|
+
##
|
80
|
+
# [parameters:]
|
81
|
+
# +scenario+ - _ScenarioBase_ - Scenario to create and run SimulationFiles for.
|
82
|
+
# +force_clear+ - _Bool_ - Clear Scenario before creating SimulationFiles.
|
83
|
+
# [return:] _Array_ Returns array of all SimulationFiles, even those created previously, for Scenario.
|
84
|
+
def run(scenario, force_clear = false)
|
85
|
+
# instantiate openstudio runner - use the defaults for now. If need to change then create
|
86
|
+
# the runner.conf file (i.e. run `rake openstudio:runner:init`)
|
87
|
+
runner = OpenStudio::Extension::Runner.new(scenario.root_dir)
|
88
|
+
|
89
|
+
# create simulation files
|
90
|
+
simulation_dirs = create_simulation_files(scenario, force_clear)
|
91
|
+
|
92
|
+
# osws = []
|
93
|
+
# simulation_dirs.each do |simulation_dir|
|
94
|
+
# if !simulation_dir.is_a?(SimulationDirOSW)
|
95
|
+
# raise "ScenarioRunnerOSW does not know how to run #{simulation_dir.class}"
|
96
|
+
# end
|
97
|
+
# if simulation_dir.out_of_date?
|
98
|
+
# osws << simulation_dir.in_osw_path
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
|
102
|
+
# cretae 3 groups to store .osw files (+building_osws+ , +transformer_osws+ , +district_system_osws+)
|
103
|
+
building_osws = []
|
104
|
+
transformer_osws = []
|
105
|
+
district_system_osws = []
|
106
|
+
|
107
|
+
simulation_dirs.each do |simulation_dir|
|
108
|
+
in_osw = File.read(simulation_dir.in_osw_path)
|
109
|
+
in_osw_hash = JSON.parse(in_osw, symbolize_names: true)
|
110
|
+
|
111
|
+
if !simulation_dir.is_a?(SimulationDirOSW)
|
112
|
+
raise "ScenarioRunnerOSW does not know how to run #{simulation_dir.class}"
|
113
|
+
end
|
114
|
+
|
115
|
+
# get feature_type value from in.osw files
|
116
|
+
feature_type = nil
|
117
|
+
in_osw_hash[:steps].each { |x| feature_type = x[:arguments][:feature_type] if x[:arguments][:feature_type] }
|
118
|
+
|
119
|
+
# add each osw file to its corresponding group id +simulation_dir+ is out_of_date
|
120
|
+
if simulation_dir.out_of_date?
|
121
|
+
|
122
|
+
if feature_type == 'Building'
|
123
|
+
building_osws << simulation_dir.in_osw_path
|
124
|
+
elsif feature_type == 'District System'
|
125
|
+
district_system_osws << simulation_dir.in_osw_path
|
126
|
+
elsif feature_type == 'Transformer'
|
127
|
+
transformer_osws << simulation_dir.in_osw_path
|
128
|
+
else
|
129
|
+
raise "ScenarioRunnerOSW does not know how to run a #{feature_type} feature"
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Run osw groups in order and store simulation failure in a array.
|
136
|
+
# Return simulation_dirs after running all simulations.
|
137
|
+
|
138
|
+
# failures
|
139
|
+
failures = []
|
140
|
+
# run building_osws
|
141
|
+
# building_failures = runner.run_osws(building_osws, num_parallel = Extension::NUM_PARALLEL, max_to_run = Extension::MAX_DATAPOINTS)
|
142
|
+
building_failures = runner.run_osws(building_osws)
|
143
|
+
failures << building_failures
|
144
|
+
# run district_system_osws
|
145
|
+
# district_system_failures = runner.run_osws(district_system_osws, num_parallel = Extension::NUM_PARALLEL, max_to_run = Extension::MAX_DATAPOINTS)
|
146
|
+
district_system_failures = runner.run_osws(district_system_osws)
|
147
|
+
failures << district_system_failures
|
148
|
+
# run transformer_osws
|
149
|
+
# transformer_failures = runner.run_osws(transformer_osws, num_parallel = Extension::NUM_PARALLEL, max_to_run = Extension::MAX_DATAPOINTS)
|
150
|
+
transformer_failures = runner.run_osws(transformer_osws)
|
151
|
+
failures << transformer_failures
|
152
|
+
|
153
|
+
# puts "failures = #{failures}"
|
154
|
+
return simulation_dirs
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|