urbanopt-scenario 0.2.0 → 0.4.2

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.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.github/pull_request_template.md +2 -2
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +53 -0
  6. data/CONTRIBUTING.md +1 -1
  7. data/Gemfile +27 -14
  8. data/Jenkinsfile +1 -1
  9. data/LICENSE.md +1 -1
  10. data/RDOC_MAIN.md +1 -1
  11. data/README.md +1 -1
  12. data/Rakefile +2 -2
  13. data/docs/README.md +1 -1
  14. data/docs/package-lock.json +2499 -2322
  15. data/docs/package.json +13 -9
  16. data/lib/urbanopt-scenario.rb +1 -1
  17. data/lib/urbanopt/scenario.rb +2 -1
  18. data/lib/urbanopt/scenario/default_reports.rb +3 -8
  19. data/lib/urbanopt/scenario/extension.rb +1 -1
  20. data/lib/urbanopt/scenario/logger.rb +1 -1
  21. data/lib/urbanopt/scenario/scenario_base.rb +1 -1
  22. data/lib/urbanopt/scenario/scenario_csv.rb +22 -9
  23. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +8 -1
  24. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +1 -1
  25. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +110 -8
  26. data/lib/urbanopt/scenario/scenario_post_processor_opendss.rb +6 -7
  27. data/lib/urbanopt/scenario/scenario_runner_base.rb +2 -2
  28. data/lib/urbanopt/scenario/scenario_runner_osw.rb +23 -9
  29. data/lib/urbanopt/scenario/scenario_visualization.rb +236 -0
  30. data/lib/urbanopt/scenario/simulation_dir_base.rb +1 -1
  31. data/lib/urbanopt/scenario/simulation_dir_osw.rb +2 -9
  32. data/lib/urbanopt/scenario/simulation_mapper_base.rb +1 -1
  33. data/lib/urbanopt/scenario/version.rb +2 -2
  34. data/package-lock.json +3 -0
  35. data/urbanopt-scenario-gem.gemspec +14 -14
  36. metadata +71 -77
  37. data/doc_templates/LICENSE.md +0 -27
  38. data/doc_templates/README.md.erb +0 -42
  39. data/doc_templates/copyright_erb.txt +0 -31
  40. data/doc_templates/copyright_js.txt +0 -4
  41. data/doc_templates/copyright_ruby.txt +0 -29
  42. data/lib/change_log.rb +0 -147
  43. data/lib/measures/.rubocop.yml +0 -5
  44. data/lib/measures/default_feature_reports/LICENSE.md +0 -27
  45. data/lib/measures/default_feature_reports/README.md +0 -56
  46. data/lib/measures/default_feature_reports/README.md.erb +0 -42
  47. data/lib/measures/default_feature_reports/measure.rb +0 -979
  48. data/lib/measures/default_feature_reports/measure.xml +0 -143
  49. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +0 -8768
  50. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +0 -238
  51. data/lib/measures/default_feature_reports/tests/example_model.osm +0 -4378
  52. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +0 -169
  53. data/lib/urbanopt/scenario/default_reports/date.rb +0 -97
  54. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +0 -379
  55. data/lib/urbanopt/scenario/default_reports/end_use.rb +0 -159
  56. data/lib/urbanopt/scenario/default_reports/end_uses.rb +0 -140
  57. data/lib/urbanopt/scenario/default_reports/feature_report.rb +0 -267
  58. data/lib/urbanopt/scenario/default_reports/generator.rb +0 -92
  59. data/lib/urbanopt/scenario/default_reports/location.rb +0 -99
  60. data/lib/urbanopt/scenario/default_reports/logger.rb +0 -44
  61. data/lib/urbanopt/scenario/default_reports/power_distribution.rb +0 -102
  62. data/lib/urbanopt/scenario/default_reports/program.rb +0 -266
  63. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +0 -301
  64. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +0 -317
  65. data/lib/urbanopt/scenario/default_reports/schema/README.md +0 -33
  66. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +0 -32
  67. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +0 -853
  68. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +0 -93
  69. data/lib/urbanopt/scenario/default_reports/storage.rb +0 -105
  70. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +0 -299
  71. data/lib/urbanopt/scenario/default_reports/validator.rb +0 -97
  72. data/lib/urbanopt/scenario/default_reports/wind.rb +0 -92
@@ -10,17 +10,21 @@
10
10
  },
11
11
  "author": "NREL",
