urbanopt-scenario 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +25 -0
  3. data/.rdoc_options +36 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +10 -0
  6. data/.travis.yml +23 -0
  7. data/CHANGELOG.md +5 -0
  8. data/Gemfile +42 -0
  9. data/Jenkinsfile +10 -0
  10. data/LICENSE.md +27 -0
  11. data/RDOC_MAIN.md +39 -0
  12. data/README.md +39 -0
  13. data/Rakefile +51 -0
  14. data/deploy_docs.sh +5 -0
  15. data/doc_templates/LICENSE.md +27 -0
  16. data/doc_templates/README.md.erb +42 -0
  17. data/doc_templates/copyright_erb.txt +31 -0
  18. data/doc_templates/copyright_js.txt +4 -0
  19. data/doc_templates/copyright_ruby.txt +29 -0
  20. data/docs/.gitignore +3 -0
  21. data/docs/.vuepress/components/InnerJsonSchema.vue +84 -0
  22. data/docs/.vuepress/components/JsonSchema.vue +12 -0
  23. data/docs/.vuepress/components/ScenarioSchema.vue +12 -0
  24. data/docs/.vuepress/components/StaticLink.vue +8 -0
  25. data/docs/.vuepress/config.js +15 -0
  26. data/docs/.vuepress/highlight.js +8 -0
  27. data/docs/.vuepress/public/custom_rdoc_styles.css +74 -0
  28. data/docs/.vuepress/utils.js +17 -0
  29. data/docs/README.md +39 -0
  30. data/docs/package-lock.json +11791 -0
  31. data/docs/package.json +22 -0
  32. data/docs/schemas/scenario-schema.md +3 -0
  33. data/lib/measures/.rubocop.yml +5 -0
  34. data/lib/measures/default_feature_reports/LICENSE.md +27 -0
  35. data/lib/measures/default_feature_reports/README.md +56 -0
  36. data/lib/measures/default_feature_reports/README.md.erb +42 -0
  37. data/lib/measures/default_feature_reports/measure.rb +731 -0
  38. data/lib/measures/default_feature_reports/measure.xml +139 -0
  39. data/lib/measures/default_feature_reports/tests/USA_CO_Golden-NREL.724666_TMY3.epw +8768 -0
  40. data/lib/measures/default_feature_reports/tests/default_feature_reports_test.rb +238 -0
  41. data/lib/measures/default_feature_reports/tests/example_model.osm +4378 -0
  42. data/lib/urbanopt-scenario.rb +31 -0
  43. data/lib/urbanopt/scenario.rb +45 -0
  44. data/lib/urbanopt/scenario/default_reports.rb +40 -0
  45. data/lib/urbanopt/scenario/default_reports/construction_cost.rb +169 -0
  46. data/lib/urbanopt/scenario/default_reports/date.rb +97 -0
  47. data/lib/urbanopt/scenario/default_reports/end_use.rb +159 -0
  48. data/lib/urbanopt/scenario/default_reports/end_uses.rb +140 -0
  49. data/lib/urbanopt/scenario/default_reports/feature_report.rb +207 -0
  50. data/lib/urbanopt/scenario/default_reports/location.rb +99 -0
  51. data/lib/urbanopt/scenario/default_reports/logger.rb +44 -0
  52. data/lib/urbanopt/scenario/default_reports/program.rb +261 -0
  53. data/lib/urbanopt/scenario/default_reports/reporting_period.rb +298 -0
  54. data/lib/urbanopt/scenario/default_reports/scenario_report.rb +276 -0
  55. data/lib/urbanopt/scenario/default_reports/schema/README.md +33 -0
  56. data/lib/urbanopt/scenario/default_reports/schema/scenario_csv_columns.txt +13 -0
  57. data/lib/urbanopt/scenario/default_reports/schema/scenario_schema.json +742 -0
  58. data/lib/urbanopt/scenario/default_reports/timeseries_csv.rb +231 -0
  59. data/lib/urbanopt/scenario/default_reports/validator.rb +97 -0
  60. data/lib/urbanopt/scenario/extension.rb +63 -0
  61. data/lib/urbanopt/scenario/logger.rb +42 -0
  62. data/lib/urbanopt/scenario/scenario_base.rb +79 -0
  63. data/lib/urbanopt/scenario/scenario_csv.rb +122 -0
  64. data/lib/urbanopt/scenario/scenario_datapoint_base.rb +162 -0
  65. data/lib/urbanopt/scenario/scenario_post_processor_base.rb +69 -0
  66. data/lib/urbanopt/scenario/scenario_post_processor_default.rb +97 -0
  67. data/lib/urbanopt/scenario/scenario_runner_base.rb +63 -0
  68. data/lib/urbanopt/scenario/scenario_runner_osw.rb +158 -0
  69. data/lib/urbanopt/scenario/simulation_dir_base.rb +90 -0
  70. data/lib/urbanopt/scenario/simulation_dir_osw.rb +261 -0
  71. data/lib/urbanopt/scenario/simulation_mapper_base.rb +47 -0
  72. data/lib/urbanopt/scenario/version.rb +35 -0
  73. data/urbanopt-scenario-gem.gemspec +36 -0
  74. metadata +227 -0
