urbanopt-scenario 0.2.0.pre2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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