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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CONTRIBUTING.md +58 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  5. data/.github/pull_request_template.md +23 -0
  6. data/.gitignore +26 -0
  7. data/.rdoc_options +36 -0
  8. data/.rspec +3 -0
  9. data/.rubocop.yml +10 -0
  10. data/.travis.yml +23 -0
  11. data/CHANGELOG.md +19 -0
  12. data/Gemfile +43 -0
  13. data/Jenkinsfile +10 -0
  14. data/LICENSE.md +27 -0
  15. data/RDOC_MAIN.md +39 -0
  16. data/README.md +39 -0
  17. data/Rakefile +51 -0
  18. data/deploy_docs.sh +5 -0
  19. data/doc_templates/LICENSE.md +27 -0
  20. data/doc_templates/README.md.erb +42 -0
  21. data/doc_templates/copyright_erb.txt +31 -0
  22. data/doc_templates/copyright_js.txt +4 -0
  23. data/doc_templates/copyright_ruby.txt +29 -0
  24. data/docs/.gitignore +3 -0
  25. data/docs/.vuepress/components/InnerJsonSchema.vue +84 -0
  26. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  27. data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
  28. data/docs/.vuepress/components/StaticLink.vue +8 -0
  29. data/docs/.vuepress/config.js +15 -0
  30. data/docs/.vuepress/highlight.js +8 -0
  31. data/docs/.vuepress/public/custom_rdoc_styles.css +74 -0
  32. data/docs/.vuepress/utils.js +17 -0
  33. data/docs/README.md +39 -0
  34. data/docs/package-lock.json +11817 -0
  35. data/docs/package.json +26 -0
  36. data/docs/schemas/scenario-schema.md +3 -0
  37. data/lib/change_log.rb +147 -0
  38. data/lib/measures/.rubocop.yml +5 -0
  39. data/lib/measures/default_feature_reports/LICENSE.md +27 -0
  40. data/lib/measures/default_feature_reports/README.md +56 -0
  41. data/lib/measures/default_feature_reports/README.md.erb +42 -0
  42. data/lib/measures/default_feature_reports/measure.rb +742 -0
  43. data/lib/measures/default_feature_reports/measure.xml +139 -0
  44. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
  45. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +238 -0
  46. data/lib/measures/default_feature_reports/tests/example_model.osm +4378 -0
  47. data/lib/urbanopt-scenario.rb +31 -0
  48. data/lib/urbanopt/scenario.rb +45 -0
  49. data/lib/urbanopt/scenario/default_reports.rb +40 -0
  50. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +169 -0
  51. data/lib/urbanopt/scenario/default_reports/date.rb +97 -0
  52. data/lib/urbanopt/scenario/default_reports/distributed_generation.rb +187 -0
  53. data/lib/urbanopt/scenario/default_reports/end_use.rb +159 -0
  54. data/lib/urbanopt/scenario/default_reports/end_uses.rb +140 -0
  55. data/lib/urbanopt/scenario/default_reports/feature_report.rb +213 -0
  56. data/lib/urbanopt/scenario/default_reports/generator.rb +92 -0
  57. data/lib/urbanopt/scenario/default_reports/location.rb +99 -0
  58. data/lib/urbanopt/scenario/default_reports/logger.rb +44 -0
  59. data/lib/urbanopt/scenario/default_reports/program.rb +261 -0
  60. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +298 -0
  61. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +300 -0
  62. data/lib/urbanopt/scenario/default_reports/schema/README.md +34 -0
  63. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +13 -0
  64. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +830 -0
  65. data/lib/urbanopt/scenario/default_reports/solar_pv.rb +92 -0
  66. data/lib/urbanopt/scenario/default_reports/storage.rb +105 -0
  67. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +258 -0
  68. data/lib/urbanopt/scenario/default_reports/validator.rb +97 -0
  69. data/lib/urbanopt/scenario/default_reports/wind.rb +92 -0
  70. data/lib/urbanopt/scenario/extension.rb +63 -0
  71. data/lib/urbanopt/scenario/logger.rb +42 -0
  72. data/lib/urbanopt/scenario/scenario_base.rb +79 -0
  73. data/lib/urbanopt/scenario/scenario_csv.rb +122 -0
  74. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +162 -0
  75. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +69 -0
  76. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +98 -0
  77. data/lib/urbanopt/scenario/scenario_runner_base.rb +63 -0
  78. data/lib/urbanopt/scenario/scenario_runner_osw.rb +158 -0
  79. data/lib/urbanopt/scenario/simulation_dir_base.rb +90 -0
  80. data/lib/urbanopt/scenario/simulation_dir_osw.rb +261 -0
  81. data/lib/urbanopt/scenario/simulation_mapper_base.rb +47 -0
  82. data/lib/urbanopt/scenario/version.rb +35 -0
  83. data/urbanopt-scenario-gem.gemspec +38 -0
  84. metadata +251 -0