12
12
  "dependencies": {
13
- "highlight.js": "^9.15.6",
14
- "json-schema-ref-parser": "^6.1.0",
13
+ "highlight.js": "^10.2.0",
14
+ "json-schema-ref-parser": "^9.0.6",
15
15
  "json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
16
- "vuepress": "^1.2.0",
17
- "webpack-dev-middleware": "^3.6.0"
16
+ "vuepress": "^1.5.4",
17
+ "webpack-dev-middleware": "^3.7.2"
18
18
  },
19
19
  "devDependencies": {
20
- "braces": ">=2.3.1",
21
- "gh-pages": "^2.0.1",
22
- "js-yaml": ">=3.13.1",
23
- "serialize-javascript": ">=2.1.1",
24
- "set-value": ">=2.0.1"
20
+ "braces": "^3.0.2",
21
+ "dot-prop": "^5.3.0",
22
+ "gh-pages": "^3.1.0",
23
+ "js-yaml": "^3.14.0",
24
+ "minimist": ">=1.2.3",
25
+ "node-forge": ">=0.10.0",
26
+ "serialize-javascript": "^5.0.1",
27
+ "set-value": "^3.0.2",
28
+ "yargs-parser": ">=18.1.1"
25
29
  }
26
30
  }
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -42,5 +42,6 @@ require 'urbanopt/scenario/scenario_runner_osw'
42
42
  require 'urbanopt/scenario/simulation_dir_base'
43
43
  require 'urbanopt/scenario/simulation_dir_osw'
44
44
  require 'urbanopt/scenario/simulation_mapper_base'
45
+ require 'urbanopt/scenario/scenario_visualization'
45
46
 
46
47
  require 'urbanopt/scenario/default_reports'
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -31,10 +31,5 @@
31
31
  ##
32
32
  # Retrieve all default_reports classes.
33
33
  ##
34
- require 'urbanopt/scenario/default_reports/construction_cost'
35
- require 'urbanopt/scenario/default_reports/feature_report'
36
- require 'urbanopt/scenario/default_reports/logger'
37
- require 'urbanopt/scenario/default_reports/program'
38
- require 'urbanopt/scenario/default_reports/reporting_period'
39
- require 'urbanopt/scenario/default_reports/scenario_report'
40
- require 'urbanopt/scenario/default_reports/timeseries_csv'
34
+
35
+ require 'urbanopt/reporting/default_reports'
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -52,7 +52,6 @@ module URBANopt
52
52
 
53
53
  def initialize(name, root_dir, run_dir, feature_file, mapper_files_dir, csv_file, num_header_rows)
54
54
  super(name, root_dir, run_dir, feature_file)
55
-
56
55
  @mapper_files_dir = mapper_files_dir
57
56
  @csv_file = csv_file
58
57
  @num_header_rows = num_header_rows
@@ -73,13 +72,27 @@ module URBANopt
73
72
 
74
73
  # Require all simulation mappers in mapper_files_dir
75
74
  def load_mapper_files
76
- Dir.glob(File.join(@mapper_files_dir, '/*.rb')).each do |f|
77
- begin
78
- require(f)
79
- rescue LoadError => e
80
- @@logger.error(e.message)
81
- raise
82
- end
75
+ dirs = Dir.glob(File.join(@mapper_files_dir, '/*.rb'))
76
+ # order is not guaranteed...attempt to add Baseline first, then High Efficiency
77
+ ordered_dirs = []
78
+ bindex = dirs.find_index { |i| i.include? 'Baseline.rb' }
79
+ if bindex
80
+ ordered_dirs << dirs[bindex]
81
+ dirs.delete_at(bindex)
82
+ end
83
+ hindex = dirs.find_index { |i| i.include? 'HighEfficiency.rb' }
84
+ if hindex
85
+ ordered_dirs << dirs[hindex] if hindex
86
+ dirs.delete_at(hindex)
87
+ end
88
+ # then the rest
89
+ ordered_dirs += dirs
90
+
91
+ ordered_dirs.each do |f|
92
+ require(f)
93
+ rescue LoadError => e
94
+ @@logger.error(e.message)
95
+ raise
83
96
  end
84
97
  end
85
98
 
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -59,6 +59,13 @@ module URBANopt
59
59
  @feature.feature_type
60
60
  end
61
61
 
62
+ ##
63
+ # Gets the type of a feature
64
+ ##
65
+ def feature_location
66
+ @feature.feature_location
67
+ end
68
+
62
69
  ##
63
70
  # Return the directory that this datapoint will run in.
64
71
  ##
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -29,12 +29,12 @@
29
29
  # *********************************************************************************
30
30
 
31
31
  require 'urbanopt/scenario/scenario_post_processor_base'