@@ -0,0 +1,276 @@
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/default_reports/construction_cost'
32
+ require 'urbanopt/scenario/default_reports/feature_report'
33
+ require 'urbanopt/scenario/default_reports/logger'
34
+ require 'urbanopt/scenario/default_reports/program'
35
+ require 'urbanopt/scenario/default_reports/reporting_period'
36
+ require 'urbanopt/scenario/default_reports/timeseries_csv'
37
+ require 'urbanopt/scenario/default_reports/validator'
38
+ require 'json-schema'
39
+
40
+ require 'json'
41
+ require 'pathname'
42
+
43
+ module URBANopt
44
+ module Scenario
45
+ module DefaultReports
46
+ ##
47
+ # ScenarioReport can generate two types of reports from a scenario.
48
+ # The first is a JSON format saved to 'default_scenario_report.json'.
49
+ # The second is a CSV format saved to 'default_scenario_report.csv'.
50
+ ##
51
+ class ScenarioReport
52
+ attr_accessor :id, :name, :directory_name, :timesteps_per_hour, :number_of_not_started_simulations,
53
+ :number_of_started_simulations, :number_of_complete_simulations, :number_of_failed_simulations,
54
+ :timeseries_csv, :location, :program, :construction_costs, :reporting_periods, :feature_reports # :nodoc:
55
+ # ScenarioReport class intializes the scenario report attributes:
56
+ # +:id+ , +:name+ , +:directory_name+, +:timesteps_per_hour+ , +:number_of_not_started_simulations+ ,
57
+ # +:number_of_started_simulations+ , +:number_of_complete_simulations+ , +:number_of_failed_simulations+ ,
58
+ # +:timeseries_csv+ , +:location+ , +:program+ , +:construction_costs+ , +:reporting_periods+ , +:feature_reports+
59
+ ##
60
+ # Each ScenarioReport object corresponds to a single Scenario.
61
+ ##
62
+ # [parameters:]
63
+ # +hash+ - _Hash_ - A hash of a previously serialized ScenarioReport.
64
+ ##
65
+ def initialize(hash = {})
66
+ hash.delete_if { |k, v| v.nil? }
67
+ hash = defaults.merge(hash)
68
+
69
+ @id = hash[:id]
70
+ @name = hash[:name]
71
+ @directory_name = hash[:directory_name]
72
+ @timesteps_per_hour = hash[:timesteps_per_hour]
73
+ @number_of_not_started_simulations = hash[:number_of_not_started_simulations]
74
+ @number_of_started_simulations = hash[:number_of_started_simulations]
75
+ @number_of_complete_simulations = hash[:number_of_complete_simulations]
76
+ @number_of_failed_simulations = hash[:number_of_failed_simulations]
77
+ @timeseries_csv = TimeseriesCSV.new(hash[:timeseries_csv])
78
+ @location = Location.new(hash[:location])
79
+ @program = Program.new(hash[:program])
80
+
81
+ @construction_costs = []
82
+ hash[:construction_costs].each do |cc|
83
+ @constructiion_costs << ConstructionCost.new(cc)
84
+ end
85
+
86
+ @reporting_periods = []
87
+ hash[:reporting_periods].each do |rp|
88
+ @reporting_periods << ReportingPeriod.new(rp)
89
+ end
90
+
91
+ # intialized here to be used in the add_feature_report method
92
+ @feature_reports = []
93
+ hash[:feature_reports].each do |fr|
94
+ @feature_reports << FeatureReport.new(fr)
95
+ end
96
+
97
+ # initialize class variables @@validator and @@schema
98
+ @@validator ||= Validator.new
99
+ @@schema ||= @@validator.schema
100
+
101
+ # initialize @@logger
102
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
103
+ end
104
+
105
+ ##
106
+ # Assigns default values if values do not exist.
107
+ ##
108
+ def defaults
109
+ hash = {}
110
+ hash[:id] = nil.to_s
111
+ hash[:name] = nil.to_s
112
+ hash[:directory_name] = nil.to_s
113
+ hash[:timesteps_per_hour] = nil # unknown
114
+ hash[:number_of_not_started_simulations] = 0
115
+ hash[:number_of_started_simulations] = 0
116
+ hash[:number_of_complete_simulations] = 0
117
+ hash[:number_of_failed_simulations] = 0
118
+ hash[:timeseries_csv] = TimeseriesCSV.new.to_hash
119
+ hash[:location] = Location.new.defaults
120
+ hash[:program] = Program.new.to_hash
121
+ hash[:construction_costs] = []
122
+ hash[:reporting_periods] = []
123
+ hash[:feature_reports] = []
124
+ return hash
125
+ end
126
+
127
+ ##
128
+ # Gets the saved JSON file path.
129
+ ##
130
+ def json_path
131
+ File.join(@directory_name, 'default_scenario_report.json')
132
+ end
133
+
134
+ ##
135
+ # Gets the saved CSV file path.
136
+ ##
137
+ def csv_path
138
+ File.join(@directory_name, 'default_scenario_report.csv')
139
+ end
140
+
141
+ ##
142
+ # Saves the 'default_feature_report.json' and 'default_scenario_report.csv' files
143
+ ##
144
+ def save
145
+ hash = {}
146
+ hash[:scenario_report] = to_hash
147
+ hash[:feature_reports] = []
148
+ @feature_reports.each do |feature_report|
149
+ hash[:feature_reports] << feature_report.to_hash
150
+ end
151
+
152
+ File.open(json_path, 'w') do |f|
153
+ f.puts JSON.pretty_generate(hash)
154
+ # make sure data is written to the disk one way or the other #:nodoc:
155
+ begin
156
+ f.fsync
157
+ rescue StandardError
158
+ f.flush
159
+ end
160
+ end
161
+
162
+ # save the csv data #:nodoc:
163
+ timeseries_csv.save_data(csv_path)
164
+
165
+ return true
166
+ end
167
+
168
+ ##
169
+ # Converts to a Hash equivalent for JSON serialization.
170
+ ##
171
+ # - Exclude attributes with nil values.
172
+ # - Validate reporting_period hash properties against schema.
173
+ ##
174
+ def to_hash
175
+ result = {}
176
+ result[:id] = @id if @id
177
+ result[:name] = @name if @name
178
+ result[:directory_name] = @directory_name if @directory_name
179
+ result[:timesteps_per_hour] = @timesteps_per_hour if @timesteps_per_hour
180
+ result[:number_of_not_started_simulations] = @number_of_not_started_simulations if @number_of_not_started_simulations
181
+ result[:number_of_started_simulations] = @number_of_started_simulations if @number_of_started_simulations
182
+ result[:number_of_complete_simulations] = @number_of_complete_simulations if @number_of_complete_simulations
183
+ result[:number_of_failed_simulations] = @number_of_failed_simulations if @number_of_failed_simulations
184
+ result[:timeseries_csv] = @timeseries_csv.to_hash if @timeseries_csv
185
+ result[:location] = @location.to_hash if @location
186
+ result[:program] = @program.to_hash if @program
187
+
188
+ result[:construction_costs] = []
189
+ @construction_costs.each { |cc| result[:construction_costs] << cc.to_hash } if @construction_costs
190
+
191
+ result[:reporting_periods] = []
192
+ @reporting_periods.each { |rp| result[:reporting_periods] << rp.to_hash } if @reporting_periods
193
+
194
+ # result[:feature_reports] = []
195
+ # @feature_reports.each { |fr| result[:feature_reports] << fr.to_hash } if @feature_reports
196
+
197
+ # validate scenario_report properties against schema
198
+ if @@validator.validate(@@schema[:definitions][:ScenarioReport][:properties], result).any?
199
+ raise "scenario_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:ScenarioReport][:properties], result)}"
200
+ end
201
+
202
+ # have to use the module method because we have not yet initialized the class one
203
+ @@logger.info("Scenario name: #{@name}")
204
+
205
+ return result
206
+ end
207
+
208
+ ##
209
+ # Add feature reports to each other.
210
+ ##
211
+ # - check if a feature report have been already added.
212
+ # - check feature simulation status
213
+ # - merge timeseries_csv information
214
+ # - merge program information
215
+ # - merge construction_cost information
216
+ # - merge reporting_periods information
217
+ # - add the array of feature_reports
218
+ # - scenario report location takes the location of the first feature in the list
219
+ ##
220
+ # [parmeters:]
221
+ # +feature_report+ - _FeatureReport_ - An object of FeatureReport class.
222
+ ##
223
+ def add_feature_report(feature_report)
224
+ if @timesteps_per_hour.nil?
225
+ @timesteps_per_hour = feature_report.timesteps_per_hour
226
+ else
227
+ if feature_report.timesteps_per_hour != @timesteps_per_hour
228
+ raise "FeatureReport timesteps_per_hour = '#{feature_report.timesteps_per_hour}' does not match scenario timesteps_per_hour '#{@timesteps_per_hour}'"
229
+ end
230
+ end
231
+
232
+ # check that we have not already added this feature
233
+ id = feature_report.id
234
+ @feature_reports.each do |existing_feature_report|
235
+ if existing_feature_report.id == id
236
+ raise "FeatureReport with id = '#{id}' has already been added"
237
+ end
238
+ end
239
+
240
+ # check feature simulation status
241
+ if feature_report.simulation_status == 'Not Started'
242
+ @number_of_not_started_simulations += 1
243
+ elsif feature_report.simulation_status == 'Started'
244
+ @number_of_started_simulations += 1
245
+ elsif feature_report.simulation_status == 'Complete'
246
+ @number_of_complete_simulations += 1
247
+ elsif feature_report.simulation_status == 'Failed'
248
+ @number_of_failed_simulations += 1
249
+ else
250
+ raise "Unknown feature_report simulation_status = '#{feature_report.simulation_status}'"
251
+ end
252
+
253
+ # merge timeseries_csv information
254
+ @timeseries_csv.add_timeseries_csv(feature_report.timeseries_csv)
255
+
256
+ @timeseries_csv.run_dir_name(@directory_name)
257
+
258
+ # merge program information
259
+ @program.add_program(feature_report.program)
260
+
261
+ # merge construction_cost information
262
+ @construction_costs = ConstructionCost.merge_construction_costs(@construction_costs, feature_report.construction_costs)
263
+
264
+ # merge reporting_periods information
265
+ @reporting_periods = ReportingPeriod.merge_reporting_periods(@reporting_periods, feature_report.reporting_periods)
266
+
267
+ # add the array of feature_reports
268
+ @feature_reports << feature_report
269
+
270
+ # scenario report location takes the location of the first feature in the list
271
+ @location = feature_reports[0].location
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
@@ -0,0 +1,33 @@
1
+ # URBANopt Scenario Schema
2
+
3
+ The URBANopt Scenario Gem includes functionality for defining scenarios, running simulations, and post-processing results. An URBANopt Scenario describes a specific set of options to apply to each Feature in a FeatureFile (e.g. each GeoJSON Feature in an URBANopt GeoJSON File). User defined SimulationMapper classes translate each Feature to a SimulationDir which is a directory containing simulation input files. A ScenarioRunner is used to perform simulations for each SimulationDir. Finally, a ScenarioPostProcessor can run on a Scenario to generate scenario level results. The [URBANopt Scenario Gem Design Document](https://docs.google.com/document/d/1ExcGuHliaSvPlrYevAJTSV8XAtTQXz_KQqH3p4iQDwg/edit) describes the gem in more detail. The [URBANopt Example Project](https://github.com/urbanopt/urbanopt-example-project) demonstrates how to use the URBANopt Scenario Gem to perform a scenario analysis.
4
+
5
+ ## Reporting output units
6
+
7
+ **JSON Output Units**
8
+
9
+ - energy outputs: kbtu
10
+ - water rate outputs : GPM (gallon per minute)
11
+ - mass flow rate outputs : lbs/min
12
+ - Temperature outputs : &deg;F
13
+ - area output: sf
14
+ - measured distance output: ft
15
+ - cost outputs: $
16
+
17
+ **CSV Output Units**
18
+
19
+ | output | unit |
20
+ | ----------------------------------- | ------- |
21
+ | Electricity:Facility | kbtu |
22
+ | ElectricityProduced:Facility | kbtu |
23
+ | Gas:Facility | kbtu |
24
+ | DistrictCooling:Facility | kbtu |
25
+ | DistrictHeating:Facility | kbtu |
26
+ | District Cooling Chilled Water Rate | GPM |
27
+ | District Cooling Mass Flow Rate | lbs/min |
28
+ | District Cooling Inlet Temperature | &deg;F |
29
+ | District Cooling Outlet Temperature | &deg;F |
30
+ | District Heating Hot Water Rate | GPM |
31
+ | District Heating Mass Flow Rate | lbs/min |
32
+ | District Heating Inlet Temperature | &deg;F |
33
+ | District Heating Outlet Temperature | &deg;F |
@@ -0,0 +1,13 @@
1
+ Electricity:Facility
2
+ ElectricityProduced:Facility
3
+ Gas:Facility
4
+ DistrictCooling:Facility
5
+ DistrictHeating:Facility
6
+ District Cooling Chilled Water Rate
7
+ District Cooling Mass Flow Rate
8
+ District Cooling Inlet Temperature
9
+ District Cooling Outlet Temperature
10
+ District Heating Hot Water Rate
11
+ District Heating Mass Flow Rate
12
+ District Heating Inlet Temperature
13
+ District Heating Outlet Temperature
@@ -0,0 +1,742 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "description": "Comment describing your JSON Schema",
4
+ "type": "object",
5
+ "properties": {
6
+ "scenario_report": {
7
+ "$ref": "#/definitions/ScenarioReport"
8
+ },
9
+ "feature_reports": {
10
+ "description": "features of each data point in the scenario",
11
+ "type": "array",
12
+ "items": {
13
+ "$ref": "#/definitions/FeatureReport"
14
+ }
15
+ }
16
+ },
17
+ "required": [
18
+ "scenario_report"
19
+ ],
20
+ "additionalProperties": false,
21
+ "definitions": {
22
+ "ScenarioReport": {
23
+ "type": "object",
24
+ "properties": {
25
+ "id": {
26
+ "type": "string"
27
+ },
28
+ "name": {
29
+ "type": "string"
30
+ },
31
+ "directory_name": {
32
+ "type": "string"
33
+ },
34
+ "timesteps_per_hour": {
35
+ "$ref": "#/definitions/TimestepsPerHour"
36
+ },
37
+ "number_of_not_started_simulations": {
38
+ "type": "number"
39
+ },
40
+ "number_of_started_simulations": {
41
+ "type": "number"
42
+ },
43
+ "number_of_complete_simulations": {
44
+ "type": "number"
45
+ },
46
+ "number_of_failed_simulations": {
47
+ "type": "number"
48
+ },
49
+ "location": {
50
+ "$ref": "#/definitions/Location"
51
+ },
52
+ "timeseries_csv": {
53
+ "$ref": "#/definitions/TimeseriesCSV"
54
+ },
55
+ "program": {
56
+ "$ref": "#/definitions/Program"
57
+ },
58
+ "construction_costs": {
59
+ "$ref": "#/definitions/ConstructionCosts"
60
+ },
61
+ "reporting_periods": {
62
+ "$ref": "#/definitions/ReportingPeriods"
63
+ }
64
+ },
65
+ "required": [
66
+ "id",
67
+ "name",
68
+ "directory_name",
69
+ "timesteps_per_hour",
70
+ "number_of_not_started_simulations",
71
+ "number_of_started_simulations",
72
+ "number_of_complete_simulations",
73
+ "number_of_failed_simulations",
74
+ "program"
75
+ ],
76
+ "additionalProperties": false
77
+ },
78
+ "FeatureReport": {
79
+ "type": "object",
80
+ "properties": {
81
+ "id": {
82
+ "description": "Id refers to the id of a building/feature",
83
+ "type": "string"
84
+ },
85
+ "name": {
86
+ "description": "name refers to the name of the feature (eg. Building 1, tranformer 5)",
87
+ "type": "string"
88
+ },
89
+ "directory_name": {
90
+ "type": "string"
91
+ },
92
+ "feature_type": {
93
+ "type": "string",
94
+ "enum": [
95
+ "Building",
96
+ "District System",
97
+ "Transformer"
98
+ ]
99
+ },
100
+ "timesteps_per_hour": {
101
+ "$ref": "#/definitions/TimestepsPerHour"
102
+ },
103
+ "simulation_status": {
104
+ "type": "string",
105
+ "enum": [
106
+ "Not Started",
107
+ "Started",
108
+ "Complete",
109
+ "Failed"
110
+ ]
111
+ },
112
+ "timeseries_csv": {
113
+ "$ref": "#/definitions/TimeseriesCSV"
114
+ },
115
+ "location": {
116
+ "$ref": "#/definitions/Location"
117
+ },
118
+ "program": {
119
+ "$ref": "#/definitions/Program"
120
+ },
121
+ "design_parameters": {
122
+ "$ref": "#/definitions/DesignParameters"
123
+ },
124
+ "construction_costs": {
125
+ "$ref": "#/definitions/ConstructionCosts"
126
+ },
127
+ "reporting_periods": {
128
+ "$ref": "#/definitions/ReportingPeriods"
129
+ }
130
+ },
131
+ "required": [
132
+ "id",
133
+ "name",
134
+ "directory_name",
135
+ "feature_type",
136
+ "timesteps_per_hour",
137
+ "simulation_status"
138
+ ],
139
+ "additionalProperties": false
140
+ },
141
+ "ReportingPeriods": {
142
+ "type": "array",
143
+ "items": {
144
+ "$ref": "#/definitions/ReportingPeriod"
145
+ }
146
+ },
147
+ "ReportingPeriod": {
148
+ "description": "Non-overlapping reporting periods",
149
+ "type": "object",
150
+ "properties": {
151
+ "id": {
152
+ "description": "Id refers to the id of the reporting period. Ids of reporting periods are matched across simulations, so the same period of time gets the same id for all simulations.",
153
+ "type": "number"
154
+ },
155
+ "name": {
156
+ "description": "name refers to the name of the reporting period(eg. Annual, January)",
157
+ "type": "string"
158
+ },
159
+ "multiplier": {
160
+ "description": "Multiplier used if this reporting period is representative of mulitple periods. For example one week simulation that represents entire month.",
161
+ "type": "number",
162
+ "default": 1
163
+ },
164
+ "start_date": {
165
+ "$ref": "#/definitions/Date"
166
+ },
167
+ "end_date": {
168
+ "$ref": "#/definitions/Date"
169
+ },
170
+ "total_site_energy": {
171
+ "description": "Total energy used on site, does not include generation (kBtu)",
172
+ "type": "number"
173
+ },
174
+ "total_source_energy": {
175
+ "description": "Total source energy used, does not include generation (kBtu)",
176
+ "type": "number"
177
+ },
178
+ "net_site_energy": {
179
+ "description": "Net site energy (kBtu)",
180
+ "type": "number"
181
+ },
182
+ "net_source_energy": {
183
+ "description": "Net source energy (kBtu)",
184
+ "type": "number"
185
+ },
186
+ "net_utility_cost": {
187
+ "description": "Total utility cost for reporting period includes generation",
188
+ "type": "number"
189
+ },
190
+ "electricity": {
191
+ "description": "Sum of all electricity used, does not include electricity produced (kWh)",
192
+ "type": "number"
193
+ },
194
+ "natural_gas": {
195
+ "description": "Sum of all natural gas end uses consumption (kBtu)",
196
+ "type": "number"
197
+ },
198
+ "additional_fuel": {
199
+ "description": "Sum of all additional fuel end uses consumption (kBtu)",
200
+ "type": "number"
201
+ },
202
+ "district_cooling": {
203
+ "description": "Sum of all distric cooling end uses consumption (kBtu)",
204
+ "type": "number"
205
+ },
206
+ "district_heating": {
207
+ "description": "Sum of all distric heating end uses consumption (kBtu)",
208
+ "type": "number"
209
+ },
210
+ "water": {
211
+ "description": "Sum of all water end uses consumption (ft^3)",
212
+ "type": "number"
213
+ },
214
+ "electricity_produced": {
215
+ "description": "Sum of all electricity produced (kWh)",
216
+ "type": "number"
217
+ },
218
+ "end_uses": {
219
+ "$ref": "#/definitions/EndUses"
220
+ },
221
+ "energy_production": {
222
+ "description": "Energy produced for reporting period. Electricity reported in kWh, water in m^3, all others in kBtu.",
223
+ "type": "object",
224
+ "properties": {
225
+ "electricity_produced": {
226
+ "type": "object",
227
+ "properties": {
228
+ "photovoltaic": {
229
+ "type": "number"
230
+ }
231
+ },
232
+ "additionalProperties": false
233
+ }
234
+ },
235
+ "additionalProperties": false
236
+ },
237
+ "utility_costs": {
238
+ "type": "array",
239
+ "items": {
240
+ "$ref": "#/definitions/UtilityCost"
241
+ }
242
+ },
243
+ "comfort_result": {
244
+ "$ref": "#/definitions/ComfortResult"
245
+ }
246
+ },
247
+ "additionalProperties": false
248
+ },
249
+ "Date": {
250
+ "type": "object",
251
+ "properties": {
252
+ "month": {
253
+ "type": "integer"
254
+ },
255
+ "day_of_month": {
256
+ "type": "integer"
257
+ },
258
+ "year": {
259
+ "type": "integer"
260
+ }
261
+ },
262
+ "additionalProperties": false
263
+ },
264
+ "EndUses": {
265
+ "description": "End uses for reporting period. Does not include energy produced. Electricity reported in kWh, water in m^3, all others in kBtu.",
266
+ "type": "object",
267
+ "properties": {
268
+ "electricity": {
269
+ "$ref": "#/definitions/EndUse"
270
+ },
271
+ "natural_gas": {
272
+ "$ref": "#/definitions/EndUse"
273
+ },
274
+ "additional_fuel": {
275
+ "$ref": "#/definitions/EndUse"
276
+ },
277
+ "district_cooling": {
278
+ "$ref": "#/definitions/EndUse"
279
+ },
280
+ "district_heating": {
281
+ "$ref": "#/definitions/EndUse"
282
+ },
283
+ "water": {
284
+ "$ref": "#/definitions/EndUse"
285
+ }
286
+ },
287
+ "additionalProperties": false
288
+ },
289
+ "EndUse": {
290
+ "type": "object",
291
+ "properties": {
292
+ "heating": {
293
+ "type": "number"
294
+ },
295
+ "cooling": {
296
+ "type": "number"
297
+ },
298
+ "interior_lighting": {
299
+ "type": "number"
300
+ },
301
+ "exterior_lighting": {
302
+ "type": "number"
303
+ },
304
+ "interior_equipment": {
305
+ "type": "number"
306
+ },
307
+ "exterior_equipment": {
308
+ "type": "number"
309
+ },
310
+ "fans": {
311
+ "type": "number"
312
+ },
313
+ "pumps": {
314
+ "type": "number"
315
+ },
316
+ "heat_rejection": {
317
+ "type": "number"
318
+ },
319
+ "humidification": {
320
+ "type": "number"
321
+ },
322
+ "heat_recovery": {
323
+ "type": "number"
324
+ },
325
+ "water_systems": {
326
+ "type": "number"
327
+ },
328
+ "refrigeration": {
329
+ "type": "number"
330
+ },
331
+ "generators": {
332
+ "type": "number"
333
+ }
334
+ },
335
+ "additionalProperties": false
336
+ },
337
+ "ComfortResult": {
338
+ "type": "object",
339
+ "properties": {
340
+ "time_setpoint_not_met_during_occupied_cooling": {
341
+ "description": "(hrs)",
342
+ "type": "number"
343
+ },
344
+ "time_setpoint_not_met_during_occupied_heating": {
345
+ "description": "(hrs)",
346
+ "type": "number"
347
+ },
348
+ "time_setpoint_not_met_during_occupied_hours": {
349
+ "description": "(hrs)",
350
+ "type": "number"
351
+ }
352
+ },
353
+ "additionalProperties": false
354
+ },
355
+ "ConstructionCosts": {
356
+ "type": "array",
357
+ "items": {
358
+ "$ref": "#/definitions/ConstructionCost"
359
+ }
360
+ },
361
+ "ConstructionCost": {
362
+ "description": "Program related information, does not change in time",
363
+ "type": "object",
364
+ "properties": {
365
+ "category": {
366
+ "type": "string",
367
+ "enum": [
368
+ "Construction",
369
+ "Building",
370
+ "Space",
371
+ "ThermalZone",
372
+ "AirLoop",
373
+ "PlantLoop",
374
+ "ZoneHVAC",
375
+ "Lights",
376
+ "Luminaire",
377
+ "Equipment",
378
+ "HVACComponent",
379
+ "ZoneHVACComponent"
380
+ ]
381
+ },
382
+ "item_name": {
383
+ "description": "Name of the item being costed, e.g. the name of the exterior wall construction",
384
+ "type": "string"
385
+ },
386
+ "unit_cost": {
387
+ "description": "Cost per unit of item, e.g. cost per area of construction. This can be adjusted in post processing.",
388
+ "type": "number"
389
+ },
390
+ "cost_units": {
391
+ "description": "Unit of cost for this item",
392
+ "type": "string",
393
+ "enum": [
394
+ "CostPerEach",
395
+ "CostPerFt2",
396
+ "CostPerKW",
397
+ "CostPerCFM"
398
+ ]
399
+ },
400
+ "item_quantity": {
401
+ "description": "Amount of the item in units corresponding to cost_units",
402
+ "type": "number"
403
+ },
404
+ "total_cost": {
405
+ "description": "Total cost is unit_cost multiplied by item_quantity. Can be updated if unit_cost is changed.",
406
+ "type": "number"
407
+ }
408
+ },
409
+ "additionalProperties": false
410
+ },
411
+ "UtilityCost": {
412
+ "type": "object",
413
+ "properties": {
414
+ "fuel_type": {
415
+ "type": "string",
416
+ "enum": [
417
+ "Electricity",
418
+ "Natural Gas",
419
+ "District Cooling",
420
+ "District Heating",
421
+ "Additional Fuel",
422
+ "Water"
423
+ ]
424
+ },
425
+ "total_cost": {
426
+ "description": "($)",
427
+ "type": "number"
428
+ },
429
+ "usage_cost": {
430
+ "description": "($)",
431
+ "type": "number"
432
+ },
433
+ "demand_cost": {
434
+ "description": "($)",
435
+ "type": "number"
436
+ }
437
+ },
438
+ "additionalProperties": false
439
+ },
440
+ "Location": {
441
+ "type": "object",
442
+ "properties": {
443
+ "latitude": {
444
+ "description": "(deg)",
445
+ "type": "number"
446
+ },
447
+ "longitude": {
448
+ "description": "(deg)",
449
+ "type": "number"
450
+ },
451
+ "surface_elevation": {
452
+ "description": "The surface elevation (above NAVD88 datum) (ft).",
453
+ "type": "number"
454
+ },
455
+ "weather_filename": {
456
+ "description": "Name of EPW weather file.",
457
+ "type": "string"
458
+ }
459
+ },
460
+ "additionalProperties": false
461
+ },
462
+ "TimestepsPerHour": {
463
+ "type": "integer",
464
+ "minimum": 1,
465
+ "maximum": 60
466
+ },
467
+ "Program": {
468
+ "type": "object",
469
+ "properties": {
470
+ "site_area": {
471
+ "description": "Area of the entire site or lot (ft^2)",
472
+ "type": "number"
473
+ },
474
+ "floor_area": {
475
+ "description": "Building gross floor area (ft^2)",
476
+ "type": "number"
477
+ },
478
+ "conditioned_area": {
479
+ "description": "Building conditioned floor area (ft^2)",
480
+ "type": "number"
481
+ },
482
+ "unconditioned_area": {
483
+ "description": "Building unconditioned floor area (ft^2)",
484
+ "type": "number"
485
+ },
486
+ "footprint_area": {
487
+ "description": "Building floorprint area (ft^2)",
488
+ "type": "number"
489
+ },
490
+ "maximum_roof_height": {
491
+ "description": "Maximum height of the roof relative to surface elevation (ft)",
492
+ "type": "number"
493
+ },
494
+ "maximum_number_of_stories": {
495
+ "description": "The maximum number of building stories, sum of number of above and below ground stories.",
496
+ "type": "number"
497
+ },
498
+ "maximum_number_of_stories_above_ground": {
499
+ "description": "The maximum number of building stories above ground",
500
+ "type": "number"
501
+ },
502
+ "parking_area": {
503
+ "description": "Parking gross area (ft^2)",
504
+ "type": "number"
505
+ },
506
+ "number_of_parking_spaces": {
507
+ "description": "Number of parking spaces",
508
+ "type": "number"
509
+ },
510
+ "number_of_parking_spaces_charging": {
511
+ "description": "Number of parking spaces with electric vehicle charging",
512
+ "type": "number"
513
+ },
514
+ "parking_footprint_area": {
515
+ "description": "Parking floorprint area (ft^2)",
516
+ "type": "number"
517
+ },
518
+ "maximum_parking_height": {
519
+ "description": "Maximum height of the parking structure relative to surface elevation (ft)",
520
+ "type": "number"
521
+ },
522
+ "maximum_number_of_parking_stories": {
523
+ "description": "The maximum number of parking stories, sum of number of above and below ground stories.",
524
+ "type": "number"
525
+ },
526
+ "maximum_number_of_parking_stories_above_ground": {
527
+ "description": "The maximum number of parking stories above ground",
528
+ "type": "number"
529
+ },
530
+ "number_of_residential_units": {
531
+ "description": "Total number of residential units.",
532
+ "type": "integer"
533
+ },
534
+ "building_types": {
535
+ "type": "array",
536
+ "items": {
537
+ "$ref": "#/definitions/BuildingType"
538
+ }
539
+ },
540
+ "window_area": {
541
+ "description": "Exterior windows gross area (ft^2)",
542
+ "type": "object",
543
+ "properties": {
544
+ "north_window_area": {
545
+ "type": "number"
546
+ },
547
+ "south_window_area": {
548
+ "type": "number"
549
+ },
550
+ "east_window_area": {
551
+ "type": "number"
552
+ },
553
+ "west_window_area": {
554
+ "type": "number"
555
+ },
556
+ "total_window_area": {
557
+ "type": "number"
558
+ }
559
+ },
560
+ "required": [
561
+ "total_window_area"
562
+ ],
563
+ "additionalProperties": false
564
+ },
565
+ "wall_area": {
566
+ "description": "exterior walls gross area (ft^2)",
567
+ "type": "object",
568
+ "properties": {
569
+ "north_wall_area": {
570
+ "type": "number"
571
+ },
572
+ "south_wall_area": {
573
+ "type": "number"
574
+ },
575
+ "east_wall_area": {
576
+ "type": "number"
577
+ },
578
+ "west_wall_area": {
579
+ "type": "number"
580
+ },
581
+ "total_wall_area": {
582
+ "type": "number"
583
+ }
584
+ },
585
+ "required": [
586
+ "north_wall_area",
587
+ "south_wall_area",
588
+ "east_wall_area",
589
+ "west_wall_area",
590
+ "total_wall_area"
591
+ ],
592
+ "additionalProperties": false
593
+ },
594
+ "roof_area": {
595
+ "type": "object",
596
+ "properties": {
597
+ "equipment_roof_area": {
598
+ "type": "number"
599
+ },
600
+ "photovoltaic_roof_area": {
601
+ "type": "number"
602
+ },
603
+ "available_roof_area": {
604
+ "description": "gross roof area (ft^2)",
605
+ "type": "number"
606
+ },
607
+ "total_roof_area": {
608
+ "description": "Exterior roofs gross area (ft^2)",
609
+ "type": "number"
610
+ }
611
+ },
612
+ "required": [
613
+ "total_roof_area"
614
+ ],
615
+ "additionalProperties": false
616
+ },
617
+ "orientation": {
618
+ "description": "Rotation of longest axis from East-West,about up axis (deg)",
619
+ "type": "number"
620
+ },
621
+ "aspect_ratio": {
622
+ "description": "Ratio of longest to shortest axis",
623
+ "type": "number"
624
+ }
625
+ },
626
+ "required": [
627
+ "floor_area",
628
+ "conditioned_area",
629
+ "unconditioned_area",
630
+ "footprint_area",
631
+ "maximum_roof_height",
632
+ "number_of_residential_units",
633
+ "building_types",
634
+ "window_area",
635
+ "wall_area",
636
+ "roof_area"
637
+ ],
638
+ "additionalProperties": false
639
+ },
640
+ "BuildingType": {
641
+ "type": "object",
642
+ "properties": {
643
+ "building_type": {
644
+ "description": "Primary building space type",
645
+ "type": "string",
646
+ "enum": [
647
+ "Single-Family",
648
+ "Multifamily (2 to 4 units)",
649
+ "Multifamily (5 or more units)",
650
+ "Mobile Home",
651
+ "Vacant",
652
+ "Office",
653
+ "Laboratory",
654
+ "Nonrefrigerated warehouse",
655
+ "Food sales",
656
+ "Public order and safety",
657
+ "Outpatient health care",
658
+ "Refrigerated warehouse",
659
+ "Religious worship",
660
+ "Public assembly",
661
+ "Education",
662
+ "Food service",
663
+ "Inpatient health care",
664
+ "Nursing",
665
+ "Lodging",
666
+ "Strip shopping mall",
667
+ "Enclosed mall",
668
+ "Retail other than mall",
669
+ "Service"
670
+ ]
671
+ },
672
+ "maximum_occupancy": {
673
+ "description": "Maximum number of occupants ",
674
+ "type": "number"
675
+ },
676
+ "floor_area": {
677
+ "description": "Building gross floor area of this type (ft^2)",
678
+ "type": "number"
679
+ }
680
+ },
681
+ "required": [
682
+ "building_type",
683
+ "maximum_occupancy",
684
+ "floor_area"
685
+ ],
686
+ "additionalProperties": false
687
+ },
688
+ "DesignParameters": {
689
+ "type": "object",
690
+ "properties": {
691
+ "district_cooling_chilled_water_rate": {
692
+ "type": "number"
693
+ },
694
+ "district_cooling_mass_flow_rate": {
695
+ "type": "number"
696
+ },
697
+ "district_cooling_inlet_temperature": {
698
+ "type": "number"
699
+ },
700
+ "district_cooling_outlet_temperature": {
701
+ "type": "number"
702
+ },
703
+ "district_heating_hot_water_rate": {
704
+ "type": "number"
705
+ },
706
+ "district_heating_mass_flow_rate": {
707
+ "type": "number"
708
+ },
709
+ "district_heating_inlet_temperature": {
710
+ "type": "number"
711
+ },
712
+ "district_heating_outlet_temperature": {
713
+ "type": "number"
714
+ }
715
+ },
716
+ "additionalProperties": false
717
+ },
718
+ "TimeseriesCSV": {
719
+ "type": "object",
720
+ "properties": {
721
+ "path": {
722
+ "type": "string"
723
+ },
724
+ "first_report_datetime": {
725
+ "type": "string"
726
+ },
727
+ "column_names": {
728
+ "type": "array",
729
+ "items": {
730
+ "type": "string"
731
+ }
732
+ }
733
+ },
734
+ "required": [
735
+ "path",
736
+ "first_report_datetime",
737
+ "column_names"
738
+ ],
739
+ "additionalProperties": false
740
+ }
741
+ }
742
+ }