@@ -0,0 +1,92 @@
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 'json'
32
+ require 'json-schema'
33
+
34
+ module URBANopt
35
+ module Scenario
36
+ module DefaultReports
37
+ ##
38
+ # Onsite solar PV system attributes
39
+ ##
40
+ class SolarPV
41
+ ##
42
+ # _Float_ - power capacity in kilowatts
43
+ #
44
+ attr_accessor :size_kw
45
+
46
+ ##
47
+ # Initialize SolarPV attributes from a hash. Solar PV attributes currently are limited to power capacity.
48
+ ##
49
+ # [parameters:]
50
+ #
51
+ # * +hash+ - _Hash_ - A hash containting a +:size_kw+ key/value pair which represents the nameplate capacity in kilowatts (kW)
52
+ #
53
+ def initialize(hash = {})
54
+ hash.delete_if { |k, v| v.nil? }
55
+
56
+ @size_kw = hash[:size_kw]
57
+
58
+ # initialize class variables @@validator and @@schema
59
+ @@validator ||= Validator.new
60
+ @@schema ||= @@validator.schema
61
+
62
+ # initialize @@logger
63
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
64
+ end
65
+
66
+ ##
67
+ # Convert to a Hash equivalent for JSON serialization
68
+ ##
69
+ def to_hash
70
+ result = {}
71
+
72
+ result[:size_kw] = @size_kw if @size_kw
73
+
74
+ return result
75
+ end
76
+
77
+ ##
78
+ # Merge PV systems
79
+ ##
80
+ def self.add_pv(existing_pv, new_pv)
81
+ if existing_pv.size_kw.nil? && new_pv.size_kw.nil?
82
+ existing_pv.size_kw = nil
83
+ else
84
+ existing_pv.size_kw = (existing_pv.size_kw || 0) + (new_pv.size_kw || 0)
85
+ end
86
+
87
+ return existing_pv
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,105 @@
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 'json'
32
+ require 'json-schema'
33
+
34
+ module URBANopt
35
+ module Scenario
36
+ module DefaultReports
37
+ ##
38
+ # Onsite storage system attributes
39
+ ##
40
+ class Storage
41
+ ##
42
+ # _Float_ - power capacity in kilowatts
43
+ #
44
+ attr_accessor :size_kw
45
+
46
+ ##
47
+ # _Float_ - storage capacity in kilowatt-hours
48
+ #
49
+ attr_accessor :size_kwh
50
+
51
+ ##
52
+ # Initialize Storage attributes from a hash. Storage attributes currently are limited to power and storage capacity.
53
+ ##
54
+ # [parameters:]
55
+ #
56
+ # * +hash+ - _Hash_ - A hash containting +:size_kw+ and +:size_kwh+ key/value pair which represents the power and storage capacity in kilowatts (kW) and kilowatt-hours respectively.
57
+ #
58
+ def initialize(hash = {})
59
+ hash.delete_if { |k, v| v.nil? }
60
+
61
+ @size_kw = hash[:size_kw]
62
+ @size_kwh = hash[:size_kwh]
63
+
64
+ # initialize class variables @@validator and @@schema
65
+ @@validator ||= Validator.new
66
+ @@schema ||= @@validator.schema
67
+
68
+ # initialize @@logger
69
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
70
+ end
71
+
72
+ ##
73
+ # Convert to a Hash equivalent for JSON serialization
74
+ ##
75
+ def to_hash
76
+ result = {}
77
+
78
+ result[:size_kw] = @size_kw if @size_kw
79
+ result[:size_kwh] = @size_kwh if @size_kwh
80
+
81
+ return result
82
+ end
83
+
84
+ ##
85
+ # Merge Storage systems
86
+ ##
87
+ def self.add_storage(existing_storage, new_storage)
88
+ if existing_storage.size_kw.nil?
89
+ existing_storage.size_kw = new_storage.size_kw
90
+ else
91
+ existing_storage.size_kw = (existing_storage.size_kw || 0) + (new_storage.size_kw || 0)
92
+ end
93
+
94
+ if existing_storage.size_kw.nil?
95
+ existing_storage.size_kwh = new_storage.size_kwh
96
+ else
97
+ existing_storage.size_kwh = (existing_storage.size_kwh || 0) + (new_storage.size_kwh || 0)
98
+ end
99
+
100
+ return existing_storage
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,258 @@
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 'csv'
32
+ require 'pathname'
33
+ require 'json-schema'
34
+ require 'urbanopt/scenario/default_reports/validator'
35
+ require 'urbanopt/scenario/default_reports/logger'
36
+
37
+ module URBANopt
38
+ module Scenario
39
+ module DefaultReports
40
+ ##
41
+ # TimeseriesCSV include timesries reults reported in a CSV file.
42
+ ##
43
+ class TimeseriesCSV
44
+ attr_accessor :path, :first_report_datetime, :column_names #:nodoc:
45
+
46
+ ##
47
+ # TimeseriesCSV class initializes timeseries csv attributes: +:path+ , +:first_report_datetime+ , +:column_names+
48
+ ##
49
+ # +hash+ - _Hash_ - A hash which may contain a deserialized timeseries_csv.
50
+ ##
51
+ def initialize(hash = {})
52
+ hash.delete_if { |k, v| v.nil? }
53
+ hash = defaults.merge(hash)
54
+
55
+ @run_dir = ''
56
+
57
+ @path = hash[:path]
58
+ @first_report_datetime = hash[:first_report_datetime]
59
+ @column_names = hash[:column_names]
60
+
61
+ # hash of column_name to array of values, does not get serialized to hash
62
+ @mutex = Mutex.new
63
+ @data = nil
64
+
65
+ # initialize class variables @@validator and @@schema
66
+ @@validator ||= Validator.new
67
+ @@schema ||= @@validator.schema
68
+
69
+ # initialize @@logger
70
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
71
+ end
72
+
73
+ ##
74
+ # Assigns default values if values does not exist.
75
+ ##
76
+ def defaults
77
+ hash = {}
78
+ hash[:path] = nil
79
+ hash[:column_names] = []
80
+ return hash
81
+ end
82
+
83
+ ##
84
+ # Gets run directory.
85
+ ##
86
+ # [parameters:]
87
+ # +name+ - _String_ - The name of the scenario (+directory_name+).
88
+ ##
89
+ def run_dir_name(name)
90
+ @run_dir = name
91
+ end
92
+
93
+ ##
94
+ # Converts to a Hash equivalent for JSON serialization.
95
+ ##
96
+ # - Exclude attributes with nil values.
97
+ # - Validate reporting_period hash properties against schema.
98
+ ##
99
+ def to_hash
100
+ result = {}
101
+ directory_path = Pathname.new File.expand_path(@run_dir.to_s, File.dirname(__FILE__)) if @run_dir
102
+ csv_path = Pathname.new @path if @path
103
+
104
+ relative_path = csv_path.to_s.sub(directory_path.to_s, '')
105
+
106
+ result[:path] = relative_path if @path
107
+ result[:first_report_datetime] = @first_report_datetime if @first_report_datetime
108
+ result[:column_names] = @column_names if @column_names
109
+
110
+ # validate timeseries_csv properties against schema
111
+ if @@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result).any?
112
+ raise "scenario_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:TimeseriesCSV][:properties], result)}"
113
+ end
114
+
115
+ return result
116
+ end
117
+
118
+ ##
119
+ # Reloads data from the CSV file.
120
+ ##
121
+ def reload_data(new_data)
122
+ @mutex.synchronize do
123
+ @data = {}
124
+ @column_names = []
125
+ new_data.each do |row|
126
+ if @column_names.empty?
127
+ @column_names = row
128
+ @column_names.each do |column_name|
129
+ @data[column_name] = []
130
+ end
131
+ else
132
+ row.each_with_index do |value, i|
133
+ @data[@column_names[i]] << value.to_f
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ ##
141
+ # Loads data from the CSV file.
142
+ ##
143
+ def load_data
144
+ @mutex.synchronize do
145
+ if @data.nil?
146
+ @data = {}
147
+ @column_names = []
148
+ CSV.foreach(@path) do |row|
149
+ if @column_names.empty?
150
+ @column_names = row
151
+ @column_names.each do |column_name|
152
+ @data[column_name] = []
153
+ end
154
+ else
155
+ row.each_with_index do |value, i|
156
+ @data[@column_names[i]] << value.to_f
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ ##
165
+ # Gets data for each column name in the CSV file.
166
+ ##
167
+ # [parameters:]
168
+ # +column_name+ - _String_ - The header of each column in the CSV file.
169
+ ##
170
+ def get_data(column_name)
171
+ load_data
172
+ return @data[column_name]
173
+ end
174
+
175
+ ##
176
+ # Saves data to the the scenario report CSV file.
177
+ ##
178
+ # [parameters:]
179
+ # +path+ - _String_ - The path of the scenario report CSV (default_scenario_report.csv).
180
+ ##
181
+ def save_data(path = nil)
182
+ if path.nil?
183
+ path = @path
184
+ end
185
+ File.open(path, 'w') do |f|
186
+ f.puts @column_names.join(',')
187
+ n = @data[@column_names[0]].size - 1
188
+
189
+ (0..n).each do |i|
190
+ line = []
191
+ @column_names.each do |column_name|
192
+ line << @data[column_name][i]
193
+ end
194
+ f.puts line.join(',')
195
+ end
196
+ begin
197
+ f.fsync
198
+ rescue StandardError
199
+ f.flush
200
+ end
201
+ end
202
+ end
203
+
204
+ ##
205
+ # Merges timeseries csv to each other.
206
+ ##
207
+ # - initialize first_report_datetime with the incoming first_report_datetime if its nil.
208
+ # - checks if first_report_datetime are identical.
209
+ # - merge the column names
210
+ # - merge the column data
211
+ ##
212
+ # [parameters:]
213
+ # +other+ - _TimeseriesCSV_ - An object of TimeseriesCSV class.
214
+ ##
215
+ def add_timeseries_csv(other)
216
+ # initialize first_report_datetime with the incoming first_report_datetime if its nil.
217
+ if @first_report_datetime.nil?
218
+ @first_report_datetime = other.first_report_datetime
219
+ end
220
+
221
+ # checks if first_report_datetime are identical.
222
+ if @first_report_datetime != other.first_report_datetime
223
+ raise "first_report_datetime '#{@first_report_datetime}' does not match other.first_report_datetime '#{other.first_report_datetime}'"
224
+ end
225
+
226
+ # merge the column names
227
+ @column_names = @column_names.concat(other.column_names).uniq
228
+
229
+ # merge the column data
230
+ other.column_names.each do |column_name|
231
+ if !@column_names.include? column_name
232
+ @column_names.push column_name
233
+ end
234
+
235
+ new_values = other.get_data(column_name)
236
+
237
+ if @data.nil?
238
+ @data = {}
239
+ end
240
+
241
+ current_values = @data[column_name]
242
+ if current_values
243
+ if current_values.size != new_values.size
244
+ raise 'Values of different sizes in add_timeseries_csv'
245
+ end
246
+ new_values.each_with_index do |value, i|
247
+ new_values[i] = value + current_values[i]
248
+ end
249
+ @data[column_name] = new_values
250
+ else
251
+ @data[column_name] = new_values
252
+ end
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end