32
- require 'urbanopt/scenario/default_reports'
33
- require 'urbanopt/scenario/default_reports/logger'
32
+ require 'urbanopt/reporting/default_reports'
34
33
 
35
34
  require 'csv'
36
35
  require 'json'
37
36
  require 'fileutils'
37
+ require 'sqlite3'
38
38
 
39
39
  module URBANopt
40
40
  module Scenario
@@ -47,10 +47,11 @@ module URBANopt
47
47
  def initialize(scenario_base)
48
48
  super(scenario_base)
49
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)
50
+ @initialization_hash = { directory_name: scenario_base.run_dir, name: scenario_base.name, id: scenario_base.name, root_dir: scenario_base.root_dir }
51
+ @scenario_result = URBANopt::Reporting::DefaultReports::ScenarioReport.new(@initialization_hash)
52
+ @default_save_name = 'default_scenario_report'
52
53
 
53
- @@logger ||= URBANopt::Scenario::DefaultReports.logger
54
+ @@logger ||= URBANopt::Reporting::DefaultReports.logger
54
55
  end
55
56
 
56
57
  ##
@@ -70,7 +71,7 @@ module URBANopt
70
71
  # [parameters:]
71
72
  # +simulation_dir+ - _SimulationDirOSW_ - An object on SimulationDirOSW class.
72
73
  def add_simulation_dir(simulation_dir)
73
- feature_reports = URBANopt::Scenario::DefaultReports::FeatureReport.from_simulation_dir(simulation_dir)
74
+ feature_reports = URBANopt::Reporting::DefaultReports::FeatureReport.from_simulation_dir(simulation_dir)
74
75
 
75
76
  feature_reports.each do |feature_report|
76
77
  if feature_report.to_hash[:simulation_status] == 'Complete'
@@ -83,12 +84,113 @@ module URBANopt
83
84
  return feature_reports
84
85
  end
85
86
 
