urbanopt-scenario 0.1.0
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/.gitignore +25 -0
- data/.rdoc_options +36 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +42 -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 +11791 -0
- data/docs/package.json +22 -0
- data/docs/schemas/scenario-schema.md +3 -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 +731 -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/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 +207 -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 +276 -0
- data/lib/urbanopt/scenario/default_reports/schema/README.md +33 -0
- data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +13 -0
- data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +742 -0
- data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +231 -0
- data/lib/urbanopt/scenario/default_reports/validator.rb +97 -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 +97 -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 +36 -0
- metadata +227 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019, 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, 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
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019, 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 SimulationDirBase
|
34
|
+
##
|
35
|
+
# SimulationDirBase is the agnostic representation of a directory of simulation input files.
|
36
|
+
##
|
37
|
+
# [parameters:]
|
38
|
+
# +scenario+ - _ScenarioBase_ - Scenario containing this SimulationDirBase.
|
39
|
+
# +features+ - _Array_ - Array of Features that this SimulationDirBase represents.
|
40
|
+
# +feature_names+ - _Array_ - Array of scenario specific names for these Features.
|
41
|
+
def initialize(scenario, features, feature_names)
|
42
|
+
@scenario = scenario
|
43
|
+
@features = features
|
44
|
+
@feature_names = feature_names
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :scenario #:nodoc:
|
48
|
+
|
49
|
+
attr_reader :features #:nodoc:
|
50
|
+
|
51
|
+
attr_reader :feature_names #:nodoc:
|
52
|
+
|
53
|
+
##
|
54
|
+
# Return the directory that this simulation will run in
|
55
|
+
##
|
56
|
+
def run_dir
|
57
|
+
raise 'run_dir is not implemented for SimulationFileBase, override in your class'
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Return true if the simulation is out of date (input files newer than results), false otherwise.
|
62
|
+
# Non-existant simulation input files are out of date.
|
63
|
+
##
|
64
|
+
def out_of_date?
|
65
|
+
raise 'out_of_date? is not implemented for SimulationFileBase, override in your class'
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Returns simulation status one of {'Not Started', 'Started', 'Complete', 'Failed'}
|
70
|
+
##
|
71
|
+
def simulation_status
|
72
|
+
raise 'simulation_status is not implemented for SimulationFileBase, override in your class'
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Clear the directory that this simulation runs in
|
77
|
+
##
|
78
|
+
def clear
|
79
|
+
raise 'clear is not implemented for SimulationFileBase, override in your class'
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Create run directory and generate simulation inputs, all previous contents of directory are removed
|
84
|
+
##
|
85
|
+
def create_input_files
|
86
|
+
raise 'create_input_files is not implemented for SimulationFileBase, override in your class'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
# *********************************************************************************
|
2
|
+
# URBANopt, Copyright (c) 2019, 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/simulation_dir_base'
|
32
|
+
|
33
|
+
module URBANopt
|
34
|
+
module Scenario
|
35
|
+
class SimulationDirOSW < SimulationDirBase
|
36
|
+
##
|
37
|
+
# SimulationDirOSW creates a OSW file to simulate features, a SimulationMapperBase is invoked to translate features to OSW.
|
38
|
+
##
|
39
|
+
# [parameters:]
|
40
|
+
# +scenario+ - _ScenarioBase_ - Scenario containing this SimulationFileBase.
|
41
|
+
# +features+ - _Array_ - Array of Features this SimulationFile represents.
|
42
|
+
# +feature_names+ - _Array_ - Array of scenario specific names for these Features.
|
43
|
+
# +mapper_class+ - _String_ - Name of class derived frmo SimulationMapperBase used to translate feature to simulation OSW.
|
44
|
+
def initialize(scenario, features, feature_names, mapper_class)
|
45
|
+
super(scenario, features, feature_names)
|
46
|
+
|
47
|
+
if features.size != 1
|
48
|
+
raise 'SimulationDirOSW currently cannot simulate more than one feature'
|
49
|
+
end
|
50
|
+
|
51
|
+
@feature = features[0]
|
52
|
+
@feature_id = @feature.id
|
53
|
+
|
54
|
+
if feature_names.size == 1
|
55
|
+
@feature_name = feature_names[0]
|
56
|
+
else
|
57
|
+
@feature_name = @feature.name
|
58
|
+
end
|
59
|
+
|
60
|
+
@mapper_class = mapper_class
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :mapper_class
|
64
|
+
|
65
|
+
##
|
66
|
+
# Return the directory that this simulation will run in.
|
67
|
+
##
|
68
|
+
def run_dir
|
69
|
+
raise 'Feature ID not set' if @feature_id.nil?
|
70
|
+
raise 'Scenario run dir not set' if scenario.run_dir.nil?
|
71
|
+
return File.join(scenario.run_dir, @feature_id + '/')
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Return the input OSW path
|
76
|
+
##
|
77
|
+
def in_osw_path
|
78
|
+
return File.join(run_dir, 'in.osw')
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Return the input OSW
|
83
|
+
##
|
84
|
+
def in_osw
|
85
|
+
result = nil
|
86
|
+
if File.exist?(in_osw_path)
|
87
|
+
File.open(in_osw_path, 'r') do |f|
|
88
|
+
result = JSON.parse(f.read, symbolize_names: true)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
return result
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Return the started.job path
|
96
|
+
##
|
97
|
+
def started_job_path
|
98
|
+
return File.join(run_dir, 'started.job')
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Return the failed.job path
|
103
|
+
##
|
104
|
+
def failed_job_path
|
105
|
+
return File.join(run_dir, 'failed.job')
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Return the finished.job path
|
110
|
+
##
|
111
|
+
def finished_job_path
|
112
|
+
return File.join(run_dir, 'finished.job')
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Return the output OSW path
|
117
|
+
##
|
118
|
+
def out_osw_path
|
119
|
+
return File.join(run_dir, 'out.osw')
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# Return the output OSW
|
124
|
+
##
|
125
|
+
def out_osw
|
126
|
+
result = nil
|
127
|
+
if File.exist?(out_osw_path)
|
128
|
+
File.open(out_osw_path, 'r') do |f|
|
129
|
+
result = JSON.parse(f.read, symbolize_names: true)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return result
|
133
|
+
end
|
134
|
+
|
135
|
+
# rubocop: disable Metrics/AbcSize #:nodoc:
|
136
|
+
|
137
|
+
##
|
138
|
+
# Return true if the simulation is out of date (input files newer than results), false otherwise.
|
139
|
+
# Non-existant simulation input files are out of date.
|
140
|
+
##
|
141
|
+
def out_of_date?
|
142
|
+
if !File.exist?(run_dir)
|
143
|
+
puts "run_dir '#{run_dir}' does not exist, simulation dir '#{run_dir}' out of date"
|
144
|
+
return true
|
145
|
+
end
|
146
|
+
|
147
|
+
if !File.exist?(finished_job_path)
|
148
|
+
puts "finished_job_path '#{finished_job_path}' does not exist, simulation dir '#{run_dir}' out of date"
|
149
|
+
return true
|
150
|
+
end
|
151
|
+
|
152
|
+
if !File.exist?(out_osw_path)
|
153
|
+
puts "out_osw_path '#{out_osw_path}' does not exist, simulation dir '#{run_dir}' out of date"
|
154
|
+
return true
|
155
|
+
end
|
156
|
+
out_osw_time = File.mtime(out_osw_path)
|
157
|
+
|
158
|
+
# array of files that this simulation dir depends on
|
159
|
+
dependencies = []
|
160
|
+
out_of_date_files = []
|
161
|
+
|
162
|
+
# depends on the in.osw
|
163
|
+
dependencies << in_osw_path
|
164
|
+
|
165
|
+
# depends on the feature file
|
166
|
+
dependencies << scenario.feature_file.path
|
167
|
+
|
168
|
+
# depends on the csv file
|
169
|
+
dependencies << scenario.csv_file
|
170
|
+
|
171
|
+
# depends on the mapper classes
|
172
|
+
Dir.glob(File.join(scenario.mapper_files_dir, '*')).each do |f|
|
173
|
+
dependencies << f
|
174
|
+
end
|
175
|
+
|
176
|
+
# depends on the root gemfile
|
177
|
+
dependencies << File.join(scenario.root_dir, 'Gemfile')
|
178
|
+
dependencies << File.join(scenario.root_dir, 'Gemfile.lock')
|
179
|
+
|
180
|
+
# todo, read in the in.osw and depend on all the measures
|
181
|
+
|
182
|
+
# check if out of date
|
183
|
+
dependencies.each do |f|
|
184
|
+
if File.exist?(f)
|
185
|
+
if File.mtime(f) > out_osw_time
|
186
|
+
out_of_date_files << f
|
187
|
+
end
|
188
|
+
else
|
189
|
+
puts "Dependency file '#{f}' does not exist"
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
if !out_of_date_files.empty?
|
194
|
+
puts "Files [#{out_of_date_files.join(',')}] are newer than '#{out_osw_path}', simulation dir '#{run_dir}' out of date"
|
195
|
+
return true
|
196
|
+
end
|
197
|
+
|
198
|
+
return false
|
199
|
+
end
|
200
|
+
# rubocop: enable Metrics/AbcSize #:nodoc:
|
201
|
+
|
202
|
+
# rubocop: disable Style/GuardClause #:nodoc:
|
203
|
+
|
204
|
+
##
|
205
|
+
# Return simulation status one of {'Not Started', 'Started', 'Complete', 'Failed'}
|
206
|
+
##
|
207
|
+
def simulation_status
|
208
|
+
if File.exist?(failed_job_path)
|
209
|
+
return 'Failed'
|
210
|
+
elsif File.exist?(started_job_path)
|
211
|
+
if File.exist?(finished_job_path)
|
212
|
+
return 'Complete'
|
213
|
+
else
|
214
|
+
return 'Failed'
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
return 'Not Started'
|
219
|
+
end
|
220
|
+
# rubocop: enable Style/GuardClause #:nodoc:
|
221
|
+
|
222
|
+
##
|
223
|
+
# Clear the directory that this simulation runs in
|
224
|
+
##
|
225
|
+
def clear
|
226
|
+
dir = run_dir
|
227
|
+
FileUtils.mkdir_p(dir) if !File.exist?(dir)
|
228
|
+
Dir.glob(File.join(dir, '/*')).each do |f|
|
229
|
+
FileUtils.rm_rf(f)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# rubocop: disable Security/Eval #:nodoc:
|
234
|
+
# rubocop: disable Style/EvalWithLocation #:nodoc:
|
235
|
+
|
236
|
+
##
|
237
|
+
# Create run directory and generate simulation OSW, all previous contents of directory are removed
|
238
|
+
# The simulation OSW is created by evaluating the mapper_class's create_osw method
|
239
|
+
##
|
240
|
+
def create_input_files
|
241
|
+
clear
|
242
|
+
|
243
|
+
dir = run_dir
|
244
|
+
osw = eval("#{@mapper_class}.new.create_osw(scenario, features, feature_names)")
|
245
|
+
osw_path = File.join(dir, 'in.osw')
|
246
|
+
File.open(osw_path, 'w') do |f|
|
247
|
+
f << JSON.pretty_generate(osw)
|
248
|
+
# make sure data is written to the disk one way or the other
|
249
|
+
begin
|
250
|
+
f.fsync
|
251
|
+
rescue StandardError
|
252
|
+
f.flush
|
253
|
+
end
|
254
|
+
end
|
255
|
+
return osw_path
|
256
|
+
end
|
257
|
+
# rubocop: enable Security/Eval #:nodoc:
|
258
|
+
# rubocop: enable Style/EvalWithLocation #:nodoc:
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|