urbanopt-scenario 0.2.0.pre2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c30cc0b50e26c5a2800687bb0f17e4f4e9584a97
4
- data.tar.gz: e03adccb2d7d9115389194fe0cb446d34f872984
3
+ metadata.gz: 268f5db33f1444f7e4daddf2f6055b5a5c7f9f03
4
+ data.tar.gz: 8a2af9239f2433fc2ffc883e69e8748f1ba69d9b
5
5
  SHA512:
6
- metadata.gz: 4c8f5ef9d42cedf144b96d314d712f7ba78a9c54af6ec1ffeb5198eaa374e843e441f741bd1f05d9d7ee225c83ccb3b5d0edf05066b4638dcc36866f5f95da24
7
- data.tar.gz: 842b3e3d0dbbdca6622476399072a9f9c85f36e82c05a50fb1017b7dc0aefb031f558b81632102513c880bbca9b1f0e9a991c9d7ea8cc35f73d942807735486c
6
+ metadata.gz: c9110c7e58e8f9d47891f46ac2519a436ba6733e11bd4a2e4907ba65bb85c39ce635133ec1edb0fc0380dea2bd5438b432ad0cdc31c370aed76afa75d6351839
7
+ data.tar.gz: e6bb432c9ef28be6db0511da9f1a58e7fc94438b5a0655924eb9654688a9bf358909715724b234d072d5d15774dfe63f5e7f30e5cce06857628ef8ddc442ce67
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # URBANopt Scenario Gem
2
-
2
+
3
+ ## Version 0.2.0
4
+
5
+
6
+ Date Range: 01/15/20 - 03/30/20:
7
+
8
+ - Fixed [#27]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/27 ), FeatureReports are not initialized with location information.
9
+ - Fixed [#38]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/38 ), Write documentation on how to configure ScenarioRunner to run multiple OSWs in parallel
10
+ - Fixed [#42]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/42 ), Scenario Report Instantiation from Hash
11
+ - Fixed [#43]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/43 ), Add timestep column to timeseries csv or add start and end timestep to feature and scenario reports
12
+ - Fixed [#46]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/46 ), add Validator class
13
+ - Fixed [#52]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/52 ), create a save as method that takes a file name
14
+ - Fixed [#54]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/54 ), Add constraint on the versions of ruby in the gemspec file
15
+ - Fixed [#56]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/56 ), Add folder for mapper csv files
16
+ - Fixed [#58]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/58 ), post process results
17
+ - Fixed [#59]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/59 ), figure out how UrbanOpt will select tariff structure for REopt
18
+ - Fixed [#65]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/65 ), make default timeseries csv for scenario; update adding feature timeseries
19
+ - Fixed [#67]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/67 ), update vuepress version
20
+ - Fixed [#70]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/70 ), updates to Scenario Gem to Support REopt Release
21
+ - Fixed [#74]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/74 ), Update copyrights
22
+ - Fixed [#75]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/75 ), make github_api a development dependency
23
+ - Fixed [#81]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/81 ), add thermal comfort results and timestamp to reports
24
+ - Fixed [#83]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/83 ), add multiple pV
25
+ - Fixed [#88]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/88 ), add units to CSV reports
26
+ - Fixed [#89]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/89 ), created Save feature report method
27
+ - Fixed [#91]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/91 ), add total_costruction_cost to reports
28
+ - Fixed [#95]( https://github.com/urbanopt/urbanopt-scenario-gem/issues/95 ), list datapoint failures
29
+ - Fixed [#98]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/98 ), add power, net power, net energy and apparent power to timeseries results
30
+ - Fixed [#101]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/101 ), fix for unit conversion when timeseries doe not exist
31
+ - Fixed [#102]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/102 ), add opendss post_processor
32
+ - Fixed [#104]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/104 ), add power distribution results to schema and reports
33
+ - Fixed [#110]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/110 ), save transformer features CSV and JSON reports
34
+ - Fixed [#112]( https://github.com/urbanopt/urbanopt-scenario-gem/pull/112 ), added additional timeseries results to CSV reports
35
+
3
36
  ## Version 0.1.1
4
37
 
5
38
  Date Range: 10/16/19 - 01/14/20
data/Gemfile CHANGED
@@ -40,6 +40,3 @@ end
40
40
 
41
41
  # simplecov has an unnecessary dependency on native json gem, use fork that does not require this
42
42
  gem 'simplecov', github: 'NREL/simplecov'
43
-
44
- # Fix rack version temporarily to work with Ruby 2.2.4
45
- gem 'rack', '2.1.2'
@@ -174,6 +174,17 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
174
174
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Gas:Facility,#{reporting_frequency};").get
175
175
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,DistrictCooling:Facility,#{reporting_frequency};").get
176
176
  result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,DistrictHeating:Facility,#{reporting_frequency};").get
177
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Cooling:Electricity,#{reporting_frequency};").get
178
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Heating:Electricity,#{reporting_frequency};").get
179
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,InteriorLights:Electricity,#{reporting_frequency};").get
180
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,ExteriorLights:Electricity,#{reporting_frequency};").get
181
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,InteriorEquipment:Electricity,#{reporting_frequency};").get
182
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Fans:Electricity,#{reporting_frequency};").get
183
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Pumps:Electricity,#{reporting_frequency};").get
184
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,WaterSystems:Electricity,#{reporting_frequency};").get
185
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Heating:Gas,#{reporting_frequency};").get
186
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,WaterSystems:Gas,#{reporting_frequency};").get
187
+ # result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,InteriorEquipment:Gas,#{reporting_frequency};").get
177
188
 
178
189
  timeseries_data = ['District Cooling Chilled Water Rate', 'District Cooling Mass Flow Rate',
179
190
  'District Cooling Inlet Temperature', 'District Cooling Outlet Temperature',
@@ -608,6 +619,17 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
608
619
  'Electricity:Facility',
609
620
  'ElectricityProduced:Facility',
610
621
  'Gas:Facility',
622
+ 'Cooling:Electricity',
623
+ 'Heating:Electricity',
624
+ 'InteriorLights:Electricity',
625
+ 'ExteriorLights:Electricity',
626
+ 'InteriorEquipment:Electricity',
627
+ 'Fans:Electricity',
628
+ 'Pumps:Electricity',
629
+ 'WaterSystems:Electricity',
630
+ 'Heating:Gas',
631
+ 'WaterSystems:Gas',
632
+ 'InteriorEquipment:Gas',
611
633
  'DistrictCooling:Facility',
612
634
  'DistrictHeating:Facility',
613
635
  'District Cooling Chilled Water Rate',
@@ -646,7 +668,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
646
668
  total_seconds = (60 / timesteps_per_hour.to_f) * 60 # make sure timesteps_per_hour is a float in the division
647
669
  total_hours = 1 / timesteps_per_hour.to_f # make sure timesteps_per_hour is a float in the division
648
670
  # set power_conversion
649
- power_conversion = total_hours
671
+ power_conversion = total_hours # we set the power conversio to total_hours since we want to convert lWh to kW
650
672
  puts "Power Converion: to convert kWh to kW values will be divided by #{power_conversion}"
651
673
 
652
674
  # number of values in each timeseries
@@ -768,7 +790,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
768
790
  newVals[j] = (values[tsToKeepIndexes['Electricity:Facility']][j].to_f - values[tsToKeepIndexes['ElectricityProduced:Facility']][j].to_f) / power_conversion / powerFactor
769
791
  j += 1
770
792
  end
771
- new_unit = 'kW'
793
+ new_unit = 'kVA'
772
794
  elsif timeseries_name.include? 'Net Electric Energy'
773
795
  (0..n - 1).each do |j|
774
796
  newVals[j] = (values[tsToKeepIndexes['Electricity:Facility']][j].to_f - values[tsToKeepIndexes['ElectricityProduced:Facility']][j].to_f)
@@ -798,7 +820,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
798
820
  newVals[j] = values[indexValue][j].to_f / power_conversion / powerFactor
799
821
  j += 1
800
822
  end
801
- new_unit = 'kW'
823
+ new_unit = 'kVA'
802
824
  else
803
825
  # Power calculation
804
826
  (0..n - 1).each do |j|
@@ -2,8 +2,8 @@
2
2
  <schema_version>3.0</schema_version>
3
3
  <name>default_feature_reports</name>
4
4
  <uid>9ee3135a-8070-4408-bfa1-b75fecf9dd4f</uid>
5
- <version_id>607df4a0-d1ff-4c14-8d2f-93cde078dc47</version_id>
6
- <version_modified>20200308T020104Z</version_modified>
5
+ <version_id>dcf043ff-d992-4835-893d-8658a6365eb3</version_id>
6
+ <version_modified>20200329T155122Z</version_modified>
7
7
  <xml_checksum>FB304155</xml_checksum>
8
8
  <class_name>DefaultFeatureReports</class_name>
9
9
  <display_name>DefaultFeatureReports</display_name>
@@ -137,7 +137,7 @@
137
137
  <filename>measure.rb</filename>
138
138
  <filetype>rb</filetype>
139
139
  <usage_type>script</usage_type>
140
- <checksum>DC29E5E6</checksum>
140
+ <checksum>DF6AAD06</checksum>
141
141
  </file>
142
142
  </files>
143
143
  </measure>
@@ -36,6 +36,7 @@ require 'urbanopt/scenario/scenario_base'
36
36
  require 'urbanopt/scenario/scenario_csv'
37
37
  require 'urbanopt/scenario/scenario_post_processor_base'
38
38
  require 'urbanopt/scenario/scenario_post_processor_default'
39
+ require 'urbanopt/scenario/scenario_post_processor_opendss'
39
40
  require 'urbanopt/scenario/scenario_runner_base'
40
41
  require 'urbanopt/scenario/scenario_runner_osw'
41
42
  require 'urbanopt/scenario/simulation_dir_base'
@@ -107,6 +107,11 @@ module URBANopt
107
107
  #
108
108
  attr_accessor :total_storage_kw
109
109
 
110
+ ##
111
+ # _Float_ - Installed storage capacity
112
+ #
113
+ attr_accessor :total_storage_kwh
114
+
110
115
  ##
111
116
  # _Float_ - Installed generator capacity
112
117
  #
@@ -286,15 +291,15 @@ module URBANopt
286
291
  result[:solar_pv].push pv.to_hash
287
292
  end
288
293
  result[:wind] = []
289
- @wind.each do |pv|
294
+ @wind.each do |wind|
290
295
  result[:wind].push wind.to_hash
291
296
  end
292
297
  result[:generator] = []
293
- @generator.each do |pv|
298
+ @generator.each do |generator|
294
299
  result[:generator].push generator.to_hash
295
300
  end
296
301
  result[:storage] = []
297
- @storage.each do |pv|
302
+ @storage.each do |storage|
298
303
  result[:storage].push storage.to_hash
299
304
  end
300
305
  return result
@@ -33,9 +33,10 @@ require 'urbanopt/scenario/default_reports/program'
33
33
  require 'urbanopt/scenario/default_reports/location'
34
34
  require 'urbanopt/scenario/default_reports/reporting_period'
35
35
  require 'urbanopt/scenario/default_reports/timeseries_csv'
36
- require 'urbanopt/scenario/default_reports/validator'
37
36
  require 'urbanopt/scenario/default_reports/distributed_generation'
37
+ require 'urbanopt/scenario/default_reports/power_distribution'
38
38
 
39
+ require 'urbanopt/scenario/default_reports/validator'
39
40
  require 'json-schema'
40
41
 
41
42
  require 'json'
@@ -52,7 +53,7 @@ module URBANopt
52
53
  ##
53
54
  class FeatureReport
54
55
  attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
55
- :timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation # :nodoc:
56
+ :timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution # :nodoc:
56
57
  ##
57
58
  # Each FeatureReport object corresponds to a single Feature.
58
59
  ##
@@ -84,7 +85,9 @@ module URBANopt
84
85
  @reporting_periods << ReportingPeriod.new(rp)
85
86
  end
86
87
 
87
- @distributed_generation = DistributedGeneration.new(hash[:distributed_generation] || {})
88
+ @distributed_generation = DistributedGeneration.new(hash[:distributed_generation])
89
+
90
+ @power_distribution = PowerDistribution.new(hash[:power_distribution])
88
91
 
89
92
  # initialize class variables @@validator and @@schema
90
93
  @@validator ||= Validator.new
@@ -104,6 +107,8 @@ module URBANopt
104
107
  hash[:program] = {}
105
108
  hash[:construction_costs] = []
106
109
  hash[:reporting_periods] = []
110
+ hash[:distributed_generation] = {}
111
+ hash[:power_distribution] = {}
107
112
  return hash
108
113
  end
109
114
 
@@ -203,6 +208,8 @@ module URBANopt
203
208
 
204
209
  result[:distributed_generation] = @distributed_generation.to_hash if @distributed_generation
205
210
 
211
+ result[:power_distribution] = @power_distribution.to_hash if @power_distribution
212
+
206
213
  # validate feature_report properties against schema
207
214
  if @@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result).any?
208
215
  raise "feature_report properties does not match schema: #{@@validator.validate(@@schema[:definitions][:FeatureReport][:properties], result)}"
@@ -216,7 +223,7 @@ module URBANopt
216
223
  ##
217
224
  # [parameters]:
218
225
  # +file_name+ - _String_ - Assign a name to the saved feature report results file without an extension
219
- def save_feature_report(file_name = 'updated_default_feature_report')
226
+ def save_feature_report(file_name = 'default_feature_report')
220
227
  # reassign the initialize local variable @file_name to the file name input.
221
228
  @file_name = file_name
222
229
 
@@ -232,13 +239,13 @@ module URBANopt
232
239
  @timeseries_csv.path = File.join(@directory_name, 'feature_reports', file_name + '.csv')
233
240
  @timeseries_csv.save_data
234
241
 
235
- hash = {}
236
- hash[:feature_report] = to_hash
242
+ # feature_hash
243
+ feature_hash = to_hash
237
244
 
238
245
  json_name_path = File.join(@directory_name, 'feature_reports', file_name + '.json')
239
246
 
240
247
  File.open(json_name_path, 'w') do |f|
241
- f.puts JSON.pretty_generate(hash)
248
+ f.puts JSON.pretty_generate(feature_hash)
242
249
  # make sure data is written to the disk one way or the other
243
250
  begin
244
251
  f.fsync
@@ -0,0 +1,102 @@
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 'urbanopt/scenario/default_reports/validator'
33
+ require 'json-schema'
34
+
35
+ module URBANopt
36
+ module Scenario
37
+ module DefaultReports
38
+ ##
39
+ # power_distributio include eletrical power distribution systems information.
40
+ ##
41
+ class PowerDistribution
42
+ attr_accessor :under_voltage_hours, :over_voltage_hours # :nodoc:
43
+ ##
44
+ # PowerDistrinution class intialize all power_distribution attributes:
45
+ # +:under_voltage_hours+ , +:over_voltage_hours+
46
+ ##
47
+ # [parameters:]
48
+ # +hash+ - _Hash_ - A hash which may contain a deserialized power_distribution.
49
+ ##
50
+ def initialize(hash = {})
51
+ hash.delete_if { |k, v| v.nil? }
52
+ hash = defaults.merge(hash)
53
+
54
+ @under_voltage_hours = hash[:under_voltage_hours]
55
+ @over_voltage_hours = hash[:over_voltage_hours]
56
+
57
+ # initialize class variables @@validator and @@schema
58
+ @@validator ||= Validator.new
59
+ @@schema ||= @@validator.schema
60
+ end
61
+
62
+ ##
63
+ # Assigns default values if attribute values do not exist.
64
+ ##
65
+ def defaults
66
+ hash = {}
67
+ hash[:under_voltage_hours] = nil
68
+ hash[:over_voltage_hours] = nil
69
+
70
+ return hash
71
+ end
72
+
73
+ ##
74
+ # Converts to a Hash equivalent for JSON serialization.
75
+ ##
76
+ # - Exclude attributes with nil values.
77
+ # - Validate power_distribution hash properties against schema.
78
+ ##
79
+ def to_hash
80
+ result = {}
81
+ result[:under_voltage_hours] = @under_voltage_hours if @under_voltage_hours
82
+ result[:over_voltage_hours] = @over_voltage_hours if @over_voltage_hours
83
+
84
+ # validate power_distribution properties against schema
85
+ if @@validator.validate(@@schema[:definitions][:PowerDistribution][:properties], result).any?
86
+ raise "power_distribution properties does not match schema: #{@@validator.validate(@@schema[:definitions][:PowerDistribution][:properties], result)}"
87
+ end
88
+
89
+ return result
90
+ end
91
+
92
+ ##
93
+ # Merges muliple power distribution results together.
94
+ ##
95
+ # +new_costs+ - _Array_ - An array of ConstructionCost objects.
96
+ def merge_power_distribition
97
+ # method to be developed for any attributes to be aggregated or merged
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -151,7 +151,7 @@ module URBANopt
151
151
  # reassign the initialize local variable @file_name to the file name input.
152
152
  @file_name = file_name
153
153
 
154
- # save the csv data
154
+ # save the scenario reports csv and json data
155
155
  old_timeseries_path = nil
156
156
  if !@timeseries_csv.path.nil?
157
157
  old_timeseries_path = @timeseries_csv.path
@@ -184,6 +184,12 @@ module URBANopt
184
184
  else
185
185
  @timeseries_csv.path = File.join(@directory_name, file_name + '.csv')
186
186
  end
187
+
188
+ # save the feature reports csv and json data
189
+ # @feature_reports.each do |feature_report|
190
+ # feature_report.save_feature_report()
191
+ # end
192
+
187
193
  return true
188
194
  end
189
195
 
@@ -1,13 +1,24 @@
1
1
  Datetime
2
2
  Electricity:Facility
3
- ElectricityProduced:Facility
3
+ ElectricityProduced:Facility
4
4
  Gas:Facility
5
- DistrictCooling:Facility
6
- DistrictHeating:Facility
7
- District Cooling Chilled Water Rate
5
+ Cooling:Electricity
6
+ Heating:Electricity
7
+ InteriorLights:Electricity
8
+ ExteriorLights:Electricity
9
+ InteriorEquipment:Electricity
10
+ Fans:Electricity
11
+ Pumps:Electricity
12
+ WaterSystems:Electricity
13
+ Heating:Gas
14
+ WaterSystems:Gas
15
+ InteriorEquipment:Gas
16
+ DistrictCooling:Facility
17
+ DistrictHeating:Facility
18
+ District Cooling Chilled Water Rate
8
19
  District Cooling Mass Flow Rate
9
- District Cooling Inlet Temperature
10
- District Cooling Outlet Temperature
20
+ District Cooling Inlet Temperature
21
+ District Cooling Outlet Temperature
11
22
  District Heating Hot Water Rate
12
23
  District Heating Mass Flow Rate
13
24
  District Heating Inlet Temperature
@@ -213,6 +213,9 @@
213
213
  },
214
214
  "distributed_generation": {
215
215
  "$ref": "#/definitions/DistributedGeneration"
216
+ },
217
+ "power_distribution": {
218
+ "$ref": "#/definitions/PowerDistribution"
216
219
  }
217
220
  },
218
221
  "required": [
@@ -834,6 +837,17 @@
834
837
  "column_names"
835
838
  ],
836
839
  "additionalProperties": false
840
+ },
841
+ "PowerDistribution": {
842
+ "type": "object",
843
+ "properties": {
844
+ "over_voltage_hours": {
845
+ "type": "number"
846
+ },
847
+ "under_voltage_hours": {
848
+ "type": "number"
849
+ }
850
+ }
837
851
  }
838
852
  }
839
853
  }
@@ -87,7 +87,8 @@ module URBANopt
87
87
  File.readlines(scenario_csv_schema).each do |line|
88
88
  l = line.delete("\n")
89
89
  a = l.delete("\t")
90
- scenario_csv_schema_headers << a
90
+ r = a.delete("\r")
91
+ scenario_csv_schema_headers << r
91
92
  end
92
93
  return scenario_csv_schema_headers
93
94
  end
@@ -152,7 +153,11 @@ module URBANopt
152
153
  end
153
154
  else
154
155
  row.each_with_index do |value, i|
155
- @data[@column_names[i]] << value.to_f
156
+ if i == 0
157
+ @data[@column_names[i]] << value
158
+ else
159
+ @data[@column_names[i]] << value.to_f
160
+ end
156
161
  end
157
162
  end
158
163
  end
@@ -204,6 +209,7 @@ module URBANopt
204
209
  if path.nil?
205
210
  path = @path
206
211
  end
212
+
207
213
  File.open(path, 'w') do |f|
208
214
  f.puts @column_names.join(',')
209
215
  n = @data[@column_names[0]].size - 1
@@ -246,35 +252,44 @@ module URBANopt
246
252
  end
247
253
 
248
254
  # merge the column names
249
- @column_names = @column_names.concat(other.column_names).uniq
255
+ other_column_names = []
256
+ other.column_names.each do |n|
257
+ if !n[0, 4].casecmp('ZONE').zero?
258
+ other_column_names << n
259
+ end
260
+ end
261
+
262
+ @column_names = @column_names.concat(other_column_names).uniq
250
263
 
251
264
  # merge the column data
252
265
  other.column_names.each do |column_name|
253
- if !@column_names.include? column_name
254
- @column_names.push column_name
255
- end
266
+ if !column_name[0, 4].casecmp('ZONE').zero?
267
+ if !@column_names.include? column_name
268
+ @column_names.push column_name
269
+ end
256
270
 
257
- new_values = other.get_data(column_name)
271
+ new_values = other.get_data(column_name)
258
272
 
259
- if @data.nil?
260
- @data = {}
261
- end
273
+ if @data.nil?
274
+ @data = {}
275
+ end
262
276
 
263
- current_values = @data[column_name]
277
+ current_values = @data[column_name]
264
278
 
265
- if current_values
266
- if current_values.size != new_values.size
267
- raise 'Values of different sizes in add_timeseries_csv'
268
- end
269
- new_values.each_with_index do |value, i|
270
- # aggregate all columns except Datime column
271
- if column_name != 'Datetime'
272
- new_values[i] = value.to_f + current_values[i].to_f
279
+ if current_values
280
+ if current_values.size != new_values.size
281
+ raise 'Values of different sizes in add_timeseries_csv'
282
+ end
283
+ new_values.each_with_index do |value, i|
284
+ # aggregate all columns except Datime column
285
+ if column_name != 'Datetime'
286
+ new_values[i] = value.to_f + current_values[i].to_f
287
+ end
273
288
  end
289
+ @data[column_name] = new_values
290
+ else
291
+ @data[column_name] = new_values
274
292
  end
275
- @data[column_name] = new_values
276
- else
277
- @data[column_name] = new_values
278
293
  end
279
294
  end
280
295
  end
@@ -0,0 +1,276 @@
1
+ # *********************************************************************************
2
+ # URBANopt, Copyright (c) 2019-2020, Alliance for Sustainable Energy, LLC, and other
3
+ # contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # Redistributions of source code must retain the above copyright notice, this list
9
+ # of conditions and the following disclaimer.
10
+ #
11
+ # Redistributions in binary form must reproduce the above copyright notice, this
12
+ # list of conditions and the following disclaimer in the documentation and/or other
13
+ # materials provided with the distribution.
14
+ #
15
+ # Neither the name of the copyright holder nor the names of its contributors may be
16
+ # used to endorse or promote products derived from this software without specific
17
+ # prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
+ # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ # *********************************************************************************
30
+
31
+ # require 'urbanopt/scenario/scenario_post_processor_base'
32
+ require 'urbanopt/scenario/default_reports'
33
+ require 'urbanopt/scenario/default_reports/logger'
34
+
35
+ require 'csv'
36
+ require 'json'
37
+ require 'fileutils'
38
+ require 'pathname'
39
+
40
+ module URBANopt
41
+ module Scenario
42
+ class OpenDSSPostProcessor
43
+ ##
44
+ # OpenDSSPostProcessor post-processes OpenDSS results to selected OpenDSS results and integrate them in scenario and feature reports.
45
+ ##
46
+ # [parameters:]
47
+ # +scenario_report+ - _ScenarioBase_ - An object of Scenario_report class.
48
+ # +opendss_results_dir_name+ - _directory name of opendss results
49
+ def initialize(scenario_report, opendss_results_dir_name = 'opendss')
50
+ if !scenario_report.nil?
51
+ @scenario_report = scenario_report
52
+ @opendss_results_dir = File.join(@scenario_report.directory_name, opendss_results_dir_name)
53
+ else
54
+ raise 'scenario_report is not valid'
55
+ end
56
+
57
+ # hash of column_name to array of values, does not get serialized to hash
58
+ @mutex = Mutex.new
59
+
60
+ # initialize opendss data
61
+ @opendss_data = {}
62
+
63
+ # initialize feature_reports data
64
+ @feature_reports_data = {}
65
+
66
+ # initialize logger
67
+ @@logger ||= URBANopt::Scenario::DefaultReports.logger
68
+ end
69
+
70
+ # load opendss data
71
+ def load_opendss_data
72
+ # load building features data
73
+ @scenario_report.feature_reports.each do |feature_report|
74
+ # read results from opendss
75
+ opendss_csv = CSV.read(File.join(@opendss_results_dir, 'results', 'Features', feature_report.id + '.csv'))
76
+ # add results to data
77
+ @opendss_data[feature_report.id] = opendss_csv
78
+ end
79
+
80
+ ## load transformers data
81
+
82
+ # transformers results directory path
83
+ tf_results_path = File.join(@opendss_results_dir, 'results', 'Transformers')
84
+
85
+ # get transformer ids
86
+ transformer_ids = []
87
+ Dir.entries(tf_results_path.to_s).select do |f|
88
+ if !File.directory? f
89
+ fn = File.basename(f, '.csv')
90
+ transformer_ids << fn
91
+ end
92
+ end
93
+
94
+ # add transformer results to @opendss_data
95
+ transformer_ids.each do |id|
96
+ # read results from transformers
97
+ transformer_csv = CSV.read(File.join(tf_results_path, id + '.csv'))
98
+ # add results to data
99
+ @opendss_data[id] = transformer_csv
100
+ end
101
+ end
102
+
103
+ # load feature report data
104
+ def load_feature_report_data
105
+ @scenario_report.feature_reports.each do |feature_report|
106
+ # read feature results
107
+ feature_csv = CSV.read(File.join(feature_report.timeseries_csv.path))
108
+ # add results to data
109
+ @feature_reports_data[feature_report.id] = feature_csv
110
+ end
111
+ end
112
+
113
+ # load feature report data and opendss data
114
+ def load_data
115
+ # load selected opendss data
116
+ load_opendss_data
117
+ # load selected feature reports data
118
+ load_feature_report_data
119
+ end
120
+
121
+ # merge data
122
+ def merge_data(feature_report_data, opendss_data)
123
+ output = CSV.generate do |csv|
124
+ opendss_data.each_with_index do |row, i|
125
+ if row.include? 'Datetime'
126
+ row.map { |header| header.prepend('opendss_') }
127
+ end
128
+ csv << (feature_report_data[i] + row[1..-1])
129
+ end
130
+ end
131
+
132
+ return output
133
+ end
134
+
135
+ # add feature reports for transformers
136
+ def save_transformers_reports
137
+ @opendss_data.keys.each do |k|
138
+ if k.include? 'Transformer'
139
+
140
+ # create transformer directory
141
+ transformer_dir = File.join(@scenario_report.directory_name, k)
142
+ FileUtils.mkdir_p(File.join(transformer_dir, 'feature_reports'))
143
+
144
+ # write data to csv
145
+ # store under voltages and over voltages
146
+ under_voltage_hrs = 0
147
+ over_voltage_hrs = 0
148
+
149
+ transformer_csv = CSV.generate do |csv|
150
+ @opendss_data[k].each_with_index do |row, i|
151
+ csv << row
152
+
153
+ if !row[1].include? 'loading'
154
+ if row[1].to_f > 1.05
155
+ over_voltage_hrs += 1
156
+ end
157
+
158
+ if row[1].to_f < 0.95
159
+ under_voltage_hrs += 1
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ # save transformer CSV report
166
+ File.write(File.join(transformer_dir, 'feature_reports', 'default_feature_report_opendss' + '.csv'), transformer_csv)
167
+
168
+ # 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')
172
+
173
+ # assign results to transfomrer report
174
+ transformer_report.power_distribution.over_voltage_hours = over_voltage_hrs
175
+ transformer_report.power_distribution.under_voltage_hours = under_voltage_hrs
176
+
177
+ ## save transformer JSON file
178
+ # transformer_hash
179
+ transformer_hash = transformer_report.to_hash
180
+ # transformer_hash.delete_if { |k, v| v.nil? }
181
+
182
+ json_name_path = File.join(transformer_dir, 'feature_reports', 'default_feature_report_opendss' + '.json')
183
+
184
+ # save the json file
185
+ File.open(json_name_path, 'w') do |f|
186
+ f.puts JSON.pretty_generate(transformer_hash)
187
+ # make sure data is written to the disk one way or the other
188
+ begin
189
+ f.fsync
190
+ rescue StandardError
191
+ f.flush
192
+ end
193
+ end
194
+
195
+ # add transformers reports to scenario_report
196
+ @scenario_report.feature_reports << transformer_report
197
+
198
+ end
199
+ end
200
+ end
201
+
202
+ ##
203
+ # Save csv report method
204
+ ##
205
+ # [parameters:]
206
+ # +feature_report+ - _feature report object_ - An onject of the feature report
207
+ # +updated_feature_report_csv+ - _CSV_ - An updated feature report csv
208
+ # +file_name+ - _String_ - Assigned name to save the file with no extension
209
+ def save_csv(feature_report, updated_feature_report_csv, file_name = 'default_feature_report')
210
+ File.write(File.join(feature_report.directory_name, 'feature_reports', "#{file_name}.csv"), updated_feature_report_csv)
211
+ end
212
+
213
+ ##
214
+ # create opendss json report results
215
+ ##
216
+ # [parameters:]
217
+ # +feature_report+ - _feature report object_ - An onject of the feature report
218
+ def add_summary_results(feature_report)
219
+ under_voltage_hrs = 0
220
+ over_voltage_hrs = 0
221
+
222
+ id = feature_report.id
223
+ @opendss_data[id].each_with_index do |row, i|
224
+ if !row[1].include? 'voltage'
225
+
226
+ if row[1].to_f > 1.05
227
+ over_voltage_hrs += 1
228
+ end
229
+
230
+ if row[1].to_f < 0.95
231
+ under_voltage_hrs += 1
232
+ end
233
+
234
+ end
235
+ end
236
+
237
+ # assign results to feature report
238
+ feature_report.power_distribution.over_voltage_hours = over_voltage_hrs
239
+ feature_report.power_distribution.under_voltage_hours = under_voltage_hrs
240
+
241
+ return feature_report
242
+ end
243
+
244
+ ##
245
+ # run opendss post_processor
246
+ ##
247
+ def run
248
+ @scenario_report.feature_reports.each do |feature_report|
249
+ # load data
250
+ load_data
251
+
252
+ # puts " @opendss data = #{@opendss_data}"
253
+
254
+ # get summary results
255
+ add_summary_results(feature_report)
256
+
257
+ # merge csv data
258
+ id = feature_report.id
259
+ updated_feature_csv = merge_data(@feature_reports_data[id], @opendss_data[id])
260
+
261
+ # save fetaure reports
262
+ feature_report.save_feature_report('default_feature_report_opendss')
263
+
264
+ # resave updated csv report
265
+ save_csv(feature_report, updated_feature_csv, 'default_feature_report_opendss')
266
+ end
267
+
268
+ # add transformer reports
269
+ save_transformers_reports
270
+
271
+ # save the updated scenario reports
272
+ @scenario_report.save(file_name = 'scenario_report_opendss')
273
+ end
274
+ end
275
+ end
276
+ end
@@ -30,6 +30,6 @@
30
30
 
31
31
  module URBANopt
32
32
  module Scenario
33
- VERSION = '0.2.0.pre2'.freeze
33
+ VERSION = '0.2.0'.freeze
34
34
  end
35
35
  end
@@ -24,17 +24,17 @@ Gem::Specification.new do |spec|
24
24
  spec.required_ruby_version = '~> 2.2.4'
25
25
 
26
26
  spec.add_development_dependency 'bundler', '~> 1.14'
27
- spec.add_development_dependency 'rake', '12.3.1'
28
- spec.add_development_dependency 'rspec', '3.7.0'
29
27
  spec.add_development_dependency 'github_api', '~> 0.18.0'
30
- # Fix rack version temporarily to work with Ruby 2.2.4
31
- spec.add_development_dependency 'rack', '2.1.2'
28
+ spec.add_development_dependency 'rake', '~> 12.3'
29
+ spec.add_development_dependency 'rspec', '~> 3.7'
32
30
 
33
31
  spec.add_dependency 'json-schema'
34
32
  spec.add_dependency 'json_pure'
35
33
  spec.add_dependency 'openstudio-model-articulation', '~> 0.1.1'
36
- spec.add_dependency 'urbanopt-core', '~> 0.1.0'
34
+ spec.add_dependency 'urbanopt-core', '~> 0.2.0'
37
35
 
38
36
  # lock the version of these dependencies due to using older version of Ruby.
39
37
  spec.add_dependency 'public_suffix', '3.1.1'
38
+ spec.add_development_dependency 'rack', '2.1.2'
39
+
40
40
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: urbanopt-scenario
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.pre2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rawad El Kontar
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-03-16 00:00:00.000000000 Z
12
+ date: 2020-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -26,61 +26,47 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.14'
28
28
  - !ruby/object:Gem::Dependency
29
- name: rake
30
- requirement: !ruby/object:Gem::Requirement
31
- requirements:
32
- - - '='
33
- - !ruby/object:Gem::Version
34
- version: 12.3.1
35
- type: :development
36
- prerelease: false
37
- version_requirements: !ruby/object:Gem::Requirement
38
- requirements:
39
- - - '='
40
- - !ruby/object:Gem::Version
41
- version: 12.3.1
42
- - !ruby/object:Gem::Dependency
43
- name: rspec
29
+ name: github_api
44
30
  requirement: !ruby/object:Gem::Requirement
45
31
  requirements:
46
- - - '='
32
+ - - "~>"
47
33
  - !ruby/object:Gem::Version
48
- version: 3.7.0
34
+ version: 0.18.0
49
35
  type: :development
50
36
  prerelease: false
51
37
  version_requirements: !ruby/object:Gem::Requirement
52
38
  requirements:
53
- - - '='
39
+ - - "~>"
54
40
  - !ruby/object:Gem::Version
55
- version: 3.7.0
41
+ version: 0.18.0
56
42
  - !ruby/object:Gem::Dependency
57
- name: github_api
43
+ name: rake
58
44
  requirement: !ruby/object:Gem::Requirement
59
45
  requirements:
60
46
  - - "~>"
61
47
  - !ruby/object:Gem::Version
62
- version: 0.18.0
48
+ version: '12.3'
63
49
  type: :development
64
50
  prerelease: false
65
51
  version_requirements: !ruby/object:Gem::Requirement
66
52
  requirements:
67
53
  - - "~>"
68
54
  - !ruby/object:Gem::Version
69
- version: 0.18.0
55
+ version: '12.3'
70
56
  - !ruby/object:Gem::Dependency
71
- name: rack
57
+ name: rspec
72
58
  requirement: !ruby/object:Gem::Requirement
73
59
  requirements:
74
- - - '='
60
+ - - "~>"
75
61
  - !ruby/object:Gem::Version
76
- version: 2.1.2
62
+ version: '3.7'
77
63
  type: :development
78
64
  prerelease: false
79
65
  version_requirements: !ruby/object:Gem::Requirement
80
66
  requirements:
81
- - - '='
67
+ - - "~>"
82
68
  - !ruby/object:Gem::Version
83
- version: 2.1.2
69
+ version: '3.7'
84
70
  - !ruby/object:Gem::Dependency
85
71
  name: json-schema
86
72
  requirement: !ruby/object:Gem::Requirement
@@ -129,14 +115,14 @@ dependencies:
129
115
  requirements:
130
116
  - - "~>"
131
117
  - !ruby/object:Gem::Version
132
- version: 0.1.0
118
+ version: 0.2.0
133
119
  type: :runtime
134
120
  prerelease: false
135
121
  version_requirements: !ruby/object:Gem::Requirement
136
122
  requirements:
137
123
  - - "~>"
138
124
  - !ruby/object:Gem::Version
139
- version: 0.1.0
125
+ version: 0.2.0
140
126
  - !ruby/object:Gem::Dependency
141
127
  name: public_suffix
142
128
  requirement: !ruby/object:Gem::Requirement
@@ -151,6 +137,20 @@ dependencies:
151
137
  - - '='
152
138
  - !ruby/object:Gem::Version
153
139
  version: 3.1.1
140
+ - !ruby/object:Gem::Dependency
141
+ name: rack
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '='
145
+ - !ruby/object:Gem::Version
146
+ version: 2.1.2
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '='
152
+ - !ruby/object:Gem::Version
153
+ version: 2.1.2
154
154
  description: Library to export data point OSW files from URBANopt Scenario CSV
155
155
  email:
156
156
  - rawad.elkontar@nrel.gov
@@ -214,6 +214,7 @@ files:
214
214
  - lib/urbanopt/scenario/default_reports/generator.rb
215
215
  - lib/urbanopt/scenario/default_reports/location.rb
216
216
  - lib/urbanopt/scenario/default_reports/logger.rb
217
+ - lib/urbanopt/scenario/default_reports/power_distribution.rb
217
218
  - lib/urbanopt/scenario/default_reports/program.rb
218
219
  - lib/urbanopt/scenario/default_reports/reporting_period.rb
219
220
  - lib/urbanopt/scenario/default_reports/scenario_report.rb
@@ -232,6 +233,7 @@ files:
232
233
  - lib/urbanopt/scenario/scenario_datapoint_base.rb
233
234
  - lib/urbanopt/scenario/scenario_post_processor_base.rb
234
235
  - lib/urbanopt/scenario/scenario_post_processor_default.rb
236
+ - lib/urbanopt/scenario/scenario_post_processor_opendss.rb
235
237
  - lib/urbanopt/scenario/scenario_runner_base.rb
236
238
  - lib/urbanopt/scenario/scenario_runner_osw.rb
237
239
  - lib/urbanopt/scenario/simulation_dir_base.rb
@@ -253,9 +255,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
253
255
  version: 2.2.4
254
256
  required_rubygems_version: !ruby/object:Gem::Requirement
255
257
  requirements:
256
- - - ">"
258
+ - - ">="
257
259
  - !ruby/object:Gem::Version
258
- version: 1.3.1
260
+ version: '0'
259
261
  requirements: []
260
262
  rubyforge_project:
261
263
  rubygems_version: 2.4.5.1