87
+ # Create database file with scenario-level results
88
+ # Sum values for each timestep across all features. Save to new table in a new database
89
+ def create_scenario_db_file(file_name = @default_save_name)
90
+ new_db_file = File.join(@initialization_hash[:directory_name], "#{file_name}.db")
91
+ scenario_db = SQLite3::Database.open new_db_file
92
+ scenario_db.execute "CREATE TABLE IF NOT EXISTS ReportData(
93
+ TimeIndex INTEGER,
94
+ Year VARCHAR(255),
95
+ Month VARCHAR(255),
96
+ Day VARCHAR(255),
97
+ Hour VARCHAR(255),
98
+ Minute VARCHAR(255),
99
+ Dst INTEGER,
100
+ ReportDataDictionaryIndex INTEGER,
101
+ Value INTEGER
102
+ )"
103
+
104
+ values_arr = []
105
+ feature_list = Pathname.new(@initialization_hash[:directory_name]).children.select(&:directory?) # Folders in the run/scenario directory
106
+
107
+ # get scenario CSV
108
+ scenario_csv = File.join(@initialization_hash[:root_dir], @initialization_hash[:name] + '.csv')
109
+ if File.exist?(scenario_csv)
110
+ # csv found
111
+ feature_ids = CSV.read(scenario_csv, headers: true)
112
+ feature_list = []
113
+ # loop through building feature ids from scenario csv
114
+ feature_ids['Feature Id'].each do |feature|
115
+ if Dir.exist?(File.join(@initialization_hash[:directory_name], feature))
116
+ feature_list << File.join(@initialization_hash[:directory_name], feature)
117
+ else
118
+ puts "warning: did not find a directory for datapoint #{feature}...skipping"
119
+ end
120
+ end
121
+ else
122
+ raise "Couldn't find scenario CSV: #{scenario_csv}"
123
+ end
124
+ feature_1_name = File.basename(feature_list[0]) # Get name of first feature, so we can read eplusout.sql from there
125
+ uo_output_sql_file = File.join(@initialization_hash[:directory_name], feature_1_name, 'eplusout.sql')
126
+ feature_list.each do |feature| # Loop through each feature in the scenario
127
+ feature_db = SQLite3::Database.open uo_output_sql_file
128
+ # Doing "db.results_as_hash = true" is prettier, but in this case significantly slower.
129
+
130
+ # RDDI == 10 is the timestep value for facility electricity in OS 3.0.1
131
+ # TODO: Dynamically read RDDI from table RDDI, insted of hardcoding it
132
+ elec_query = feature_db.query "SELECT ReportData.TimeIndex, Time.Year, Time.Month, Time.Day, Time.Hour, Time.Minute, Time.Dst, ReportData.Value
133
+ FROM ReportData
134
+ INNER JOIN Time ON Time.TimeIndex=ReportData.TimeIndex
135
+ WHERE ReportDataDictionaryIndex == 10
136
+ ORDER BY ReportData.TimeIndex"
137
+
138
+ elec_query.each do |row| # Add up all the values for electricity usage across all Features at this timestep
139
+ # row[0] == TimeIndex, row[1] == Value
140
+
141
+ arr_match = values_arr.find { |v| v[:time_index] == row[0] }
142
+ if arr_match.nil?
143
+ # add new row to value_arr
144
+ values_arr << { time_index: row[0], year: row[1], month: row[2], day: row[3], hour: row[4], minute: row[5], dst: row[6], elec_val: Float(row[7]), gas_val: 0 }
145
+ else
146
+ # running sum
147
+ arr_match[:elec_val] += Float(row[7])
148
+ end
149
+ end # End elec_query
150
+ elec_query.close
151
+
152
+ # RDDI == 1382 is the timestep value for facility gas in OS 3.0.1
153
+ # TODO: Dynamically read RDDI from table RDDI, insted of hardcoding it
154
+ gas_query = feature_db.query "SELECT ReportData.TimeIndex, Time.Year, Time.Month, Time.Day, Time.Hour, Time.Minute, Time.Dst, ReportData.Value
155
+ FROM ReportData
156
+ INNER JOIN Time ON Time.TimeIndex=ReportData.TimeIndex
157
+ WHERE ReportDataDictionaryIndex == 1382
158
+ ORDER BY ReportData.TimeIndex"
159
+
160
+ gas_query.each do |row|
161
+ # row[0] == TimeIndex, row[1] == Value
162
+ arr_match = values_arr.find { |v| v[:time_index] == row[0] }
163
+ if arr_match.nil?
164
+ # add new row to value_arr
165
+ values_arr << { time_index: row[0], year: row[1], month: row[2], day: row[3], hour: row[4], minute: row[5], dst: row[6], gas_val: Float(row[7]), elec_val: 0 }
166
+ else
167
+ # running sum
168
+ arr_match[:gas_val] += Float(row[7])
169
+ end
170
+ end # End gas_query
171
+ gas_query.close
172
+ feature_db.close
173
+ end # End feature_list loop
174
+
175
+ elec_sql = []
176
+ gas_sql = []
177
+ values_arr.each do |i|
178
+ elec_sql << "(#{i[:time_index]}, #{i[:year]}, #{i[:month]}, #{i[:day]}, #{i[:hour]}, #{i[:minute]}, #{i[:dst]}, 10, #{i[:elec_val]})"
179
+ gas_sql << "(#{i[:time_index]}, #{i[:year]}, #{i[:month]}, #{i[:day]}, #{i[:hour]}, #{i[:minute]}, #{i[:dst]}, 1382, #{i[:gas_val]})"
180
+ end
181
+
182
+ # Put summed Values into the database
183
+ scenario_db.execute("INSERT INTO ReportData VALUES #{elec_sql.join(', ')}")
184
+ scenario_db.execute("INSERT INTO ReportData VALUES #{gas_sql.join(', ')}")
185
+ scenario_db.close
186
+ end
187
+
86
188
  ##
87
189
  # Save scenario result
88
190
  ##
89
191
  # [parameters:]
90
192
  # +file_name+ - _String_ - Assign a name to the saved scenario results file
91
- def save(file_name = 'default_scenario_report')
193
+ def save(file_name = @default_save_name)
92
194
  @scenario_result.save
93
195
 
94
196
  return @scenario_result
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -29,8 +29,7 @@
29
29
  # *********************************************************************************
30
30
 
31
31
  # require 'urbanopt/scenario/scenario_post_processor_base'
32
- require 'urbanopt/scenario/default_reports'
33
- require 'urbanopt/scenario/default_reports/logger'
32
+ require 'urbanopt/reporting/default_reports'
34
33
 
35
34
  require 'csv'
36
35
  require 'json'
@@ -64,7 +63,7 @@ module URBANopt
64
63
  @feature_reports_data = {}
65
64
 
66
65
  # initialize logger
67
- @@logger ||= URBANopt::Scenario::DefaultReports.logger
66
+ @@logger ||= URBANopt::Reporting::DefaultReports.logger
68
67
  end
69
68
 
70
69
  # load opendss data
@@ -166,9 +165,9 @@ module URBANopt
166
165
  File.write(File.join(transformer_dir, 'feature_reports', 'default_feature_report_opendss' + '.csv'), transformer_csv)
167
166
 
168
167
  # create transformer report
169
- transformer_report = URBANopt::Scenario::DefaultReports::FeatureReport.new(id: k, name: k, directory_name: transformer_dir, feature_type: 'Transformer',
170
- timesteps_per_hour: @scenario_report.timesteps_per_hour,
171
- simulation_status: 'complete')
168
+ transformer_report = URBANopt::Reporting::DefaultReports::FeatureReport.new(id: k, name: k, directory_name: transformer_dir, feature_type: 'Transformer',
169
+ timesteps_per_hour: @scenario_report.timesteps_per_hour,
170
+ simulation_status: 'complete')
172
171
 
173
172
  # assign results to transfomrer report
174
173
  transformer_report.power_distribution.over_voltage_hours = over_voltage_hrs
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -55,7 +55,7 @@ module URBANopt
55
55
  # +force_clear+ - _Bool_ - Clear Scenario before creating Simulation input files.
56
56
  #
57
57
  # [return:] _Array_ Returns an array of all SimulationDirs, even those created previously, for Scenario.
58
- def run(scenario, force_clear = false)
58
+ def run(scenario, force_clear = false, options = {})
59
59
  raise 'run is not implemented for ScenarioRunnerBase, override in your class'
60
60
  end
61
61
  end
@@ -1,5 +1,5 @@
1
1
  # *********************************************************************************
2
- # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
2
+ # URBANopt (tm), Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
3
  # contributors. All rights reserved.
4
4
  #
5
5
  # Redistribution and use in source and binary forms, with or without modification,
@@ -55,6 +55,7 @@ module URBANopt
55
55
  end
56
56
 
57
57
  FileUtils.mkdir_p(scenario.run_dir) if !File.exist?(scenario.run_dir)
58
+ FileUtils.rm_rf(File.join(scenario.run_dir, 'run_status.json')) if File.exist?(File.join(scenario.run_dir, 'run_status.json'))
58
59
 
59
60
  simulation_dirs = scenario.simulation_dirs
60
61
 
@@ -81,10 +82,11 @@ module URBANopt
81
82
  # +scenario+ - _ScenarioBase_ - Scenario to create and run SimulationFiles for.
82
83
  # +force_clear+ - _Bool_ - Clear Scenario before creating SimulationFiles.
83
84
  # [return:] _Array_ Returns array of all SimulationFiles, even those created previously, for Scenario.
84
- def run(scenario, force_clear = false)
85
+ def run(scenario, force_clear = false, options = {})
85
86
  # instantiate openstudio runner - use the defaults for now. If need to change then create
86
87
  # the runner.conf file (i.e. run `rake openstudio:runner:init`)
87
- runner = OpenStudio::Extension::Runner.new(scenario.root_dir)
88
+ # allow passing gemfile_path and bundle_install_path in options
89
+ runner = OpenStudio::Extension::Runner.new(scenario.root_dir, [], options)
88
90
 
89
91
  # create simulation files
90
92
  simulation_dirs = create_simulation_files(scenario, force_clear)
@@ -156,18 +158,30 @@ module URBANopt
156
158
  # puts "DATAPOINT FAILURES: #{failures}"
157
159
  # end
158
160
 
159
- # look for other failed datapoints
161
+ # write results to file and to command line
162
+ get_results(scenario, simulation_dirs)
163
+
164
+ return simulation_dirs
165
+ end
166
+
167
+ def get_results(scenario, simulation_dirs)
168
+ # look for other failed datapoints (command line display)
169
+ # also compile datapoint status for latest_run.json file
170
+ status_arr = []
160
171
  failed_sims = []
161
- simulation_dirs.each do |simulation_dir|
162
- if File.exist?(File.join(simulation_dir.run_dir, 'failed.job'))
163
- failed_sims << simulation_dir.run_dir.split('/')[-1]
172
+ simulation_dirs.each do |sim_dir|
173
+ if File.exist?(sim_dir.failed_job_path)
174
+ failed_sims << sim_dir.run_dir.split('/')[-1]
164
175
  end
176
+ status_arr << { "id": sim_dir.feature_id, "status": sim_dir.simulation_status, "mapper_class": sim_dir.mapper_class }
165
177
  end
178
+
179
+ # write to file
180
+ File.open(File.join(scenario.run_dir, 'run_status.json'), 'w') { |f| f.write JSON.pretty_generate("timestamp": Time.now.strftime('%Y-%m-%dT%k:%M:%S.%L'), "results": status_arr) }
181
+
166
182
  if !failed_sims.empty?
167
183
  puts "FAILED SIMULATION IDs: #{failed_sims.join(',')}"
168
184
  end
169
-
170
- return simulation_dirs
171
185
  end
172
186
  end
173
187
  end